| #ifndef _RAR_ARRAY_ |
| #define _RAR_ARRAY_ |
| |
| namespace third_party_unrar { |
| |
| extern ErrorHandler ErrHandler; |
| |
| template <class T> class Array |
| { |
| private: |
| T *Buffer; |
| size_t BufSize; |
| size_t AllocSize; |
| size_t MaxSize; |
| bool Secure; // Clean memory if true. |
| public: |
| Array(); |
| Array(size_t Size); |
| Array(const Array &Src); // Copy constructor. |
| ~Array(); |
| inline void CleanData(); |
| inline T& operator [](size_t Item) const; |
| inline T* operator + (size_t Pos); |
| inline size_t Size(); // Returns the size in items, not in bytes. |
| void Add(size_t Items); |
| void Alloc(size_t Items); |
| void Reset(); |
| void SoftReset(); |
| void operator = (Array<T> &Src); |
| void Push(T Item); |
| void Append(T *Item,size_t Count); |
| T* Addr(size_t Item) {return Buffer+Item;} |
| void SetMaxSize(size_t Size) {MaxSize=Size;} |
| T* Begin() {return Buffer;} |
| T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;} |
| void SetSecure() {Secure=true;} |
| }; |
| |
| |
| template <class T> void Array<T>::CleanData() |
| { |
| Buffer=NULL; |
| BufSize=0; |
| AllocSize=0; |
| MaxSize=0; |
| Secure=false; |
| } |
| |
| |
| template <class T> Array<T>::Array() |
| { |
| CleanData(); |
| } |
| |
| |
| template <class T> Array<T>::Array(size_t Size) |
| { |
| CleanData(); |
| Add(Size); |
| } |
| |
| |
| // Copy constructor in case we need to pass an object as value. |
| template <class T> Array<T>::Array(const Array &Src) |
| { |
| CleanData(); |
| Alloc(Src.BufSize); |
| if (Src.BufSize!=0) |
| memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); |
| } |
| |
| |
| template <class T> Array<T>::~Array() |
| { |
| if (Buffer!=NULL) |
| { |
| if (Secure) |
| cleandata(Buffer,AllocSize*sizeof(T)); |
| free(Buffer); |
| } |
| } |
| |
| |
| template <class T> inline T& Array<T>::operator [](size_t Item) const |
| { |
| return Buffer[Item]; |
| } |
| |
| |
| template <class T> inline T* Array<T>::operator +(size_t Pos) |
| { |
| return Buffer+Pos; |
| } |
| |
| |
| template <class T> inline size_t Array<T>::Size() |
| { |
| return BufSize; |
| } |
| |
| |
| template <class T> void Array<T>::Add(size_t Items) |
| { |
| BufSize+=Items; |
| if (BufSize>AllocSize) |
| { |
| if (MaxSize!=0 && BufSize>MaxSize) |
| { |
| ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize); |
| ErrHandler.MemoryError(); |
| } |
| |
| size_t Suggested=AllocSize+AllocSize/4+32; |
| size_t NewSize=Max(BufSize,Suggested); |
| |
| T *NewBuffer; |
| if (Secure) |
| { |
| NewBuffer=(T *)malloc(NewSize*sizeof(T)); |
| if (NewBuffer==NULL) |
| ErrHandler.MemoryError(); |
| if (Buffer!=NULL) |
| { |
| memcpy(NewBuffer,Buffer,AllocSize*sizeof(T)); |
| cleandata(Buffer,AllocSize*sizeof(T)); |
| free(Buffer); |
| } |
| } |
| else |
| { |
| NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T)); |
| if (NewBuffer==NULL) |
| ErrHandler.MemoryError(); |
| } |
| Buffer=NewBuffer; |
| AllocSize=NewSize; |
| } |
| } |
| |
| |
| template <class T> void Array<T>::Alloc(size_t Items) |
| { |
| if (Items>AllocSize) |
| Add(Items-BufSize); |
| else |
| BufSize=Items; |
| } |
| |
| |
| template <class T> void Array<T>::Reset() |
| { |
| if (Buffer!=NULL) |
| { |
| free(Buffer); |
| Buffer=NULL; |
| } |
| BufSize=0; |
| AllocSize=0; |
| } |
| |
| |
| // Reset buffer size, but preserve already allocated memory if any, |
| // so we can reuse it without wasting time to allocation. |
| template <class T> void Array<T>::SoftReset() |
| { |
| BufSize=0; |
| } |
| |
| |
| template <class T> void Array<T>::operator =(Array<T> &Src) |
| { |
| Reset(); |
| Alloc(Src.BufSize); |
| if (Src.BufSize!=0) |
| memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); |
| } |
| |
| |
| template <class T> void Array<T>::Push(T Item) |
| { |
| Add(1); |
| (*this)[Size()-1]=Item; |
| } |
| |
| |
| template <class T> void Array<T>::Append(T *Items,size_t Count) |
| { |
| size_t CurSize=Size(); |
| Add(Count); |
| memcpy(Buffer+CurSize,Items,Count*sizeof(T)); |
| } |
| |
| } // namespace third_party_unrar |
| |
| #endif |