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