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