You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeutils/khexedit/lib/kfixedsizebuffer.cpp

273 lines
7.6 KiB

/***************************************************************************
kfixedsizebuffer.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>
// lib specific
#include "kfixedsizebuffer.h"
using namespace KHE;
KFixedSizeBuffer::KFixedSizeBuffer( char *D, unsigned int S, char FUC )
: Data( D ),
Size( S ),
FillUpChar( FUC ),
ReadOnly( true ),
Modified( false ),
AutoDelete( false )
{
}
KFixedSizeBuffer::KFixedSizeBuffer( unsigned int S, char FUC )
: Data( new char[S] ),
Size( S ),
FillUpChar( FUC ),
ReadOnly( false ),
Modified( false ),
AutoDelete( true )
{
reset( 0, S );
}
KFixedSizeBuffer::~KFixedSizeBuffer()
{
if( AutoDelete )
delete [] Data;
}
int KFixedSizeBuffer::insert( int Pos, const char* D, int InputLength )
{
// check all parameters
if( Pos >= (int)Size || InputLength == 0 )
return 0;
if( Pos + InputLength > (int)Size )
InputLength = Size - Pos;
unsigned int BehindInsertPos = Pos + InputLength;
// fmove right data behind the input range
memmove( &Data[BehindInsertPos], &Data[Pos], Size-BehindInsertPos );
// insert input
memcpy( &Data[Pos], D, InputLength );
Modified = true;
return InputLength;
}
int KFixedSizeBuffer::remove( KSection Remove )
{
if( Remove.start() >= (int)Size || Remove.width() == 0 )
return 0;
Remove.restrictEndTo( Size-1 );
int RemoveLength = Remove.width();
int BehindRemovePos = Remove.end()+1;;
// fmove right data behind the input range
memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos );
// clear freed space
reset( Size-RemoveLength, RemoveLength );
Modified = true;
return RemoveLength;
}
unsigned int KFixedSizeBuffer::replace( KSection Remove, const char* D, unsigned int InputLength )
{
// check all parameters
if( Remove.startsBehind( Size-1 ) || (Remove.width()==0 && InputLength==0) )
return 0;
Remove.restrictEndTo( Size-1 );
if( Remove.start() + InputLength > Size )
InputLength = Size - Remove.start();
int SizeDiff = InputLength - Remove.width();
// is input longer than removed?
if( SizeDiff > 0 )
{
unsigned int BehindInsertPos = Remove.start() + InputLength;
// fmove right data behind the input range
memmove( &Data[BehindInsertPos], &Data[Remove.end()+1], Size-BehindInsertPos );
}
// is input smaller than removed?
else if( SizeDiff < 0 )
{
unsigned int BehindRemovePos = Remove.end()+1;
// fmove right data behind the input range
memmove( &Data[Remove.start()+InputLength], &Data[BehindRemovePos], Size-BehindRemovePos );
// clear freed space
reset( Size+SizeDiff, -SizeDiff );
}
// insert input
memcpy( &Data[Remove.start()], D, InputLength );
Modified = true;
return InputLength;
}
int KFixedSizeBuffer::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 KFixedSizeBuffer::fill( const char FChar, int FillLength, unsigned int Pos )
{
// nothing to fill
if( Pos >= Size )
return 0;
unsigned int LengthToEnd = Size - Pos;
if( FillLength < 0 || FillLength > (int)LengthToEnd )
FillLength = LengthToEnd;
memset( &Data[Pos], FChar, FillLength );
Modified = true;
return FillLength;
}
int KFixedSizeBuffer::compare( const KDataBuffer &Other, KSection OtherRange, unsigned int Pos )
{
//kdDebug() << TQString("Pos: %1, OtherRange: (%3/%4)" ).arg(Pos).arg(OtherRange.start()).arg(OtherRange.end())
// << endl;
// test other values
if( OtherRange.startsBehind(Other.size()-1) )
return 1;
// check own values
if( Pos >= Size )
return -1;
int ValueByLength = 0; // default: equal
KSection Range( Pos, OtherRange.width(), true );
int Last = Other.size()-1;
//
if( OtherRange.endsBehind(Last) )
{
// make shorter
OtherRange.setEnd( Last );
if( OtherRange.width() < Range.width() )
ValueByLength = 1;
}
Last = Size-1;
if( Range.endsBehind(Last) )
{
// make shorter
Range.setEnd( Last );
if( OtherRange.width() > Range.width() )
ValueByLength = -1;
}
//kdDebug()
// << TQString( "Range: (%1/%2), OtherRange: (%3/%4)" ).arg(Range.start()).arg(Range.end()).arg(OtherRange.start()).arg(OtherRange.end())
// << endl;
int oi = OtherRange.start();
for( int i=Range.start(); i<=Range.end(); ++i,++oi )
{
char OD = Other.datum(oi);
char D = Data[i];
//kdDebug() << TQString("%1==%2").arg((int)D).arg((int)OD) << endl;
if( OD == D )
continue;
return OD < D ? 1 : -1;
}
return ValueByLength;
}
int KFixedSizeBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const { return 0; }
int KFixedSizeBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; }
void KFixedSizeBuffer::reset( unsigned int Pos, unsigned int Length )
{
memset( &Data[Pos], FillUpChar, Length );
}