array.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * category: [data structure]
  3. * apply status: framework
  4. * edit status: not
  5. * build status: windows&linux
  6. * description:
  7. */
  8. #ifndef ARRAY_H
  9. #define ARRAY_H
  10. #pragma once
  11. #include "config.h"
  12. #ifdef __cplusplus
  13. extern "C" {
  14. #endif
  15. #include <stdarg.h>
  16. #include <stdlib.h>
  17. #include "memutil.h"
  18. typedef struct array_header_t array_header_t;
  19. /** An opaque array type */
  20. struct array_header_t {
  21. /** The amount of memory allocated for each element of the array */
  22. int elt_size;
  23. /** The number of active elements in the array */
  24. int nelts;
  25. /** The number of elements already allocated in the array */
  26. int nalloc;
  27. /** The elements in the array, start address.*/
  28. char *elts;
  29. };
  30. /**
  31. * Determine if the array is empty (either NULL or having no elements)
  32. * @param a The array to check
  33. * @return True if empty, False otherwise
  34. */
  35. TOOLKIT_API int array_empty(const array_header_t *a);
  36. /**
  37. * Create an array
  38. * @param nelts the number of elements in the initial array
  39. * @param elt_size The size of each element in the array.
  40. * @return The new array
  41. */
  42. TOOLKIT_API array_header_t *array_make(int nelts, int elt_size);
  43. /**
  44. * destroy an array
  45. */
  46. TOOLKIT_API void array_free(array_header_t *arr);
  47. /**
  48. * Add a new element to an array (as a first-in, last-out stack)
  49. * @param arr The array to add an element to.
  50. * @return Location for the new element in the array.
  51. * @remark If there are no free spots in the array, then this function will
  52. * allocate new space for the new element.
  53. */
  54. TOOLKIT_API void *array_push(array_header_t *arr);
  55. /** A helper macro for accessing a member of an array.
  56. *
  57. * @param ary the array
  58. * @param i the index into the array to return
  59. * @param type the type of the objects stored in the array
  60. *
  61. * @return the item at index i
  62. */
  63. #define ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i])
  64. /** A helper macro for pushing elements into an array.
  65. *
  66. * @param ary the array
  67. * @param type the type of the objects stored in the array
  68. *
  69. * @return the location where the new object should be placed
  70. */
  71. #define ARRAY_PUSH(ary,type) (*((type *)array_push(ary)))
  72. /** A helper function to exchange two elem
  73. *
  74. * @param ary the array
  75. * @param type the type of the objects stored in the array
  76. *
  77. * note: element type must be single type(not struct)
  78. */
  79. #define ARRAY_XCHG(ary, x, y, type) \
  80. do { \
  81. type tmp; \
  82. tmp = ARRAY_IDX(ary, x, type); \
  83. ARRAY_IDX(ary, x, type) = ARRAY_IDX(ary, y, type); \
  84. ARRAY_IDX(ary, y, type) = tmp; \
  85. } while (0)
  86. #define ARRAY_XCHG_STRUCT(ary, i, j, type) \
  87. do { \
  88. type* ti = &ARRAY_IDX(ary, i, type); \
  89. type* tj = &ARRAY_IDX(ary, j, type); \
  90. type tmp; \
  91. memcpy(&tmp, ti, sizeof(type)); \
  92. memcpy(ti, tj, sizeof(type)); \
  93. memcpy(tj, &tmp, sizeof(type)); \
  94. } while(0)
  95. /** A helper by exchange position x with tail, witch type is a simple type
  96. *
  97. * @param ary the array
  98. * @param type the type of the objects stored in the array
  99. *
  100. * note: element type must be single type(not struct)
  101. */
  102. #define ARRAY_XCHG_TAIL(ary, x, type) \
  103. do { \
  104. if ((x) < (ary->nelts - 1)) { \
  105. ARRAY_XCHG(ary, x, ary->nelts - 1, type); \
  106. } \
  107. } while(0)
  108. /** A helper by exchange position x with tail, witch type is a struct type */
  109. #define ARRAY_XCHG_TAIL_STRUCT(ary, x, type) \
  110. do { \
  111. if ((x) < (ary->nelts - 1)) { \
  112. ARRAY_XCHG_STRUCT(ary, x, ary->nelts - 1, type); \
  113. } \
  114. } while (0)
  115. /** A helper delete x by exchange value with tail and pop out */
  116. #define ARRAY_DEL(ary, x, type) \
  117. ARRAY_XCHG_TAIL(ary, x, type); \
  118. array_pop(ary);
  119. /** A helper delete x by exchange value with tail and pop out, for struct type */
  120. #define ARRAY_DEL_STRUCT(ary, i, type) \
  121. ARRAY_XCHG_TAIL_STRUCT(ary, i, type); \
  122. array_pop(ary);
  123. /** helper for walk through each element */
  124. #define ARRAY_FOR_EACH_ENTRY(pos, i, ary, type) \
  125. for (i = ary->nelts-1; pos = ARRAY_IDX(ary, i, type), i >= 0; --i)
  126. /** helper for walk through each element, can delete current pos */
  127. #define ARRAY_FOR_EACH_ENTRY_SAFE ARRAY_FOR_EACH_ENTRY
  128. /**
  129. * Remove an element from an array (as a first-in, last-out stack)
  130. * @param arr The array to remove an element from.
  131. * @return Location of the element in the array.
  132. * @remark If there are no elements in the array, NULL is returned.
  133. */
  134. TOOLKIT_API void * array_pop(array_header_t *arr);
  135. /**
  136. * Remove all elements from an array.
  137. * @param arr The array to remove all elements from.
  138. * @remark As the underlying storage is allocated from a pool, no
  139. * memory is freed by this operation, but is available for reuse.
  140. */
  141. TOOLKIT_API void array_clear(array_header_t *arr);
  142. /**
  143. * Concatenate two arrays together
  144. * @param dst The destination array, and the one to go first in the combined
  145. * array
  146. * @param src The source array to add to the destination array
  147. */
  148. TOOLKIT_API void array_cat(array_header_t *dst,const array_header_t *src);
  149. /**
  150. * Copy the entire array
  151. * @param arr The array to copy
  152. * @return An exact copy of the array passed in
  153. * @remark The alternate apr_array_copy_hdr copies only the header, and arranges
  154. * for the elements to be copied if (and only if) the code subsequently
  155. * does a push or arraycat.
  156. */
  157. TOOLKIT_API array_header_t * array_copy(const array_header_t *arr);
  158. /**
  159. * Reserves a minimum length of storage, allocating space if necessary
  160. *
  161. */
  162. TOOLKIT_API void array_reserve(array_header_t *arr, int cnt);
  163. /**
  164. * destroy an array, and destry each element by free
  165. */
  166. static __inline void array_free2(array_header_t *arr)
  167. {
  168. int i;
  169. for (i = 0; i < arr->nelts; ++i) {
  170. free(ARRAY_IDX(arr, i, void*));
  171. }
  172. array_free(arr);
  173. }
  174. TOOLKIT_API void toolkit_array_free2(array_header_t *arr);
  175. #ifdef __cplusplus
  176. } // extern "C" {
  177. #endif
  178. #endif // ARRAY_H