/* * @(#) bytearr.cpp - Void and byte arrays class library (source). * (c) 1998 Ivan Maidanski http://ivmai.chat.ru * Freeware class library source. All rights reserved. ** * Language: ISO/ANSI C++ * Tested with: Microsoft Visual C++ (R) v4.2, Watcom C++ 16/32 v11.0 * Last modified: 1998-09-07 00:55:00 GMT+04:00 */ #include "bytearr.h" // library header #include // realloc() #include // memmove(), memset() // macros declaration section (all macros may be overriden) #ifndef ARRAYS_MIN_EXTRA // minimum resized array extra size (in bytes) #define ARRAYS_MIN_EXTRA 16 #endif #ifndef ARRAYS_MAX_EXTRA // maximum resized array extra size (in bytes) #define ARRAYS_MAX_EXTRA 4096 #endif #ifndef ARRAYS_EXTRA_RATIO // ratio between array required and extra sizes #define ARRAYS_EXTRA_RATIO 8 #endif #ifndef ARRAYS_AUTO_SHRINK // array auto-shrinking enable/disable toggler #define ARRAYS_AUTO_SHRINK 0 #endif // user-defined macros validity checkers section #if ARRAYS_MIN_EXTRA<0 #error ARRAYS_MIN_EXTRA must be non-negative! #endif #if ARRAYS_MAX_EXTRASrcOffset+CopySize || SrcOffset+CopySize>Array.SizeVal) throw TBadIndexError(); #endif if (SizeValSizeVal) if (NewCount<=NewSize) return NewSize; else throw TOutOfMemoryError(); #if ARRAYS_AUTO_SHRINK else if (NewSizeOffset+RepCount || Offset+RepCount>SizeVal) throw TBadIndexError(); #endif memset((void *)((char *)Ptr+Offset),Ch,RepCount); return *this; } TVoidArray &TVoidArray::CopyAt(unsigned Offset, const TVoidArray &Array, unsigned SrcOffset, unsigned CopySize) { #if ARRAYS_CHECK_INDEX if (Offset>Offset+CopySize || Offset+CopySize>SizeVal || SrcOffset>SrcOffset+CopySize || SrcOffset+CopySize>Array.SizeVal) throw TBadIndexError(); #endif if (this!=&Array || Offset!=SrcOffset) memmove((void *)((char *)Ptr+Offset), (const void *)((const char *)Array.Ptr+SrcOffset),CopySize); return *this; } TVoidArray &TVoidArray::CopyAt(unsigned Offset, const void *PData, unsigned CopySize) { #if ARRAYS_CHECK_INDEX if (Offset>Offset+CopySize || Offset+CopySize>SizeVal || !PData && CopySize) throw TBadIndexError(); #endif if ((const void *)((const char *)Ptr+Offset)!=PData) memmove((void *)((char *)Ptr+Offset),PData,CopySize); return *this; } void *TVoidArray::CopyAt(void *PDestData, unsigned SrcOffset, unsigned CopySize) const { #if ARRAYS_CHECK_INDEX if (!PDestData && CopySize || SrcOffset>SrcOffset+CopySize || SrcOffset+CopySize>SizeVal) throw TBadIndexError(); #endif if (PDestData!=(void *)((char *)Ptr+SrcOffset)) memmove(PDestData,(const void *)((const char *)Ptr+SrcOffset),CopySize); return PDestData; } TVoidArray &TVoidArray::SwapAt(unsigned OffsetA, TVoidArray &ArrayB, unsigned OffsetB, unsigned SwapSize) { #if ARRAYS_CHECK_INDEX if (OffsetA>OffsetA+SwapSize || OffsetA+SwapSize>SizeVal || OffsetB>OffsetB+SwapSize || OffsetB+SwapSize>ArrayB.SizeVal) throw TBadIndexError(); #endif char TempCh; char *PChA=(char *)Ptr+OffsetA; char *PChB=(char *)ArrayB.Ptr+OffsetB; if (PChA!=PChB) while (SwapSize--) { TempCh=*PChA; *PChA++=*PChB; *PChB++=TempCh; } return *this; } TVoidArray &TVoidArray::SwapAt(unsigned OffsetA, void *PDataB, unsigned SwapSize) { #if ARRAYS_CHECK_INDEX if (OffsetA>OffsetA+SwapSize || OffsetA+SwapSize>SizeVal || !PDataB && SwapSize) throw TBadIndexError(); #endif char TempCh; char *PChA=(char *)Ptr+OffsetA; char *PChB=(char *)PDataB; if (PChA!=PChB) while (SwapSize--) { TempCh=*PChA; *PChA++=*PChB; *PChB++=TempCh; } return *this; } TByteArray::TByteArray(unsigned InitCount) : Cnt(0) { TVoidArray::Size(CalcNewSize(InitCount)); TVoidArray::SetAt(0,'\0',InitCount); Cnt=InitCount; } TByteArray::TByteArray(unsigned char Byte, unsigned InitCount) : Cnt(0) { TVoidArray::Size(CalcNewSize(InitCount)); TVoidArray::SetAt(0,(char)Byte,InitCount); Cnt=InitCount; } TByteArray::TByteArray(const unsigned char *PBytes, unsigned InitCount) : Cnt(0) { TVoidArray::Size(CalcNewSize(InitCount)); TVoidArray::CopyAt(0,(const void *)PBytes,InitCount); Cnt=InitCount; } TByteArray::TByteArray(const TByteArray &Array) : Cnt(0) { TVoidArray::Size(CalcNewSize(Array.Cnt)); TVoidArray::CopyAt(0,Array,0,Array.Cnt); Cnt=Array.Cnt; } TByteArray::TByteArray(const TByteArray &Array, unsigned SrcIndex, unsigned InitCount) : Cnt(0) { #if ARRAYS_CHECK_INDEX if (SrcIndex+InitCount>Array.Cnt) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(InitCount)); TVoidArray::CopyAt(0,Array,SrcIndex,InitCount); Cnt=InitCount; } TByteArray &TByteArray::operator=(const TByteArray &Array) { TVoidArray::Size(Array.TVoidArray::Size()); TVoidArray::CopyAt(0,Array,0,Cnt=Array.Cnt); return *this; } TByteArray &TByteArray::Copy(const unsigned char *PBytes, unsigned CopyCount) { #if ARRAYS_CHECK_INDEX if (!PBytes && CopyCount) throw TBadIndexError(); #endif if (CntSrcIndex+CopyCount || SrcIndex+CopyCount>Array.Cnt) throw TBadIndexError(); #endif if (CntCnt) { TVoidArray::Size(CalcNewSize(Index)); TVoidArray::SetAt(Cnt,'\0',Index-Cnt); Cnt=Index; } } unsigned TByteArray::IndexOf(const unsigned char &RByte) const { unsigned Index=(unsigned)(&RByte- (const unsigned char *)TVoidArray::GetData()); if (Index>=Cnt || (const unsigned char *)TVoidArray::GetData()+Index!=&RByte) throw TBadIndexError(); return Index; } const unsigned char &TByteArray::ElementAtEnd(unsigned Offset) const { #if ARRAYS_CHECK_INDEX if (Offset>=Cnt) throw TBadIndexError(); #endif return *((const unsigned char *)TVoidArray::GetData()+ (Cnt-Offset-(unsigned)1)); } unsigned char &TByteArray::ElementAtEnd(unsigned Offset) { #if ARRAYS_CHECK_INDEX if (Offset>=Cnt) throw TBadIndexError(); #endif return *((unsigned char *)TVoidArray::GetData()+(Cnt-Offset-(unsigned)1)); } TByteArray &TByteArray::SwapAt(unsigned IndexA, unsigned char &ByteB) { #if ARRAYS_CHECK_INDEX if (IndexA>=Cnt) throw TBadIndexError(); #endif unsigned char TempByte= *((const unsigned char *)TVoidArray::GetData()+IndexA); *((unsigned char *)TVoidArray::GetData()+IndexA)=ByteB; ByteB=TempByte; return *this; } TByteArray &TByteArray::ReverseAt(unsigned Index, unsigned RevCount) { #if ARRAYS_CHECK_INDEX if (Index>Index+RevCount || Index+RevCount>Cnt) throw TBadIndexError(); #endif unsigned char TempByte; unsigned char *PByteA=(unsigned char *)TVoidArray::GetData()+Index; unsigned char *PByteB=PByteA+RevCount; while ((RevCount--)>1) { TempByte=*PByteA; *PByteA++=*--PByteB; *PByteB=TempByte; RevCount--; } return *this; } TByteArray &TByteArray::Append(unsigned char Byte, unsigned RepCount) { TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,RepCount))); TVoidArray::SetAt(Cnt,(char)Byte,RepCount); Cnt+=RepCount; return *this; } TByteArray &TByteArray::Append(const unsigned char *PBytes, unsigned CopyCount) { #if ARRAYS_CHECK_INDEX if (!PBytes && CopyCount) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,CopyCount))); TVoidArray::CopyAt(Cnt,(const void *)PBytes,CopyCount); Cnt+=CopyCount; return *this; } TByteArray &TByteArray::Append(const TByteArray &Array, unsigned SrcIndex, unsigned CopyCount) { #if ARRAYS_CHECK_INDEX if (SrcIndex>SrcIndex+CopyCount || SrcIndex+CopyCount>Array.Cnt) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,CopyCount))); TVoidArray::CopyAt(Cnt,Array,SrcIndex,CopyCount); Cnt+=CopyCount; return *this; } TByteArray &TByteArray::InsertAt(unsigned Index, unsigned char Byte, unsigned RepCount) { #if ARRAYS_CHECK_INDEX if (Index>Cnt) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,RepCount))); TVoidArray::CopyAt(Index+RepCount,*this,Index,Cnt-Index); TVoidArray::SetAt(Index,(char)Byte,RepCount); Cnt+=RepCount; return *this; } TByteArray &TByteArray::InsertAt(unsigned Index, const unsigned char *PBytes, unsigned CopyCount) { #if ARRAYS_CHECK_INDEX if (Index>Cnt || !PBytes && CopyCount) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,CopyCount))); TVoidArray::CopyAt(Index+CopyCount,*this,Index,Cnt-Index); TVoidArray::CopyAt(Index,(const void *)PBytes,CopyCount); Cnt+=CopyCount; return *this; } TByteArray &TByteArray::InsertAt(unsigned Index, const TByteArray &Array, unsigned SrcIndex, unsigned CopyCount) { #if ARRAYS_CHECK_INDEX if (Index>Cnt || SrcIndex>SrcIndex+CopyCount || SrcIndex+CopyCount>Array.Cnt) throw TBadIndexError(); #endif TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,CopyCount))); TVoidArray::CopyAt(Index+CopyCount,*this,Index,Cnt-Index); TVoidArray::CopyAt(Index,Array, SrcIndex+(this==&Array && Index=Cnt) throw TBadIndexError(); #endif DestByte=*((const unsigned char *)TVoidArray::GetData()+Index); TVoidArray::CopyAt(Index,*this,Index+(unsigned)1,Cnt-(Index+(unsigned)1)); TVoidArray::Size(CalcNewSize(--Cnt)); return *this; } TByteArray &TByteArray::ExtractAt(unsigned Index, unsigned ExtrCount, unsigned char *PDestBytes) { #if ARRAYS_CHECK_INDEX if (Index+ExtrCount>Cnt) throw TBadIndexError(); #endif TVoidArray::CopyAt((void *)PDestBytes,Index,ExtrCount); TVoidArray::CopyAt(Index,*this,Index+ExtrCount,Cnt-(Index+ExtrCount)); TVoidArray::Size(CalcNewSize(Cnt-=ExtrCount)); return *this; } TByteArray &TByteArray::ExtractAt(unsigned Index, unsigned ExtrCount, TByteArray &DestArray) { #if ARRAYS_CHECK_INDEX if (Index>Index+ExtrCount || Index+ExtrCount>Cnt) throw TBadIndexError(); #endif if (DestArray.CntIndex+RemoveCount || Index+RemoveCount>Cnt) throw TBadIndexError(); #endif TVoidArray::CopyAt(Index,*this,Index+RemoveCount,Cnt-(Index+RemoveCount)); TVoidArray::Size(CalcNewSize(Cnt-=RemoveCount)); return *this; } TByteArray &TByteArray::Push(unsigned char Byte) { TVoidArray::Size(CalcNewSize(SizeAdd(Cnt,1))); *((unsigned char *)TVoidArray::GetData()+(Cnt++))=Byte; return *this; } TByteArray &TByteArray::Pop(unsigned char &DestByte) { #if ARRAYS_CHECK_INDEX if (!Cnt) throw TBadIndexError(); #endif DestByte=*((const unsigned char *)TVoidArray::GetData()+(--Cnt)); TVoidArray::Size(CalcNewSize(Cnt)); return *this; } unsigned TByteArray::GetEqualLenAt(unsigned IndexA, const TByteArray &ArrayB, unsigned IndexB, unsigned CompareCount) const { #if ARRAYS_CHECK_INDEX if (IndexA>IndexA+CompareCount || IndexA+CompareCount>Cnt || IndexB>IndexB+CompareCount || IndexB+CompareCount>ArrayB.Cnt) throw TBadIndexError(); #endif const unsigned char *PBytesA= (const unsigned char *)TVoidArray::GetData()+IndexA; const unsigned char *PBytesB= (const unsigned char *)ArrayB.TVoidArray::GetData()+IndexB; unsigned RemainCount=PBytesA!=PBytesB? CompareCount : 0; for (;RemainCount;RemainCount--) if (*PBytesA++!=*PBytesB++) break; return CompareCount-RemainCount; } unsigned TByteArray::GetEqualLenAt(unsigned IndexA, const unsigned char *PBytesB, unsigned CompareCount) const { #if ARRAYS_CHECK_INDEX if (IndexA>IndexA+CompareCount || IndexA+CompareCount>Cnt || !PBytesB && CompareCount) throw TBadIndexError(); #endif const unsigned char *PBytesA= (const unsigned char *)TVoidArray::GetData()+IndexA; unsigned RemainCount=PBytesA!=PBytesB? CompareCount : 0; for (;RemainCount;RemainCount--) if (*PBytesA++!=*PBytesB++) break; return CompareCount-RemainCount; } unsigned TByteArray::FindAt(unsigned Index, unsigned char Byte) const { #if ARRAYS_CHECK_INDEX if (Index>Cnt) throw TBadIndexError(); #endif const unsigned char *PBytes= (const unsigned char *)TVoidArray::GetData()+Index; for (Index=Cnt-Index;Index;Index--) if (*PBytes++==Byte) break; return Cnt-Index; } unsigned TByteArray::FindAt(unsigned Index, const TByteArray &Array, unsigned SrcIndex, unsigned SrcCount) const { #if ARRAYS_CHECK_INDEX if (Index>Cnt || SrcIndex>SrcIndex+SrcCount && SrcIndex+SrcCount>Array.Cnt) throw TBadIndexError(); #endif unsigned RemainCount=Cnt-Index; for (RemainCount=RemainCount>=SrcCount && SrcCount? RemainCount-(SrcCount-(unsigned)1) : 0; RemainCount--;Index++) if (GetEqualLenAt(Index,Array,SrcIndex,SrcCount)==SrcCount) return Index; return Cnt; } unsigned TByteArray::FindAt(unsigned Index, const unsigned char *PBytes, unsigned SrcCount) const { #if ARRAYS_CHECK_INDEX if (Index>Cnt || !PBytes && SrcCount) throw TBadIndexError(); #endif unsigned RemainCount=Cnt-Index; for (RemainCount=RemainCount>=SrcCount && SrcCount? RemainCount-(SrcCount-(unsigned)1) : 0; RemainCount--;Index++) if (GetEqualLenAt(Index,PBytes,SrcCount)==SrcCount) return Index; return Cnt; } unsigned TByteArray::ReverseFindAt(unsigned Index, unsigned char Byte) const { #if ARRAYS_CHECK_INDEX if (Index>=Cnt) throw TBadIndexError(); #endif const unsigned char *PBytes= (const unsigned char *)TVoidArray::GetData()+(++Index); while (Index--) if (*--PBytes==Byte) return Index; return Cnt; } unsigned TByteArray::ReverseFindAt(unsigned Index, const TByteArray &Array, unsigned SrcIndex, unsigned SrcCount) const { #if ARRAYS_CHECK_INDEX if (Index>=Cnt || SrcIndex>SrcIndex+SrcCount || SrcIndex+SrcCount>Array.Cnt) throw TBadIndexError(); #endif if (Cnt>=SrcCount && SrcCount) { if (Index>Cnt-SrcCount) Index=Cnt-SrcCount; for (Index++;Index--;) if (GetEqualLenAt(Index,Array,SrcIndex,SrcCount)==SrcCount) return Index; } return Cnt; } unsigned TByteArray::ReverseFindAt(unsigned Index, const unsigned char *PBytes, unsigned SrcCount) const { #if ARRAYS_CHECK_INDEX if (Index>=Cnt || !PBytes && SrcCount) throw TBadIndexError(); #endif if (Cnt>=SrcCount && SrcCount) { if (Index>Cnt-SrcCount) Index=Cnt-SrcCount; for (Index++;Index--;) if (GetEqualLenAt(Index,PBytes,SrcCount)==SrcCount) return Index; } return Cnt; }