00001 /* 00002 * libfid - Full-text Index Data structure library 00003 * Copyright (C) 2006, 2007, 2008, 2009 Robert Homann 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00018 * MA 02110-1301 USA 00019 */ 00020 00021 #ifndef ARRAYS_H 00022 #define ARRAYS_H 00023 /*!\addtogroup arrays Dynamic arrays 00024 * Generic implementation of dynamic arrays. Here is a set of macros for 00025 * mamaging dynamic arrays of arbitrary types. To declare a new dynamic array 00026 * type, use fid_DYNARRAY_DECLARE(). Then use fid_DYNARRAY_INIT() or 00027 * fid_DYNARRAY_INIT_PREALLOC() for initialization, and one of the various 00028 * macros described in here to add or remove elements to/from your array. When 00029 * running out of space, the array will grow automatically (depending on the 00030 * macro used). Free up the space occupied by your array with 00031 * fid_DYNARRAY_FREE(). 00032 * 00033 * Macro fid_DYNARRAY_DECLARE() declares a new dynamic array type of a given 00034 * name, storing elements of given type. This new type has several members, 00035 * where the "public" ones are 00036 * - \c dyndata, 00037 * - \c allocated, and 00038 * - \c occupied 00039 * 00040 * The actual data is stored in memory pointed to by \c dyndata. This is a 00041 * pointer of the type passed to fid_DYNARRAY_DECLARE(). The number of 00042 * allocated elements is stored in \c allocated. This is the total number of 00043 * elements of the stored type that the array can store, not the size of the 00044 * memory block in bytes. If the total size needs to be known in bytes, then 00045 * this can be obtained by multiplying \c allocated with the size of the stored 00046 * type. The number of elements currently in use is stored in \c occupied. The 00047 * dynamic arrays implemented here do not maintain a free-list, but assume a 00048 * stack-like organization. That is, the value \c occupied is always 00049 * interpreted in a way that elements <code>0, 1, ..., occupied-1</code> are 00050 * in use, and that elements <code>occupied, occupied+1, ..., allocated-1</code> 00051 * are free. This makes the element at index <code>occupied-1</code> the last 00052 * used element in the array, which can be accessed easily using macro 00053 * fid_DYNARRAY_TOPELEM(). 00054 * 00055 * \note When compiled for debugging (i.e., with preprocessor symbol \c DEBUG 00056 * defined), then the array structures are augmented with one extra member that 00057 * is used for additional checks. These checks are only performed in debug 00058 * mode. An implication is that array structure sizes are different in debug 00059 * and non-debug modes, so that applications compiled with \c DEBUG are 00060 * <em>binary incompatible</em> with a version of \c libfid compiled without 00061 * \c DEBUG (and vice versa). Please keep this in mind when observing strange 00062 * things happening. 00063 */ 00064 /*@{*/ 00065 #ifdef __cplusplus 00066 #include <cassert> 00067 #else /* !__cplusplus */ 00068 #include <assert.h> 00069 #endif /* __cplusplus */ 00070 00071 /* 00072 * Here is some documentation for the macros defined inside the #ifdef, #else, 00073 * #endif blocks. No need for copy-and-paste... 00074 */ 00075 00076 /*!\def fid_DYNARRAY_SIZECHECK 00077 * \brief Debugging. 00078 * 00079 * Only defined to something meaningful in debug mode (i.e., when \c DEBUG is 00080 * defined). Please ignore this. 00081 */ 00082 00083 /*!\def fid_DYNARRAY_DECLARE 00084 * \brief Declare a dynamic array. 00085 * 00086 * \param NAME The name of the new structure. 00087 * \param TYPE The type of elements to be stored inside the dynamic array. 00088 */ 00089 00090 /*!\def fid_DYNARRAY_INIT 00091 * \brief Initialize a dynamic array. 00092 * 00093 * \param ARRAY A pointer to a dynamic array. 00094 * \param TYPE Type of the elements stored inside the dynamic array. 00095 */ 00096 00097 /*!\def fid_DYNARRAY_FREE 00098 * \brief Free space occupied by a dynamic array. 00099 * 00100 * This macro does attempt not iterate over the array's elements and free them. 00101 * If the array elements need to be freed, maybe because they contain pointers 00102 * to allocated memory, then you must free them by yourself before calling this 00103 * macro. 00104 * 00105 * \param ARRAY A pointer to a dynamic array. 00106 * \param TYPE Type of the elements stored inside the dynamic array. 00107 */ 00108 00109 /*!\def fid_DYNARRAY_PUSH_UNSAFE 00110 * \brief Append element to dynamic array, without size check. 00111 * 00112 * This macro, like fid_DYNARRAY_PUSH(), does not store anything to the array. 00113 * It is just a convenience macro that increases the \c occupied member of the 00114 * array. After that, the element at index \c occupied is considered free and 00115 * can be written to. This macro is used to be make the code more readable, and 00116 * also to emphasize that a simple increment of the \c occupied variable is not 00117 * safe in general. 00118 * 00119 * Use fid_DYNARRAY_PUSH() if the dynamic array may need to be resized. Also 00120 * check if fid_DYNARRAY_APPEND() or fid_DYNARRAY_APPEND_UNSAFE() are more 00121 * appropriate for your application. 00122 * 00123 * Never use this macro unless you are absolutely sure that there is enough 00124 * free space in the array. The debug version may catch an attempt to write 00125 * beyond array bounds, but the non-debug version will \e not. 00126 * 00127 * \param ARRAY A pointer to a dynamic array. 00128 * \param TYPE Type of the elements stored inside the dynamic array. 00129 */ 00130 00131 /*!\def fid_DYNARRAY_POP_ELEM 00132 * \brief Assign last element of dynamic array to some variable, and remove it 00133 * from the array. 00134 * 00135 * This macro is unsafe. If the array is empty, your program will not do the 00136 * correct thing since it will try to read the non-existent element beyond the 00137 * lower array boundary. The debug version might catch such a mistake, the 00138 * non-debug version will \e not. 00139 * 00140 * Also think if the assignment performed by this macro is correct for your 00141 * application, or if the use of some copy function would be more approriate, 00142 * or if you could simply use the array element directly. 00143 * 00144 * \param ARRAY A pointer to a dynamic array. 00145 * \param TYPE Type of the elements stored inside the dynamic array. 00146 * \param VAL A variable of type \p TYPE that the last element of the dynamic 00147 * array is assigned to. 00148 */ 00149 00150 /*!\def fid_DYNARRAY_POP 00151 * \brief Remove last element from dynamic array. 00152 * 00153 * Like fid_DYNARRAY_PUSH_UNSAFE(), this macro is a convenience macro that 00154 * simply decrements the \c occupied member of the passed dynamic array. And 00155 * like fid_DYNARRAY_POP_ELEM(), it is also unsafe to use it on empty arrays. 00156 * 00157 * \param ARRAY A pointer to a dynamic array. 00158 * \param TYPE Type of the elements stored inside the dynamic array. 00159 */ 00160 00161 #ifdef DEBUG 00162 #define fid_DYNARRAY_SIZECHECK(ARRAY,TYPE) assert((ARRAY)->size_of_type == sizeof(TYPE)) 00163 00164 #define fid_DYNARRAY_DECLARE(NAME,TYPE)\ 00165 typedef struct\ 00166 {\ 00167 size_t occupied; /*!<\brief Number of elements in use. */\ 00168 size_t allocated; /*!<\brief Number of elements for which space has 00169 * been allocated. */\ 00170 TYPE *dyndata; /*!<\brief Pointer to array data. */\ 00171 TYPE *prev_dyndata; /*!<\brief Temporary used before calling 00172 * \c realloc() to prevent leaking memory. */\ 00173 size_t size_of_type; /*!<\brief Size of stored type for additional checks 00174 * (only available in debug mode). */\ 00175 } NAME 00176 00177 #define fid_DYNARRAY_INIT(ARRAY,TYPE)\ 00178 (ARRAY)->occupied=(ARRAY)->allocated=0;\ 00179 (ARRAY)->dyndata=(TYPE *)NULL;\ 00180 (ARRAY)->prev_dyndata=(TYPE *)NULL;\ 00181 (ARRAY)->size_of_type=sizeof(TYPE) 00182 00183 #define fid_DYNARRAY_FREE(ARRAY,TYPE)\ 00184 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00185 if(((ARRAY)->dyndata) != NULL)\ 00186 {\ 00187 free((ARRAY)->dyndata);\ 00188 }\ 00189 (ARRAY)->size_of_type=0 00190 00191 #define fid_DYNARRAY_PUSH_UNSAFE(ARRAY,TYPE)\ 00192 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00193 assert((ARRAY)->occupied < (ARRAY)->allocated);\ 00194 ++(ARRAY)->occupied 00195 00196 #define fid_DYNARRAY_POP_ELEM(ARRAY,TYPE,VAL)\ 00197 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00198 assert((ARRAY)->occupied > 0);\ 00199 (VAL)=(ARRAY)->dyndata[--(ARRAY)->occupied] 00200 00201 #define fid_DYNARRAY_POP(ARRAY,TYPE)\ 00202 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00203 assert((ARRAY)->occupied > 0);\ 00204 --(ARRAY)->occupied 00205 #else /* !DEBUG */ 00206 #define fid_DYNARRAY_SIZECHECK(ARRAY,TYPE) 00207 00208 #define fid_DYNARRAY_DECLARE(NAME,TYPE)\ 00209 typedef struct\ 00210 {\ 00211 size_t occupied; /*!<\brief Number of elements in use. */\ 00212 size_t allocated; /*!<\brief Number of elements for which space has 00213 * been allocated. */\ 00214 TYPE *dyndata; /*!<\brief Pointer to array data. */\ 00215 TYPE *prev_dyndata; /*!<\brief Temporary used before calling\ 00216 * \c realloc() to prevent leaking memory. */\ 00217 } NAME 00218 00219 #define fid_DYNARRAY_INIT(ARRAY,TYPE)\ 00220 (ARRAY)->occupied=(ARRAY)->allocated=0;\ 00221 (ARRAY)->dyndata=(TYPE *)NULL;\ 00222 (ARRAY)->prev_dyndata=(TYPE *)NULL 00223 00224 #define fid_DYNARRAY_FREE(ARRAY,TYPE)\ 00225 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00226 if(((ARRAY)->dyndata) != NULL)\ 00227 {\ 00228 free((ARRAY)->dyndata);\ 00229 } 00230 00231 #define fid_DYNARRAY_PUSH_UNSAFE(ARRAY,TYPE)\ 00232 ++(ARRAY)->occupied 00233 00234 #define fid_DYNARRAY_POP_ELEM(ARRAY,TYPE,VAL)\ 00235 (VAL)=(ARRAY)->dyndata[--(ARRAY)->occupied] 00236 00237 #define fid_DYNARRAY_POP(ARRAY,TYPE)\ 00238 --(ARRAY)->occupied 00239 #endif /* DEBUG */ 00240 00241 /*! 00242 * \brief Make sure that there are at least \e n free elements in dynamic array. 00243 * 00244 * If you know that you will store a certain number of elements inside a 00245 * dynamic array, then this macro can be used to pre-allocate this number of 00246 * elements. After a successful call of this macro, the next \p N elements, 00247 * starting at index \c occupied, can be used safely. This means that macros 00248 * like fid_DYNARRAY_PUSH_UNSAFE() or fid_DYNARRAY_APPEND_UNSAFE() can be used 00249 * safely up to \p N times in order to access the next \p N elements of the 00250 * array. 00251 * 00252 * \param ARRAY A pointer to a dynamic array. 00253 * \param TYPE Type of the elements stored inside the dynamic array. 00254 * \param N The number of elements needed. 00255 * \param FAILCODE When there is not enough memory left, then this code is 00256 * executed. 00257 * 00258 * \note In case of failure, the \c dyndata pointer will still point to the old 00259 * memory block, which is left intact. 00260 */ 00261 #define fid_DYNARRAY_ENSURE_NFREE(ARRAY,TYPE,N,FAILCODE)\ 00262 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00263 if((ARRAY)->occupied+(N) > (ARRAY)->allocated)\ 00264 {\ 00265 (ARRAY)->allocated=(ARRAY)->occupied+(N);\ 00266 (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ 00267 (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->allocated);\ 00268 if((ARRAY)->dyndata == NULL)\ 00269 {\ 00270 (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ 00271 FAILCODE\ 00272 }\ 00273 }\ 00274 assert((ARRAY)->dyndata != NULL) 00275 00276 /*! 00277 * \brief Make sure that the next element in a dynamic array can be written to. 00278 * 00279 * Before writing to the next element in a dynamic array, use this macro to 00280 * make sure that this next element can actually be used. When running out of 00281 * space, the macro resizes the dynamic array so that \p N more elements can be 00282 * stored. After a successful call of this macro, the element at index 00283 * \c occupied can safely be written to, and unsafe macros like 00284 * fid_DYNARRAY_PUSH_UNSAFE() may be used once (in that case, however, you may 00285 * use fid_DYNARRAY_PUSH() as well). 00286 * 00287 * Use fid_DYNARRAY_ENSURE_NFREE() to pre-allocate a specific number of free 00288 * elements. 00289 * 00290 * \param ARRAY A pointer to a dynamic array. 00291 * \param TYPE Type of the elements stored inside the dynamic array. 00292 * \param N The number of elements to add to the array when running out of 00293 * space. This value should be an estimate on how many elements are likely to 00294 * be added while the application is running. The greater this value, the fewer 00295 * reallocations will happen, which is good for performance, but the more space 00296 * is likely to be wasted. 00297 * \param FAILCODE When there is not enough memory left, then this code is 00298 * executed. 00299 * 00300 * \note In case of failure, the \c dyndata pointer will still point to the old 00301 * memory block, which is left intact. 00302 */ 00303 #define fid_DYNARRAY_ENSURE_NEXT(ARRAY,TYPE,N,FAILCODE)\ 00304 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00305 if((ARRAY)->occupied >= (ARRAY)->allocated)\ 00306 {\ 00307 (ARRAY)->allocated=(ARRAY)->occupied+(N);\ 00308 (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ 00309 (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->allocated);\ 00310 if((ARRAY)->dyndata == NULL)\ 00311 {\ 00312 (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ 00313 FAILCODE\ 00314 }\ 00315 }\ 00316 assert((ARRAY)->dyndata != NULL) 00317 00318 /*! 00319 * \brief Initialize a dynamic array, pre-allocate some elements. 00320 * 00321 * Like fid_DYNARRAY_INIT(), but also make sure that the first \p N elements 00322 * can be written to. The \p occupied member is initialized to point beyond the 00323 * last free element (i.e., set to the same value as \p allocated) so as to 00324 * mark all elements used. 00325 * 00326 * This macro makes using dynamic arrays convenient to use as fixed-size arrays 00327 * (that may, of course, be enlarged later), when the number of elements, or 00328 * initial number of elements, is known in advance. 00329 * 00330 * \note Unsafe macros that rely on the value of \c occupied being smaller than 00331 * \c allocated, like fid_DYNARRAY_APPEND_UNSAFE(), must \e not be used on 00332 * pre-allocated arrays initialized by this macro. Using macros like 00333 * fid_DYNARRAY_APPEND() may not work as expected since they will write 00334 * \e after the pre-allocated elements. 00335 * 00336 * \param ARRAY A pointer to a dynamic array. 00337 * \param TYPE Type of the elements stored inside the dynamic array. 00338 * \param N The number of elements to allocate. 00339 * \param FAILCODE When there is not enough memory left, then this code is 00340 * executed. 00341 */ 00342 #define fid_DYNARRAY_INIT_PREALLOC(ARRAY,TYPE,N,FAILCODE)\ 00343 fid_DYNARRAY_INIT(ARRAY,TYPE);\ 00344 fid_DYNARRAY_ENSURE_NFREE(ARRAY,TYPE,N,FAILCODE);\ 00345 (ARRAY)->occupied=(ARRAY)->allocated 00346 00347 /*! 00348 * \brief Append a value to a dynamic array. 00349 * 00350 * This is a shortcut for a call of fid_DYNARRAY_ENSURE_NEXT(), followed by an 00351 * assignment of a value to the last element of a dynamic array, followed by an 00352 * increment of \c occupied. 00353 * 00354 * The passed value \p VAL is stored via assigment. If this is not enough, 00355 * i.e., you need to call some copy function to make a real copy, then may 00356 * prefer to use fid_DYNARRAY_PUSH(), which does the same as this macro does, 00357 * but omits the assigment. 00358 * 00359 * \param ARRAY A pointer to a dynamic array. 00360 * \param TYPE Type of the elements stored inside the dynamic array. 00361 * \param N The number of elements to add to the array when running out of 00362 * space. See fid_DYNARRAY_ENSURE_NEXT(). 00363 * \param VAL The value of type \p TYPE to be stored. 00364 * \param FAILCODE When there is not enough memory left, then this code is 00365 * executed. 00366 * 00367 * \note In case of failure, the \c dyndata pointer will still point to the old 00368 * memory block, which is left intact. 00369 */ 00370 #define fid_DYNARRAY_APPEND(ARRAY,TYPE,N,VAL,FAILCODE)\ 00371 fid_DYNARRAY_ENSURE_NEXT(ARRAY,TYPE,N,FAILCODE);\ 00372 (ARRAY)->dyndata[(ARRAY)->occupied++]=(VAL) 00373 00374 /*! 00375 * \brief Append a value to a dynamic array, without size check. 00376 * 00377 * Just like fid_DYNARRAY_APPEND(), but omit the check if there is enough space 00378 * left. 00379 * 00380 * Never use this macro unless you are absolutely sure that there is enough 00381 * free space in the array. The debug version may catch an attempt to write 00382 * beyond array bounds, but the non-debug version will \e not. 00383 * 00384 * \param ARRAY A pointer to a dynamic array. 00385 * \param TYPE Type of the elements stored inside the dynamic array. 00386 * space. See fid_DYNARRAY_ENSURE_NEXT(). 00387 * \param VAL The value of type \p TYPE to be stored. 00388 */ 00389 #define fid_DYNARRAY_APPEND_UNSAFE(ARRAY,TYPE,VAL)\ 00390 fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ 00391 (ARRAY)->dyndata[(ARRAY)->occupied++]=(VAL) 00392 00393 /*! 00394 * \brief Append element to dynamic array. 00395 * 00396 * Simpler alternative for fid_DYNARRAY_APPEND() when assignment is not good 00397 * enough. After a successful call of this macro, you may want to use 00398 * fid_DYNARRAY_TOPELEM() to initialize the new element. 00399 * 00400 * \param ARRAY A pointer to a dynamic array. 00401 * \param TYPE Type of the elements stored inside the dynamic array. 00402 * \param N The number of elements to add to the array when running out of 00403 * space. See fid_DYNARRAY_ENSURE_NEXT(). 00404 * \param FAILCODE When there is not enough memory left, then this code is 00405 * executed. 00406 * 00407 * \note In case of failure, the \c dyndata pointer will still point to the old 00408 * memory block, which is left intact. 00409 */ 00410 #define fid_DYNARRAY_PUSH(ARRAY,TYPE,N,FAILCODE)\ 00411 fid_DYNARRAY_ENSURE_NEXT(ARRAY,TYPE,N,FAILCODE);\ 00412 fid_DYNARRAY_PUSH_UNSAFE(ARRAY,TYPE) 00413 00414 /*! 00415 * \brief Access last/top element in dynamic array. 00416 * 00417 * Just a shortcut macro to make the code more readable. It is safe to put a 00418 * <code>&</code> in front of this macro to obtain a pointer to the last 00419 * element. (Bear in mind, however, that this pointer may quickly become 00420 * invalid when the array needs to be reallocated.) 00421 * 00422 * \param ARRAY A pointer to a dynamic array. 00423 * \param TYPE Type of the elements stored inside the dynamic array. 00424 */ 00425 #define fid_DYNARRAY_TOPELEM(ARRAY,TYPE)\ 00426 ((ARRAY)->dyndata[(ARRAY)->occupied-1]) 00427 00428 /*! 00429 * \brief Reallocate array so that it does not use up more space than necessary. 00430 * 00431 * If the array is empty, i.e., \c occupied is zero, then the array will be 00432 * freed and re-initialized. 00433 * 00434 * \param ARRAY A pointer to a dynamic array. 00435 * \param TYPE Type of the elements stored inside the dynamic array. 00436 * \param FAILCODE When reallocation failed, then this code is executed. 00437 * 00438 * \note In case of failure, the \c dyndata pointer will still point to the old 00439 * memory block, which is left intact. This means, it might be safe to ignore 00440 * a failure, and keep your program running even in case of failure since all 00441 * data will still be there, and the rest of the dynamic array will remain 00442 * unchanged. 00443 */ 00444 #define fid_DYNARRAY_SHRINK(ARRAY,TYPE,FAILCODE)\ 00445 if((ARRAY)->occupied > 0)\ 00446 {\ 00447 if((ARRAY)->allocated > (ARRAY)->occupied)\ 00448 {\ 00449 (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ 00450 (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->occupied);\ 00451 if((ARRAY)->dyndata != NULL)\ 00452 {\ 00453 (ARRAY)->allocated=(ARRAY)->occupied;\ 00454 }\ 00455 else\ 00456 {\ 00457 (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ 00458 FAILCODE\ 00459 }\ 00460 }\ 00461 }\ 00462 else\ 00463 {\ 00464 fid_DYNARRAY_FREE(ARRAY,TYPE);\ 00465 fid_DYNARRAY_INIT(ARRAY,TYPE);\ 00466 } 00467 00468 /*! 00469 * \brief Dynamic array of <code>char</code> values. 00470 */ 00471 fid_DYNARRAY_DECLARE(fid_Arraychar,char); 00472 00473 /*! 00474 * \brief Dynamic array of <code>unsigned char</code> values. 00475 */ 00476 fid_DYNARRAY_DECLARE(fid_Arrayuchar,unsigned char); 00477 00478 /*! 00479 * \brief Dynamic array of <code>fid_Uint32</code> values. 00480 */ 00481 fid_DYNARRAY_DECLARE(fid_ArrayUint32,fid_Uint32); 00482 00483 /*! 00484 * \brief Dynamic array of <code>fid_Uint64</code> values. 00485 */ 00486 fid_DYNARRAY_DECLARE(fid_ArrayUint64,fid_Uint64); 00487 00488 /*! 00489 * \brief Dynamic array of <code>fid_Sint32</code> values. 00490 */ 00491 fid_DYNARRAY_DECLARE(fid_ArraySint32,fid_Sint32); 00492 00493 /*! 00494 * \brief Dynamic array of <code>fid_Sint64</code> values. 00495 */ 00496 fid_DYNARRAY_DECLARE(fid_ArraySint64,fid_Sint64); 00497 /*@}*/ 00498 00499 #endif /* !ARRAYS_H */