array.h 5.4 KB

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