/* * category: [data structure] * apply status: framework * edit status: not * build status: windows&linux * description: */ #ifndef ARRAY_H #define ARRAY_H #pragma once #include "config.h" #ifdef __cplusplus extern "C" { #endif #include #include #include "memutil.h" typedef struct array_header_t array_header_t; /** An opaque array type */ struct array_header_t { /** The amount of memory allocated for each element of the array */ int elt_size; /** The number of active elements in the array */ int nelts; /** The number of elements already allocated in the array */ int nalloc; /** The elements in the array, start address.*/ char *elts; }; /** * Determine if the array is empty (either NULL or having no elements) * @param a The array to check * @return True if empty, False otherwise */ TOOLKIT_API int array_empty(const array_header_t *a); /** * Create an array * @param nelts the number of elements in the initial array * @param elt_size The size of each element in the array. * @return The new array */ TOOLKIT_API array_header_t *array_make(int nelts, int elt_size); /** * destroy an array */ TOOLKIT_API void array_free(array_header_t *arr); /** * Add a new element to an array (as a first-in, last-out stack) * @param arr The array to add an element to. * @return Location for the new element in the array. * @remark If there are no free spots in the array, then this function will * allocate new space for the new element. */ TOOLKIT_API void *array_push(array_header_t *arr); /** A helper macro for accessing a member of an array. * * @param ary the array * @param i the index into the array to return * @param type the type of the objects stored in the array * * @return the item at index i */ #define ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i]) /** A helper macro for pushing elements into an array. * * @param ary the array * @param type the type of the objects stored in the array * * @return the location where the new object should be placed */ #define ARRAY_PUSH(ary,type) (*((type *)array_push(ary))) /** A helper function to exchange two elem * * @param ary the array * @param type the type of the objects stored in the array * * note: element type must be single type(not struct) */ #define ARRAY_XCHG(ary, x, y, type) \ do { \ type tmp; \ tmp = ARRAY_IDX(ary, x, type); \ ARRAY_IDX(ary, x, type) = ARRAY_IDX(ary, y, type); \ ARRAY_IDX(ary, y, type) = tmp; \ } while (0) #define ARRAY_XCHG_STRUCT(ary, i, j, type) \ do { \ type* ti = &ARRAY_IDX(ary, i, type); \ type* tj = &ARRAY_IDX(ary, j, type); \ type tmp; \ memcpy(&tmp, ti, sizeof(type)); \ memcpy(ti, tj, sizeof(type)); \ memcpy(tj, &tmp, sizeof(type)); \ } while(0) /** A helper by exchange position x with tail, witch type is a simple type * * @param ary the array * @param type the type of the objects stored in the array * * note: element type must be single type(not struct) */ #define ARRAY_XCHG_TAIL(ary, x, type) \ do { \ if ((x) < (ary->nelts - 1)) { \ ARRAY_XCHG(ary, x, ary->nelts - 1, type); \ } \ } while(0) /** A helper by exchange position x with tail, witch type is a struct type */ #define ARRAY_XCHG_TAIL_STRUCT(ary, x, type) \ do { \ if ((x) < (ary->nelts - 1)) { \ ARRAY_XCHG_STRUCT(ary, x, ary->nelts - 1, type); \ } \ } while (0) /** A helper delete x by exchange value with tail and pop out */ #define ARRAY_DEL(ary, x, type) \ ARRAY_XCHG_TAIL(ary, x, type); \ array_pop(ary); /** A helper delete x by exchange value with tail and pop out, for struct type */ #define ARRAY_DEL_STRUCT(ary, i, type) \ ARRAY_XCHG_TAIL_STRUCT(ary, i, type); \ array_pop(ary); /** helper for walk through each element */ #define ARRAY_FOR_EACH_ENTRY(pos, i, ary, type) \ for (i = ary->nelts-1; pos = ARRAY_IDX(ary, i, type), i >= 0; --i) /** helper for walk through each element, can delete current pos */ #define ARRAY_FOR_EACH_ENTRY_SAFE ARRAY_FOR_EACH_ENTRY /** * Remove an element from an array (as a first-in, last-out stack) * @param arr The array to remove an element from. * @return Location of the element in the array. * @remark If there are no elements in the array, NULL is returned. */ TOOLKIT_API void * array_pop(array_header_t *arr); /** * Remove all elements from an array. * @param arr The array to remove all elements from. * @remark As the underlying storage is allocated from a pool, no * memory is freed by this operation, but is available for reuse. */ TOOLKIT_API void array_clear(array_header_t *arr); /** * Concatenate two arrays together * @param dst The destination array, and the one to go first in the combined * array * @param src The source array to add to the destination array */ TOOLKIT_API void array_cat(array_header_t *dst,const array_header_t *src); /** * Copy the entire array * @param arr The array to copy * @return An exact copy of the array passed in * @remark The alternate apr_array_copy_hdr copies only the header, and arranges * for the elements to be copied if (and only if) the code subsequently * does a push or arraycat. */ TOOLKIT_API array_header_t * array_copy(const array_header_t *arr); /** * Reserves a minimum length of storage, allocating space if necessary * */ TOOLKIT_API void array_reserve(array_header_t *arr, int cnt); /** * destroy an array, and destry each element by free */ static __inline void array_free2(array_header_t *arr) { int i; for (i = 0; i < arr->nelts; ++i) { free(ARRAY_IDX(arr, i, void*)); } array_free(arr); } TOOLKIT_API void toolkit_array_free2(array_header_t *arr); #ifdef __cplusplus } // extern "C" { #endif #endif // ARRAY_H