1 #ifndef _RAR_ARRAY_
2 #define _RAR_ARRAY_
3 
4 extern ErrorHandler ErrHandler;
5 
6 template <class T> class Array
7 {
8   private:
9     T *Buffer;
10     size_t BufSize;
11     size_t AllocSize;
12     size_t MaxSize;
13     bool Secure; // Clean memory if true.
14   public:
15     Array();
16     Array(size_t Size);
17     Array(const Array &Src); // Copy constructor.
18     ~Array();
19     inline void CleanData();
20     inline T& operator [](size_t Item) const;
21     inline T* operator + (size_t Pos);
22     inline size_t Size(); // Returns the size in items, not in bytes.
23     void Add(size_t Items);
24     void Alloc(size_t Items);
25     void Reset();
26     void SoftReset();
27     void operator = (Array<T> &Src);
28     void Push(T Item);
29     void Append(T *Item,size_t Count);
Addr(size_t Item)30     T* Addr(size_t Item) {return Buffer+Item;}
SetMaxSize(size_t Size)31     void SetMaxSize(size_t Size) {MaxSize=Size;}
Begin()32     T* Begin() {return Buffer;}
End()33     T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
SetSecure()34     void SetSecure() {Secure=true;}
35 };
36 
37 
CleanData()38 template <class T> void Array<T>::CleanData()
39 {
40   Buffer=NULL;
41   BufSize=0;
42   AllocSize=0;
43   MaxSize=0;
44   Secure=false;
45 }
46 
47 
Array()48 template <class T> Array<T>::Array()
49 {
50   CleanData();
51 }
52 
53 
Array(size_t Size)54 template <class T> Array<T>::Array(size_t Size)
55 {
56   CleanData();
57   Add(Size);
58 }
59 
60 
61 // Copy constructor in case we need to pass an object as value.
Array(const Array & Src)62 template <class T> Array<T>::Array(const Array &Src)
63 {
64   CleanData();
65   Alloc(Src.BufSize);
66   if (Src.BufSize!=0)
67     memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
68 }
69 
70 
~Array()71 template <class T> Array<T>::~Array()
72 {
73   if (Buffer!=NULL)
74   {
75     if (Secure)
76       cleandata(Buffer,AllocSize*sizeof(T));
77     free(Buffer);
78   }
79 }
80 
81 
operator [](size_t Item) const82 template <class T> inline T& Array<T>::operator [](size_t Item) const
83 {
84   return Buffer[Item];
85 }
86 
87 
operator +(size_t Pos)88 template <class T> inline T* Array<T>::operator +(size_t Pos)
89 {
90   return Buffer+Pos;
91 }
92 
93 
Size()94 template <class T> inline size_t Array<T>::Size()
95 {
96   return BufSize;
97 }
98 
99 
Add(size_t Items)100 template <class T> void Array<T>::Add(size_t Items)
101 {
102   BufSize+=Items;
103   if (BufSize>AllocSize)
104   {
105     if (MaxSize!=0 && BufSize>MaxSize)
106     {
107       ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize);
108       ErrHandler.MemoryError();
109     }
110 
111     size_t Suggested=AllocSize+AllocSize/4+32;
112     size_t NewSize=Max(BufSize,Suggested);
113 
114     T *NewBuffer;
115     if (Secure)
116     {
117       NewBuffer=(T *)malloc(NewSize*sizeof(T));
118       if (NewBuffer==NULL)
119         ErrHandler.MemoryError();
120       if (Buffer!=NULL)
121       {
122         memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
123         cleandata(Buffer,AllocSize*sizeof(T));
124         free(Buffer);
125       }
126     }
127     else
128     {
129       NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
130       if (NewBuffer==NULL)
131         ErrHandler.MemoryError();
132     }
133     Buffer=NewBuffer;
134     AllocSize=NewSize;
135   }
136 }
137 
138 
Alloc(size_t Items)139 template <class T> void Array<T>::Alloc(size_t Items)
140 {
141   if (Items>AllocSize)
142     Add(Items-BufSize);
143   else
144     BufSize=Items;
145 }
146 
147 
Reset()148 template <class T> void Array<T>::Reset()
149 {
150   if (Buffer!=NULL)
151   {
152     free(Buffer);
153     Buffer=NULL;
154   }
155   BufSize=0;
156   AllocSize=0;
157 }
158 
159 
160 // Reset buffer size, but preserve already allocated memory if any,
161 // so we can reuse it without wasting time to allocation.
SoftReset()162 template <class T> void Array<T>::SoftReset()
163 {
164   BufSize=0;
165 }
166 
167 
operator =(Array<T> & Src)168 template <class T> void Array<T>::operator =(Array<T> &Src)
169 {
170   Reset();
171   Alloc(Src.BufSize);
172   if (Src.BufSize!=0)
173     memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
174 }
175 
176 
Push(T Item)177 template <class T> void Array<T>::Push(T Item)
178 {
179   Add(1);
180   (*this)[Size()-1]=Item;
181 }
182 
183 
Append(T * Items,size_t Count)184 template <class T> void Array<T>::Append(T *Items,size_t Count)
185 {
186   size_t CurSize=Size();
187   Add(Count);
188   memcpy(Buffer+CurSize,Items,Count*sizeof(T));
189 }
190 
191 #endif
192