summaryrefslogtreecommitdiffstats
path: root/khexedit/lib/kplainbuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khexedit/lib/kplainbuffer.cpp')
-rw-r--r--khexedit/lib/kplainbuffer.cpp344
1 files changed, 344 insertions, 0 deletions
diff --git a/khexedit/lib/kplainbuffer.cpp b/khexedit/lib/kplainbuffer.cpp
new file mode 100644
index 0000000..63c1db7
--- /dev/null
+++ b/khexedit/lib/kplainbuffer.cpp
@@ -0,0 +1,344 @@
+/***************************************************************************
+ kplainbuffer.cpp - description
+ -------------------
+ begin : Mit Jun 03 2003
+ copyright : (C) 2003 by Friedrich W. H. Kossebau
+ email : Friedrich.W.H@Kossebau.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+//#include <kdebug.h>
+// c specific
+#include <string.h>
+#include <stdlib.h>
+// lib specific
+#include "kplainbuffer.h"
+
+
+static const unsigned int MinChunkSize = 512;
+static const unsigned int MaxChunkSize = 1024*10; // TODO: get max. memory page size
+
+// TODO: think about realloc & Co.
+using namespace KHE;
+
+KPlainBuffer::KPlainBuffer( char *D, unsigned int S, int RS, bool KM )
+ : Data( D ),
+ Size( S ),
+ RawSize( RS<(int)S?S:RS ),
+ MaxSize( -1 ),
+ KeepsMemory( KM ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::KPlainBuffer( const char *D, unsigned int S )
+ : Data( (char *)D ),
+ Size( S ),
+ RawSize( S ),
+ MaxSize( -1 ),
+ KeepsMemory( true ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::KPlainBuffer( int S, int MS )
+ : Data( S?new char[S]:0 ),
+ Size( S ),
+ RawSize( S ),
+ MaxSize( MS ),
+ KeepsMemory( false ),
+ ReadOnly( true ),
+ Modified( false )
+{
+}
+
+KPlainBuffer::~KPlainBuffer()
+{
+}
+
+
+
+int KPlainBuffer::insert( int Pos, const char* D, int Length )
+{
+ // check all parameters
+ if( Length == 0 )
+ return 0;
+ //kdDebug() << QString("before: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl;
+ // correct for appending
+ if( Pos > (int)Size )
+ Pos = Size;
+
+ Length = addSize( Length, Pos, true );
+
+ // copy new data to its place
+ memcpy( &Data[Pos], D, Length );
+
+ //kdDebug() << QString("after: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl;
+
+ Modified = true;
+ return Length;
+}
+
+
+int KPlainBuffer::remove( KSection Remove )
+{
+ if( Remove.startsBehind(Size-1) || Remove.width() == 0 )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+
+ unsigned int BehindRemovePos = Remove.end()+1;
+ // move right data behind the input range
+ memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // set new values
+ Size -= Remove.width();
+
+ Modified = true;
+ return Remove.width();
+}
+
+
+unsigned int KPlainBuffer::replace( KSection Remove, const char* D, unsigned int InputLength )
+{
+ // check all parameters
+ if( Remove.start() >= (int)Size || (Remove.width()==0 && InputLength==0) )
+ return 0;
+
+ Remove.restrictEndTo( Size-1 );
+
+ int SizeDiff = InputLength - Remove.width();
+ unsigned int NewSize = Size + SizeDiff;
+ // check if buffer does not get to big TODO: make algo simplier and less if else
+ if( MaxSize != -1 && (int)NewSize > MaxSize)
+ {
+ if( (int)Size == MaxSize )
+ return 0;
+ InputLength -= NewSize - MaxSize;
+ NewSize = MaxSize;
+ }
+ else if( KeepsMemory && NewSize > RawSize )
+ {
+ if( Size == RawSize )
+ return 0;
+ InputLength -= NewSize - RawSize;
+ NewSize = RawSize;
+ }
+
+ int BehindInsertPos = Remove.start() + InputLength;
+ int BehindRemovePos = Remove.end()+1;
+
+ // raw array not big enough?
+ if( RawSize < NewSize )
+ {
+ // create new buffer
+ char *NewData = new char[NewSize];
+ if( NewData == 0 )
+ return 0;
+
+ // move old data to its (new) places
+ memcpy( NewData, Data, Remove.start() );
+ memcpy( &NewData[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // remove old
+ delete [] Data;
+ // set new values
+ Data = NewData;
+ RawSize = NewSize;
+ }
+ else
+ // move old data to its (new) places
+ memmove( &Data[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos );
+
+ // copy new data to its place
+ memcpy( &Data[Remove.start()], D, InputLength );
+
+ // set new values
+ Size = NewSize;
+
+ Modified = true;
+ return InputLength;
+}
+
+
+int KPlainBuffer::move( int DestPos, KSection SourceSection )
+{
+ // check all parameters
+ if( SourceSection.start() >= (int)Size || SourceSection.width() == 0
+ || DestPos > (int)Size || SourceSection.start() == DestPos )
+ return SourceSection.start();
+
+ SourceSection.restrictEndTo( Size-1 );
+ bool ToRight = DestPos > SourceSection.start();
+ int MovedLength = SourceSection.width();
+ int DisplacedLength = ToRight ? DestPos - SourceSection.end()-1 : SourceSection.start() - DestPos;
+
+ // find out section that is smaller
+ int SmallPartLength, LargePartLength, SmallPartStart, LargePartStart, SmallPartDest, LargePartDest;
+ // moving part is smaller?
+ if( MovedLength < DisplacedLength )
+ {
+ SmallPartStart = SourceSection.start();
+ SmallPartLength = MovedLength;
+ LargePartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ SmallPartDest = DestPos - MovedLength;
+ LargePartStart = SourceSection.end()+1;
+ LargePartDest = SourceSection.start();
+ }
+ else
+ {
+ SmallPartDest = DestPos;
+ LargePartStart = DestPos;
+ LargePartDest = DestPos + MovedLength;
+ }
+ }
+ else
+ {
+ LargePartStart = SourceSection.start();
+ LargePartLength = MovedLength;
+ SmallPartLength = DisplacedLength;
+ // moving part moves right?
+ if( ToRight )
+ {
+ LargePartDest = DestPos - MovedLength;
+ SmallPartStart = SourceSection.end()+1;
+ SmallPartDest = SourceSection.start();
+ }
+ else
+ {
+ LargePartDest = DestPos;
+ SmallPartStart = DestPos;
+ SmallPartDest = DestPos + MovedLength;
+ }
+ }
+
+ // copy smaller part to tempbuffer
+ char *Temp = new char[SmallPartLength];
+ memcpy( Temp, &Data[SmallPartStart], SmallPartLength );
+
+ // move the larger part
+ memmove( &Data[LargePartDest], &Data[LargePartStart], LargePartLength );
+
+ // copy smaller part to its new dest
+ memcpy( &Data[SmallPartDest], Temp, SmallPartLength );
+ delete [] Temp;
+
+ Modified = true;
+ return MovedLength < DisplacedLength ? SmallPartDest : LargePartDest;
+}
+
+
+int KPlainBuffer::fill( const char FChar, int FillLength, unsigned int Pos )
+{
+ // nothing to fill
+ if( Pos >= Size )
+ return 0;
+
+ int LengthToEnd = Size - Pos;
+
+ if( FillLength < 0 )
+ FillLength = LengthToEnd;
+ else if( FillLength > LengthToEnd )
+ FillLength = addSize( FillLength, Pos, false );
+
+ memset( &Data[Pos], FChar, FillLength );
+ Modified = true;
+ return FillLength;
+}
+
+
+int KPlainBuffer::find( const char* SearchString, int Length, KSection Section ) const
+{
+ Section.restrictEndTo( Size-1 );
+
+ for( int i = Section.start(); i <= Section.end(); ++i )
+ {
+ int Result;
+// if( IgnoreCase )
+// result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() );
+// else
+ Result = memcmp( &Data[i], SearchString, Length );
+ // found?
+ if( Result == 0 )
+ return i;
+ }
+ return -1;
+}
+
+int KPlainBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
+
+
+int KPlainBuffer::addSize( int AddSize, int SplitPos, bool SaveUpperPart )
+{
+ unsigned int NewSize = Size + AddSize;
+ // check if buffer does not get too big
+ if( MaxSize != -1 && (int)NewSize > MaxSize )
+ {
+ if( (int)Size == MaxSize )
+ return 0;
+ NewSize = MaxSize;
+ AddSize = NewSize - Size;
+ }
+ else if( KeepsMemory && NewSize > RawSize )
+ {
+ if( Size == RawSize )
+ return 0;
+ NewSize = RawSize;
+ AddSize = NewSize - Size;
+ }
+
+ int BehindSplitPos = SplitPos + AddSize;
+ // raw array not big enough?
+ if( RawSize < NewSize )
+ {
+ // get new raw size
+ unsigned int ChunkSize = MinChunkSize;
+ // find chunk size where newsize fits into
+ while( ChunkSize < NewSize )
+ ChunkSize <<= 1;
+ // limit to max size
+ if( ChunkSize > MaxChunkSize )
+ ChunkSize = MaxChunkSize;
+ // find add size
+ unsigned int NewRawSize = ChunkSize;
+ while( NewRawSize<NewSize )
+ NewRawSize += ChunkSize;
+ // create new buffer
+ char *NewData = new char[NewRawSize];
+
+ // move old data to its (new) places
+ memcpy( NewData, Data, SplitPos );
+ if( SaveUpperPart )
+ memcpy( &NewData[BehindSplitPos], &Data[SplitPos], Size-SplitPos );
+
+ // remove old
+ delete [] Data;
+ // set new values
+ Data = NewData;
+ RawSize = NewRawSize;
+ }
+ // old buffer kept
+ else
+ {
+ if( SaveUpperPart )
+ // move old data to its (new) places
+ memmove( &Data[BehindSplitPos], &Data[SplitPos], Size-SplitPos );
+ }
+
+ // set new values
+ Size = NewSize;
+
+ return AddSize;
+}