stretchy_buffer.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // stretchy_buffer.h - v1.04 - public domain - nothings.org/stb
  2. // a vector<>-like dynamic array for C
  3. //
  4. // version history:
  5. // 1.04 - fix warning
  6. // 1.03 - compile as C++ maybe
  7. // 1.02 - tweaks to syntax for no good reason
  8. // 1.01 - added a "common uses" documentation section
  9. // 1.0 - fixed bug in the version I posted prematurely
  10. // 0.9 - rewrite to try to avoid strict-aliasing optimization
  11. // issues, but won't compile as C++
  12. //
  13. // Will probably not work correctly with strict-aliasing optimizations.
  14. //
  15. // The idea:
  16. //
  17. // This implements an approximation to C++ vector<> for C, in that it
  18. // provides a generic definition for dynamic arrays which you can
  19. // still access in a typesafe way using arr[i] or *(arr+i). However,
  20. // it is simply a convenience wrapper around the common idiom of
  21. // of keeping a set of variables (in a struct or globals) which store
  22. // - pointer to array
  23. // - the length of the "in-use" part of the array
  24. // - the current size of the allocated array
  25. //
  26. // I find it to be the single most useful non-built-in-structure when
  27. // programming in C (hash tables a close second), but to be clear
  28. // it lacks many of the capabilities of C++ vector<>: there is no
  29. // range checking, the object address isn't stable (see next section
  30. // for details), the set of methods available is small (although
  31. // the file stb.h has another implementation of stretchy buffers
  32. // called 'stb_arr' which provides more methods, e.g. for insertion
  33. // and deletion).
  34. //
  35. // How to use:
  36. //
  37. // Unlike other stb header file libraries, there is no need to
  38. // define an _IMPLEMENTATION symbol. Every #include creates as
  39. // much implementation is needed.
  40. //
  41. // stretchy_buffer.h does not define any types, so you do not
  42. // need to #include it to before defining data types that are
  43. // stretchy buffers, only in files that *manipulate* stretchy
  44. // buffers.
  45. //
  46. // If you want a stretchy buffer aka dynamic array containing
  47. // objects of TYPE, declare such an array as:
  48. //
  49. // TYPE *myarray = NULL;
  50. //
  51. // (There is no typesafe way to distinguish between stretchy
  52. // buffers and regular arrays/pointers; this is necessary to
  53. // make ordinary array indexing work on these objects.)
  54. //
  55. // Unlike C++ vector<>, the stretchy_buffer has the same
  56. // semantics as an object that you manually malloc and realloc.
  57. // The pointer may relocate every time you add a new object
  58. // to it, so you:
  59. //
  60. // 1. can't take long-term pointers to elements of the array
  61. // 2. have to return the pointer from functions which might expand it
  62. // (either as a return value or by storing it to a ptr-to-ptr)
  63. //
  64. // Now you can do the following things with this array:
  65. //
  66. // sb_free(TYPE *a) free the array
  67. // sb_count(TYPE *a) the number of elements in the array
  68. // sb_push(TYPE *a, TYPE v) adds v on the end of the array, a la push_back
  69. // sb_add(TYPE *a, int n) adds n uninitialized elements at end of array & returns pointer to first added
  70. // sb_last(TYPE *a) returns an lvalue of the last item in the array
  71. // a[n] access the nth (counting from 0) element of the array
  72. //
  73. // #define STRETCHY_BUFFER_NO_SHORT_NAMES to only export
  74. // names of the form 'stb_sb_' if you have a name that would
  75. // otherwise collide.
  76. //
  77. // Note that these are all macros and many of them evaluate
  78. // their arguments more than once, so the arguments should
  79. // be side-effect-free.
  80. //
  81. // Note that 'TYPE *a' in sb_push and sb_add must be lvalues
  82. // so that the library can overwrite the existing pointer if
  83. // the object has to be reallocated.
  84. //
  85. // In an out-of-memory condition, the code will try to
  86. // set up a null-pointer or otherwise-invalid-pointer
  87. // exception to happen later. It's possible optimizing
  88. // compilers could detect this write-to-null statically
  89. // and optimize away some of the code, but it should only
  90. // be along the failure path. Nevertheless, for more security
  91. // in the face of such compilers, #define STRETCHY_BUFFER_OUT_OF_MEMORY
  92. // to a statement such as assert(0) or exit(1) or something
  93. // to force a failure when out-of-memory occurs.
  94. //
  95. // Common use:
  96. //
  97. // The main application for this is when building a list of
  98. // things with an unknown quantity, either due to loading from
  99. // a file or through a process which produces an unpredictable
  100. // number.
  101. //
  102. // My most common idiom is something like:
  103. //
  104. // SomeStruct *arr = NULL;
  105. // while (something)
  106. // {
  107. // SomeStruct new_one;
  108. // new_one.whatever = whatever;
  109. // new_one.whatup = whatup;
  110. // new_one.foobar = barfoo;
  111. // sb_push(arr, new_one);
  112. // }
  113. //
  114. // and various closely-related factorings of that. For example,
  115. // you might have several functions to create/init new SomeStructs,
  116. // and if you use the above idiom, you might prefer to make them
  117. // return structs rather than take non-const-pointers-to-structs,
  118. // so you can do things like:
  119. //
  120. // SomeStruct *arr = NULL;
  121. // while (something)
  122. // {
  123. // if (case_A) {
  124. // sb_push(arr, some_func1());
  125. // } else if (case_B) {
  126. // sb_push(arr, some_func2());
  127. // } else {
  128. // sb_push(arr, some_func3());
  129. // }
  130. // }
  131. //
  132. // Note that the above relies on the fact that sb_push doesn't
  133. // evaluate its second argument more than once. The macros do
  134. // evaluate the *array* argument multiple times, and numeric
  135. // arguments may be evaluated multiple times, but you can rely
  136. // on the second argument of sb_push being evaluated only once.
  137. //
  138. // Of course, you don't have to store bare objects in the array;
  139. // if you need the objects to have stable pointers, store an array
  140. // of pointers instead:
  141. //
  142. // SomeStruct **arr = NULL;
  143. // while (something)
  144. // {
  145. // SomeStruct *new_one = malloc(sizeof(*new_one));
  146. // new_one->whatever = whatever;
  147. // new_one->whatup = whatup;
  148. // new_one->foobar = barfoo;
  149. // sb_push(arr, new_one);
  150. // }
  151. //
  152. // How it works:
  153. //
  154. // A long-standing tradition in things like malloc implementations
  155. // is to store extra data before the beginning of the block returned
  156. // to the user. The stretchy buffer implementation here uses the
  157. // same trick; the current-count and current-allocation-size are
  158. // stored before the beginning of the array returned to the user.
  159. // (This means you can't directly free() the pointer, because the
  160. // allocated pointer is different from the type-safe pointer provided
  161. // to the user.)
  162. //
  163. // The details are trivial and implementation is straightforward;
  164. // the main trick is in realizing in the first place that it's
  165. // possible to do this in a generic, type-safe way in C.
  166. //
  167. // Contributors:
  168. //
  169. // Timothy Wright (github:ZenToad)
  170. //
  171. // LICENSE
  172. //
  173. // See end of file for license information.
  174. #ifndef STB_STRETCHY_BUFFER_H_INCLUDED
  175. #define STB_STRETCHY_BUFFER_H_INCLUDED
  176. #ifndef NO_STRETCHY_BUFFER_SHORT_NAMES
  177. #define sb_free stb_sb_free
  178. #define sb_push stb_sb_push
  179. #define sb_count stb_sb_count
  180. #define sb_add stb_sb_add
  181. #define sb_last stb_sb_last
  182. #endif
  183. #define stb_sb_free(a) ((a) ? free(stb__sbraw(a)),0 : 0)
  184. #define stb_sb_push(a,v) (stb__sbmaybegrow(a,1), (a)[stb__sbn(a)++] = (v))
  185. #define stb_sb_count(a) ((a) ? stb__sbn(a) : 0)
  186. #define stb_sb_add(a,n) (stb__sbmaybegrow(a,n), stb__sbn(a)+=(n), &(a)[stb__sbn(a)-(n)])
  187. #define stb_sb_last(a) ((a)[stb__sbn(a)-1])
  188. #define stb__sbraw(a) ((int *) (void *) (a) - 2)
  189. #define stb__sbm(a) stb__sbraw(a)[0]
  190. #define stb__sbn(a) stb__sbraw(a)[1]
  191. #define stb__sbneedgrow(a,n) ((a)==0 || stb__sbn(a)+(n) >= stb__sbm(a))
  192. #define stb__sbmaybegrow(a,n) (stb__sbneedgrow(a,(n)) ? stb__sbgrow(a,n) : 0)
  193. #define stb__sbgrow(a,n) (*((void **)&(a)) = stb__sbgrowf((a), (n), sizeof(*(a))))
  194. #include <stdlib.h>
  195. static void * stb__sbgrowf(void *arr, int increment, int itemsize)
  196. {
  197. int dbl_cur = arr ? 2*stb__sbm(arr) : 0;
  198. int min_needed = stb_sb_count(arr) + increment;
  199. int m = dbl_cur > min_needed ? dbl_cur : min_needed;
  200. int *p = (int *) realloc(arr ? stb__sbraw(arr) : 0, itemsize * m + sizeof(int)*2);
  201. if (p) {
  202. if (!arr)
  203. p[1] = 0;
  204. p[0] = m;
  205. return p+2;
  206. } else {
  207. #ifdef STRETCHY_BUFFER_OUT_OF_MEMORY
  208. STRETCHY_BUFFER_OUT_OF_MEMORY ;
  209. #endif
  210. return (void *) (2*sizeof(int)); // try to force a NULL pointer exception later
  211. }
  212. }
  213. #endif // STB_STRETCHY_BUFFER_H_INCLUDED
  214. /*
  215. ------------------------------------------------------------------------------
  216. This software is available under 2 licenses -- choose whichever you prefer.
  217. ------------------------------------------------------------------------------
  218. ALTERNATIVE A - MIT License
  219. Copyright (c) 2017 Sean Barrett
  220. Permission is hereby granted, free of charge, to any person obtaining a copy of
  221. this software and associated documentation files (the "Software"), to deal in
  222. the Software without restriction, including without limitation the rights to
  223. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  224. of the Software, and to permit persons to whom the Software is furnished to do
  225. so, subject to the following conditions:
  226. The above copyright notice and this permission notice shall be included in all
  227. copies or substantial portions of the Software.
  228. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  229. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  230. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  231. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  232. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  233. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  234. SOFTWARE.
  235. ------------------------------------------------------------------------------
  236. ALTERNATIVE B - Public Domain (www.unlicense.org)
  237. This is free and unencumbered software released into the public domain.
  238. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  239. software, either in source code form or as a compiled binary, for any purpose,
  240. commercial or non-commercial, and by any means.
  241. In jurisdictions that recognize copyright laws, the author or authors of this
  242. software dedicate any and all copyright interest in the software to the public
  243. domain. We make this dedication for the benefit of the public at large and to
  244. the detriment of our heirs and successors. We intend this dedication to be an
  245. overt act of relinquishment in perpetuity of all present and future rights to
  246. this software under copyright law.
  247. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  248. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  249. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  250. AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  251. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  252. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  253. ------------------------------------------------------------------------------
  254. */