gl_oset.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* Abstract ordered set data type.
  2. Copyright (C) 2006-2007, 2009-2013 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2006.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #ifndef _GL_OSET_H
  15. #define _GL_OSET_H
  16. #include <stdbool.h>
  17. #include <stddef.h>
  18. #ifndef _GL_INLINE_HEADER_BEGIN
  19. #error "Please include config.h first."
  20. #endif
  21. _GL_INLINE_HEADER_BEGIN
  22. #ifndef GL_OSET_INLINE
  23. # define GL_OSET_INLINE _GL_INLINE
  24. #endif
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28. /* gl_oset is an abstract ordered set data type. It can contain any number
  29. of objects ('void *' or 'const void *' pointers) in the order of a given
  30. comparator function. Duplicates (in the sense of the comparator) are
  31. forbidden.
  32. There are several implementations of this ordered set datatype, optimized
  33. for different operations or for memory. You can start using the simplest
  34. ordered set implementation, GL_ARRAY_OSET, and switch to a different
  35. implementation later, when you realize which operations are performed
  36. the most frequently. The API of the different implementations is exactly
  37. the same; when switching to a different implementation, you only have to
  38. change the gl_oset_create call.
  39. The implementations are:
  40. GL_ARRAY_OSET a growable array
  41. GL_AVLTREE_OSET a binary tree (AVL tree)
  42. GL_RBTREE_OSET a binary tree (red-black tree)
  43. The memory consumption is asymptotically the same: O(1) for every object
  44. in the set. When looking more closely at the average memory consumed
  45. for an object, GL_ARRAY_OSET is the most compact representation, and
  46. GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory.
  47. The guaranteed average performance of the operations is, for a set of
  48. n elements:
  49. Operation ARRAY TREE
  50. gl_oset_size O(1) O(1)
  51. gl_oset_add O(n) O(log n)
  52. gl_oset_remove O(n) O(log n)
  53. gl_oset_search O(log n) O(log n)
  54. gl_oset_search_atleast O(log n) O(log n)
  55. gl_oset_iterator O(1) O(log n)
  56. gl_oset_iterator_next O(1) O(log n)
  57. */
  58. /* -------------------------- gl_oset_t Data Type -------------------------- */
  59. /* Type of function used to compare two elements. Same as for qsort().
  60. NULL denotes pointer comparison. */
  61. typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2);
  62. /* Type of function used to dispose an element once it's removed from a set.
  63. NULL denotes a no-op. */
  64. typedef void (*gl_setelement_dispose_fn) (const void *elt);
  65. /* Type of function used to compare an element with a threshold.
  66. Return true if the element is greater or equal than the threshold. */
  67. typedef bool (*gl_setelement_threshold_fn) (const void *elt, const void *threshold);
  68. struct gl_oset_impl;
  69. /* Type representing an entire ordered set. */
  70. typedef struct gl_oset_impl * gl_oset_t;
  71. struct gl_oset_implementation;
  72. /* Type representing a ordered set datatype implementation. */
  73. typedef const struct gl_oset_implementation * gl_oset_implementation_t;
  74. #if 0 /* Unless otherwise specified, these are defined inline below. */
  75. /* Create an empty set.
  76. IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET.
  77. COMPAR_FN is an element comparison function or NULL.
  78. DISPOSE_FN is an element disposal function or NULL. */
  79. /* declared in gl_xoset.h */
  80. extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation,
  81. gl_setelement_compar_fn compar_fn,
  82. gl_setelement_dispose_fn dispose_fn);
  83. /* Likewise. Return NULL upon out-of-memory. */
  84. extern gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
  85. gl_setelement_compar_fn compar_fn,
  86. gl_setelement_dispose_fn dispose_fn);
  87. /* Return the current number of elements in an ordered set. */
  88. extern size_t gl_oset_size (gl_oset_t set);
  89. /* Search whether an element is already in the ordered set.
  90. Return true if found, or false if not present in the set. */
  91. extern bool gl_oset_search (gl_oset_t set, const void *elt);
  92. /* Search the least element in the ordered set that compares greater or equal
  93. to the given THRESHOLD. The representation of the THRESHOLD is defined
  94. by the THRESHOLD_FN.
  95. Return true and store the found element in *ELTP if found, otherwise return
  96. false. */
  97. extern bool gl_oset_search_atleast (gl_oset_t set,
  98. gl_setelement_threshold_fn threshold_fn,
  99. const void *threshold,
  100. const void **eltp);
  101. /* Add an element to an ordered set.
  102. Return true if it was not already in the set and added, false otherwise. */
  103. /* declared in gl_xoset.h */
  104. extern bool gl_oset_add (gl_oset_t set, const void *elt);
  105. /* Likewise. Return -1 upon out-of-memory. */
  106. extern int gl_oset_nx_add (gl_oset_t set, const void *elt)
  107. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
  108. __attribute__ ((__warn_unused_result__))
  109. #endif
  110. ;
  111. /* Remove an element from an ordered set.
  112. Return true if it was found and removed. */
  113. extern bool gl_oset_remove (gl_oset_t set, const void *elt);
  114. /* Free an entire ordered set.
  115. (But this call does not free the elements of the set.) */
  116. extern void gl_oset_free (gl_oset_t set);
  117. #endif /* End of inline and gl_xlist.h-defined functions. */
  118. /* --------------------- gl_oset_iterator_t Data Type --------------------- */
  119. /* Functions for iterating through an ordered set. */
  120. /* Type of an iterator that traverses an ordered set.
  121. This is a fixed-size struct, so that creation of an iterator doesn't need
  122. memory allocation on the heap. */
  123. typedef struct
  124. {
  125. /* For fast dispatch of gl_oset_iterator_next. */
  126. const struct gl_oset_implementation *vtable;
  127. /* For detecting whether the last returned element was removed. */
  128. gl_oset_t set;
  129. size_t count;
  130. /* Other, implementation-private fields. */
  131. void *p; void *q;
  132. size_t i; size_t j;
  133. } gl_oset_iterator_t;
  134. #if 0 /* These are defined inline below. */
  135. /* Create an iterator traversing an ordered set.
  136. The set's contents must not be modified while the iterator is in use,
  137. except for removing the last returned element. */
  138. extern gl_oset_iterator_t gl_oset_iterator (gl_oset_t set);
  139. /* If there is a next element, store the next element in *ELTP, advance the
  140. iterator and return true. Otherwise, return false. */
  141. extern bool gl_oset_iterator_next (gl_oset_iterator_t *iterator,
  142. const void **eltp);
  143. /* Free an iterator. */
  144. extern void gl_oset_iterator_free (gl_oset_iterator_t *iterator);
  145. #endif /* End of inline functions. */
  146. /* ------------------------ Implementation Details ------------------------ */
  147. struct gl_oset_implementation
  148. {
  149. /* gl_oset_t functions. */
  150. gl_oset_t (*nx_create_empty) (gl_oset_implementation_t implementation,
  151. gl_setelement_compar_fn compar_fn,
  152. gl_setelement_dispose_fn dispose_fn);
  153. size_t (*size) (gl_oset_t set);
  154. bool (*search) (gl_oset_t set, const void *elt);
  155. bool (*search_atleast) (gl_oset_t set,
  156. gl_setelement_threshold_fn threshold_fn,
  157. const void *threshold, const void **eltp);
  158. int (*nx_add) (gl_oset_t set, const void *elt);
  159. bool (*remove_elt) (gl_oset_t set, const void *elt);
  160. void (*oset_free) (gl_oset_t set);
  161. /* gl_oset_iterator_t functions. */
  162. gl_oset_iterator_t (*iterator) (gl_oset_t set);
  163. bool (*iterator_next) (gl_oset_iterator_t *iterator, const void **eltp);
  164. void (*iterator_free) (gl_oset_iterator_t *iterator);
  165. };
  166. struct gl_oset_impl_base
  167. {
  168. const struct gl_oset_implementation *vtable;
  169. gl_setelement_compar_fn compar_fn;
  170. gl_setelement_dispose_fn dispose_fn;
  171. };
  172. /* Define all functions of this file as accesses to the
  173. struct gl_oset_implementation. */
  174. GL_OSET_INLINE gl_oset_t
  175. gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
  176. gl_setelement_compar_fn compar_fn,
  177. gl_setelement_dispose_fn dispose_fn)
  178. {
  179. return implementation->nx_create_empty (implementation, compar_fn,
  180. dispose_fn);
  181. }
  182. GL_OSET_INLINE size_t
  183. gl_oset_size (gl_oset_t set)
  184. {
  185. return ((const struct gl_oset_impl_base *) set)->vtable->size (set);
  186. }
  187. GL_OSET_INLINE bool
  188. gl_oset_search (gl_oset_t set, const void *elt)
  189. {
  190. return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt);
  191. }
  192. GL_OSET_INLINE bool
  193. gl_oset_search_atleast (gl_oset_t set,
  194. gl_setelement_threshold_fn threshold_fn,
  195. const void *threshold, const void **eltp)
  196. {
  197. return ((const struct gl_oset_impl_base *) set)->vtable
  198. ->search_atleast (set, threshold_fn, threshold, eltp);
  199. }
  200. GL_OSET_INLINE int
  201. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
  202. __attribute__ ((__warn_unused_result__))
  203. #endif
  204. gl_oset_nx_add (gl_oset_t set, const void *elt)
  205. {
  206. return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt);
  207. }
  208. GL_OSET_INLINE bool
  209. gl_oset_remove (gl_oset_t set, const void *elt)
  210. {
  211. return ((const struct gl_oset_impl_base *) set)->vtable
  212. ->remove_elt (set, elt);
  213. }
  214. GL_OSET_INLINE void
  215. gl_oset_free (gl_oset_t set)
  216. {
  217. ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set);
  218. }
  219. GL_OSET_INLINE gl_oset_iterator_t
  220. gl_oset_iterator (gl_oset_t set)
  221. {
  222. return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set);
  223. }
  224. GL_OSET_INLINE bool
  225. gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
  226. {
  227. return iterator->vtable->iterator_next (iterator, eltp);
  228. }
  229. GL_OSET_INLINE void
  230. gl_oset_iterator_free (gl_oset_iterator_t *iterator)
  231. {
  232. iterator->vtable->iterator_free (iterator);
  233. }
  234. #ifdef __cplusplus
  235. }
  236. #endif
  237. _GL_INLINE_HEADER_END
  238. #endif /* _GL_OSET_H */