array.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* $OpenBSD$ */
  2. /*
  3. * Copyright (c) 2006 Nicholas Marriott <nicholas.marriott@gmail.com>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  14. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  15. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #ifndef ARRAY_H
  18. #define ARRAY_H
  19. #define ARRAY_INITIALIZER { NULL, 0, 0 }
  20. #define ARRAY_DECL(n, c) \
  21. struct n { \
  22. c *list; \
  23. u_int num; \
  24. size_t space; \
  25. }
  26. #define ARRAY_ITEM(a, i) ((a)->list[i])
  27. #define ARRAY_ITEMSIZE(a) (sizeof *(a)->list)
  28. #define ARRAY_INITIALSPACE(a) (10 * ARRAY_ITEMSIZE(a))
  29. #define ARRAY_ENSURE(a, n) do { \
  30. if (UINT_MAX - (n) < (a)->num) \
  31. fatalx("number too big"); \
  32. if (SIZE_MAX / ((a)->num + (n)) < ARRAY_ITEMSIZE(a)) \
  33. fatalx("size too big"); \
  34. if ((a)->space == 0) { \
  35. (a)->space = ARRAY_INITIALSPACE(a); \
  36. (a)->list = xrealloc((a)->list, (a)->space); \
  37. } \
  38. while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \
  39. (a)->list = xreallocarray((a)->list, 2, (a)->space); \
  40. (a)->space *= 2; \
  41. } \
  42. } while (0)
  43. #define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0)
  44. #define ARRAY_LENGTH(a) ((a)->num)
  45. #define ARRAY_DATA(a) ((a)->list)
  46. #define ARRAY_FIRST(a) ARRAY_ITEM(a, 0)
  47. #define ARRAY_LAST(a) ARRAY_ITEM(a, (a)->num - 1)
  48. #define ARRAY_INIT(a) do { \
  49. (a)->num = 0; \
  50. (a)->list = NULL; \
  51. (a)->space = 0; \
  52. } while (0)
  53. #define ARRAY_CLEAR(a) do { \
  54. (a)->num = 0; \
  55. } while (0)
  56. #define ARRAY_SET(a, i, s) do { \
  57. (a)->list[i] = s; \
  58. } while (0)
  59. #define ARRAY_ADD(a, s) do { \
  60. ARRAY_ENSURE(a, 1); \
  61. (a)->list[(a)->num] = s; \
  62. (a)->num++; \
  63. } while (0)
  64. #define ARRAY_INSERT(a, i, s) do { \
  65. ARRAY_ENSURE(a, 1); \
  66. if ((i) < (a)->num) { \
  67. memmove((a)->list + (i) + 1, (a)->list + (i), \
  68. ARRAY_ITEMSIZE(a) * ((a)->num - (i))); \
  69. } \
  70. (a)->list[i] = s; \
  71. (a)->num++; \
  72. } while (0)
  73. #define ARRAY_REMOVE(a, i) do { \
  74. if ((i) < (a)->num - 1) { \
  75. memmove((a)->list + (i), (a)->list + (i) + 1, \
  76. ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \
  77. } \
  78. (a)->num--; \
  79. if ((a)->num == 0) \
  80. ARRAY_FREE(a); \
  81. } while (0)
  82. #define ARRAY_EXPAND(a, n) do { \
  83. ARRAY_ENSURE(a, n); \
  84. (a)->num += n; \
  85. } while (0)
  86. #define ARRAY_TRUNC(a, n) do { \
  87. if ((a)->num > n) \
  88. (a)->num -= n; \
  89. else \
  90. ARRAY_FREE(a); \
  91. } while (0)
  92. #define ARRAY_CONCAT(a, b) do { \
  93. ARRAY_ENSURE(a, (b)->num); \
  94. memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)); \
  95. (a)->num += (b)->num; \
  96. } while (0)
  97. #define ARRAY_FREE(a) do { \
  98. free((a)->list); \
  99. ARRAY_INIT(a); \
  100. } while (0)
  101. #define ARRAY_FREEALL(a) do { \
  102. ARRAY_FREE(a); \
  103. free(a); \
  104. } while (0)
  105. #endif