1 /*------------------------------------------------------------------------------
2 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
3 *
4 * Distributable under the terms of either the Apache License (Version 2.0) or
5 * the GNU Lesser General Public License, as specified in the COPYING file.
6 ------------------------------------------------------------------------------*/
7 #ifndef _lucene_util_Array_
8 #define _lucene_util_Array_
9 
10 #include <stdlib.h>
11 #include <string.h>
12 
CL_NS_DEF(util)13 CL_NS_DEF(util)
14 
15 template<typename T>
16 class CLUCENE_INLINE_EXPORT ArrayBase: LUCENE_BASE{
17 public:
18 	T* values;
19 	size_t length;
20 
21   /**
22   * Delete's the values in the array.
23   * This won't do anything if deleteArray or takeArray is called first.
24   * This is overridden in various implementations to provide the appropriate deletor function.
25   */
26   virtual void deleteValues(){
27     if ( this->values == NULL )
28       return;
29 	  for (size_t i=0;i<this->length;i++){
30 		  deleteValue(this->values[i]);
31 		}
32   }
33   /**
34   * Delete's a single value. Used when resizing...
35   */
36   virtual void deleteValue(T) = 0;
37 
38   /**
39   * Delete's the values in the array and then calls deleteArray().
40   * This won't do anything if deleteArray or takeArray is called first.
41   * This is overridden in various implementations to provide the appropriate deletor function.
42   */
43 	void deleteAll(){
44     this->deleteValues();
45     this->deleteArray();
46   }
47 
48 	/**
49 	* Deletes the array holding the values. Do this if you want to take
50 	* ownership of the array's values, but not the array containing the values.
51 	*/
52 	void deleteArray(){
53 		free(this->values);
54     this->values = NULL;
55 	}
56 	/**
57 	* Empties the array. Do this if you want to take ownership of the array
58 	* and the array's values.
59 	*/
60 	T* takeArray(){
61 	    T* ret = values;
62 	    values = NULL;
63 	    return ret;
64 	}
65 
66     ArrayBase(const size_t initialLength = 0)
67         : values(NULL), length(initialLength)
68     {
69         if (initialLength > 0)
70         {
71             this->values = (T*)malloc(sizeof(T)*length);
72             memset(this->values,0,sizeof(T)*length);
73         }
74     }
75 	ArrayBase(T* _values, const size_t _length)
76         : values(_values), length(_length)
77     {
78 	}
79 	virtual ~ArrayBase(){
80 	}
81 
82 	const T& operator[](const size_t _Pos) const
83 	{
84 		if (length <= _Pos){
85 			_CLTHROWA(CL_ERR_IllegalArgument,"vector subscript out of range");
86 		}
87 		return (*(values + _Pos));
88 	}
89 	T& operator[](const size_t _Pos)
90 	{
91 		if (length <= _Pos){
92 			_CLTHROWA(CL_ERR_IllegalArgument,"vector subscript out of range");
93 		}
94 		return (*(values + _Pos));
95 	}
96 
97   /**
98   * Resize the array
99   * @param deleteValues if shrinking, delete the values that are lost.
100   */
101   void resize(const size_t newSize, const bool deleteValues=false){
102     if ( length == newSize ) return;
103 
104     if ( values == NULL )
105     {
106         values = (T*)malloc(sizeof(T)*newSize);
107         memset(values,0,sizeof(T) * newSize);
108         length = newSize;
109         return;
110     }
111 
112     if (length < newSize)
113     {
114         values = (T*)realloc(values, sizeof(T) * newSize);
115         memset(values + length,0,sizeof(T) * (newSize-length));
116     }
117     else // length > newSize, including newSize == 0
118     {
119         if ( deleteValues ){
120             for ( size_t i=newSize;i<length;i++ ){
121                 deleteValue(values[i]);
122             }
123         }
124 
125         if ( newSize == 0 )
126         {
127             free(values);
128             values = NULL;
129         }else{
130             // TODO: alternatively, we could store the actual array length without really shrinking it and
131             // by that save the deallocation process + possibly another realloc later
132             values = (T*)realloc(values, sizeof(T) * newSize);
133         }
134     }
135 
136     length = newSize;
137   }
138 };
139 
140 /**
141 * An array of objects. _CLDELETE is called on every contained object.
142 */
143 template<typename T>
144 class CLUCENE_INLINE_EXPORT ObjectArray: public ArrayBase<T*>{
145 public:
ObjectArray()146   ObjectArray():ArrayBase<T*>(){}
ObjectArray(T ** values,size_t length)147 	ObjectArray(T** values, size_t length):ArrayBase<T*>(values,length){}
ObjectArray(size_t length)148 	ObjectArray(size_t length):ArrayBase<T*>(length){}
149 
deleteValues()150   void deleteValues(){
151       if ( this->values == NULL )
152         return;
153 		  for (size_t i=0;i<this->length;++i){
154 			    _CLLDELETE(this->values[i]);
155 		  }
156 	    this->deleteArray();
157 	}
deleteUntilNULL()158   void deleteUntilNULL(){
159       if ( this->values == NULL )
160         return;
161 		  for (size_t i=0;i<this->length && this->values[i] != NULL;++i){
162 			    _CLLDELETE(this->values[i]);
163 		  }
164 	    this->deleteArray();
165 	}
deleteValue(T * v)166   void deleteValue(T* v){
167      _CLLDELETE(v);
168 	}
~ObjectArray()169 	virtual ~ObjectArray(){
170 	    deleteValues();
171 	}
172 
173 	/* Initializes all cells in the array with a NULL value */
initArray()174 	void initArray(){
175 		for (size_t i=0;i<this->length;i++){
176 			this->values[i]=NULL;
177 		}
178 	}
179 };
180 
181 /**
182 * Legacy code... don't use, remove all instances of this!
183 */
184 template<typename T>
185 class CLUCENE_INLINE_EXPORT Array: public ArrayBase<T>{
186 public:
_CL_DEPRECATED(ObjectArray or ValueArray)187   _CL_DEPRECATED(ObjectArray or ValueArray) Array():ArrayBase<T>(){}
Array(T * values,size_t length)188 	_CL_DEPRECATED(ObjectArray or ValueArray) Array(T* values, size_t length):ArrayBase<T>(values,length){}
Array(size_t length)189 	_CL_DEPRECATED(ObjectArray or ValueArray) Array(size_t length):ArrayBase<T>(length){}
deleteValues()190   void deleteValues(){
191     if ( this->values == NULL )
192         return;
193     this->deleteArray();
194 	}
deleteValue(T v)195   void deleteValue(T v){} //nothing to do...
~Array()196 	virtual ~Array(){
197 	}
198 };
199 
200 /**
201 * An array where the values do not need to be deleted
202 */
203 template<typename T>
204 class CLUCENE_INLINE_EXPORT ValueArray: public ArrayBase<T>{
205 public:
ValueArray()206   ValueArray():ArrayBase<T>(){}
ValueArray(T * values,size_t length)207 	ValueArray(T* values, size_t length):ArrayBase<T>(values,length){}
ValueArray(size_t length)208 	ValueArray(size_t length):ArrayBase<T>(length){}
209 
deleteValues()210   void deleteValues(){
211     if ( this->values == NULL )
212         return;
213     this->deleteArray();
214 	}
deleteValue(T)215   void deleteValue(T /*v*/){} //nothing to do...
~ValueArray()216   virtual ~ValueArray(){
217     deleteValues();
218   }
219 };
220 
221 /** A value array for const values (never deleted) */
222 template<typename T>
223 class CLUCENE_INLINE_EXPORT ConstValueArray: public ArrayBase<T>{
224 public:
ConstValueArray()225   ConstValueArray():ArrayBase<T>(){}
ConstValueArray(T * values,size_t length)226 	ConstValueArray(T* values, size_t length):ArrayBase<T>(values,length){}
ConstValueArray(size_t length)227 	ConstValueArray(size_t length):ArrayBase<T>(length){}
228 
deleteValues()229   void deleteValues(){}
deleteValue(T)230   void deleteValue(T /*v*/){} //nothing to do...
~ConstValueArray()231   virtual ~ConstValueArray(){}
232 };
233 
234 
235 /**
236 * An array of TCHAR strings
237 */
238 class CLUCENE_INLINE_EXPORT TCharArray: public ArrayBase<TCHAR*>{
239 public:
TCharArray()240   TCharArray():ArrayBase<TCHAR*>(){}
TCharArray(size_t length)241 	TCharArray(size_t length):ArrayBase<TCHAR*>(length){}
242 
deleteValues()243   void deleteValues(){
244     if ( this->values == NULL )
245         return;
246 	  for (size_t i=0;i<this->length;i++)
247 		  _CLDELETE_CARRAY(this->values[i]);
248     this->deleteArray();
249 	}
deleteValue(TCHAR * v)250   void deleteValue(TCHAR* v){
251 		  _CLDELETE_LCARRAY(v);
252   }
~TCharArray()253 	virtual ~TCharArray(){
254 	    deleteValues();
255 	}
256 };
257 
258 /**
259 * An array of char strings
260 */
261 class CLUCENE_INLINE_EXPORT CharArray: public ArrayBase<char*>{
262 public:
CharArray()263   CharArray():ArrayBase<char*>(){}
CharArray(size_t length)264 	CharArray(size_t length):ArrayBase<char*>(length){}
265 
deleteValues()266     void deleteValues(){
267       if ( this->values == NULL )
268           return;
269 		  for (size_t i=0;i<this->length;i++)
270 			  _CLDELETE_CaARRAY(this->values[i]);
271 	    this->deleteArray();
272 	}
~CharArray()273 	virtual ~CharArray(){
274 	    deleteValues();
275 	}
276 };
277 
278 /**
279 * An array of const TCHAR strings
280 */
281 class CLUCENE_INLINE_EXPORT TCharConstArray: public ArrayBase<const TCHAR*>{
282 public:
TCharConstArray()283   TCharConstArray():ArrayBase<const TCHAR*>(){}
TCharConstArray(size_t length)284 	TCharConstArray(size_t length):ArrayBase<const TCHAR*>(length){}
285 
deleteValues()286     void deleteValues(){
287         if ( this->values == NULL )
288             return;
289 	    this->deleteArray();
290 	}
~TCharConstArray()291 	virtual ~TCharConstArray(){
292 	    deleteValues();
293 	}
294 };
295 
296 /**
297 * An array of const char strings
298 */
299 class CLUCENE_INLINE_EXPORT CharConstArray: public ArrayBase<const char*>{
300 public:
CharConstArray()301     CharConstArray():ArrayBase<const char*>(){}
CharConstArray(size_t length)302 	CharConstArray(size_t length):ArrayBase<const char*>(length){}
303 
deleteValues()304     void deleteValues(){
305         if ( this->values == NULL )
306             return;
307 	    this->deleteArray();
308 	}
~CharConstArray()309 	virtual ~CharConstArray(){
310 	    deleteValues();
311 	}
312 };
313 
314 /** An array that uses _CLDECDELETE for deletion */
315 template<typename T>
316 class CLUCENE_INLINE_EXPORT RefCountArray: public ArrayBase<T>{
317 public:
RefCountArray()318   RefCountArray():ArrayBase<T>(){}
RefCountArray(T * values,size_t length)319   RefCountArray(T* values, size_t length):ArrayBase<T>(values,length){}
RefCountArray(size_t length)320   RefCountArray(size_t length):ArrayBase<T>(length){}
321 
deleteValues()322   void deleteValues(){
323     if ( this->values == NULL )
324         return;
325     ArrayBase<T>::deleteValues();
326     this->deleteArray();
327     }
deleteValue(T v)328   void deleteValue(T v){
329     _CLDECDELETE(v);
330   } //nothing to do...
~RefCountArray()331   virtual ~RefCountArray(){
332     deleteValues();
333   }
334 };
335 
336 
337 CL_NS_END
338 #endif
339