123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- // stretchy_buffer.h - v1.04 - public domain - nothings.org/stb
- // a vector<>-like dynamic array for C
- //
- // version history:
- // 1.04 - fix warning
- // 1.03 - compile as C++ maybe
- // 1.02 - tweaks to syntax for no good reason
- // 1.01 - added a "common uses" documentation section
- // 1.0 - fixed bug in the version I posted prematurely
- // 0.9 - rewrite to try to avoid strict-aliasing optimization
- // issues, but won't compile as C++
- //
- // Will probably not work correctly with strict-aliasing optimizations.
- //
- // The idea:
- //
- // This implements an approximation to C++ vector<> for C, in that it
- // provides a generic definition for dynamic arrays which you can
- // still access in a typesafe way using arr[i] or *(arr+i). However,
- // it is simply a convenience wrapper around the common idiom of
- // of keeping a set of variables (in a struct or globals) which store
- // - pointer to array
- // - the length of the "in-use" part of the array
- // - the current size of the allocated array
- //
- // I find it to be the single most useful non-built-in-structure when
- // programming in C (hash tables a close second), but to be clear
- // it lacks many of the capabilities of C++ vector<>: there is no
- // range checking, the object address isn't stable (see next section
- // for details), the set of methods available is small (although
- // the file stb.h has another implementation of stretchy buffers
- // called 'stb_arr' which provides more methods, e.g. for insertion
- // and deletion).
- //
- // How to use:
- //
- // Unlike other stb header file libraries, there is no need to
- // define an _IMPLEMENTATION symbol. Every #include creates as
- // much implementation is needed.
- //
- // stretchy_buffer.h does not define any types, so you do not
- // need to #include it to before defining data types that are
- // stretchy buffers, only in files that *manipulate* stretchy
- // buffers.
- //
- // If you want a stretchy buffer aka dynamic array containing
- // objects of TYPE, declare such an array as:
- //
- // TYPE *myarray = NULL;
- //
- // (There is no typesafe way to distinguish between stretchy
- // buffers and regular arrays/pointers; this is necessary to
- // make ordinary array indexing work on these objects.)
- //
- // Unlike C++ vector<>, the stretchy_buffer has the same
- // semantics as an object that you manually malloc and realloc.
- // The pointer may relocate every time you add a new object
- // to it, so you:
- //
- // 1. can't take long-term pointers to elements of the array
- // 2. have to return the pointer from functions which might expand it
- // (either as a return value or by storing it to a ptr-to-ptr)
- //
- // Now you can do the following things with this array:
- //
- // sb_free(TYPE *a) free the array
- // sb_count(TYPE *a) the number of elements in the array
- // sb_push(TYPE *a, TYPE v) adds v on the end of the array, a la push_back
- // sb_add(TYPE *a, int n) adds n uninitialized elements at end of array & returns pointer to first added
- // sb_last(TYPE *a) returns an lvalue of the last item in the array
- // a[n] access the nth (counting from 0) element of the array
- //
- // #define STRETCHY_BUFFER_NO_SHORT_NAMES to only export
- // names of the form 'stb_sb_' if you have a name that would
- // otherwise collide.
- //
- // Note that these are all macros and many of them evaluate
- // their arguments more than once, so the arguments should
- // be side-effect-free.
- //
- // Note that 'TYPE *a' in sb_push and sb_add must be lvalues
- // so that the library can overwrite the existing pointer if
- // the object has to be reallocated.
- //
- // In an out-of-memory condition, the code will try to
- // set up a null-pointer or otherwise-invalid-pointer
- // exception to happen later. It's possible optimizing
- // compilers could detect this write-to-null statically
- // and optimize away some of the code, but it should only
- // be along the failure path. Nevertheless, for more security
- // in the face of such compilers, #define STRETCHY_BUFFER_OUT_OF_MEMORY
- // to a statement such as assert(0) or exit(1) or something
- // to force a failure when out-of-memory occurs.
- //
- // Common use:
- //
- // The main application for this is when building a list of
- // things with an unknown quantity, either due to loading from
- // a file or through a process which produces an unpredictable
- // number.
- //
- // My most common idiom is something like:
- //
- // SomeStruct *arr = NULL;
- // while (something)
- // {
- // SomeStruct new_one;
- // new_one.whatever = whatever;
- // new_one.whatup = whatup;
- // new_one.foobar = barfoo;
- // sb_push(arr, new_one);
- // }
- //
- // and various closely-related factorings of that. For example,
- // you might have several functions to create/init new SomeStructs,
- // and if you use the above idiom, you might prefer to make them
- // return structs rather than take non-const-pointers-to-structs,
- // so you can do things like:
- //
- // SomeStruct *arr = NULL;
- // while (something)
- // {
- // if (case_A) {
- // sb_push(arr, some_func1());
- // } else if (case_B) {
- // sb_push(arr, some_func2());
- // } else {
- // sb_push(arr, some_func3());
- // }
- // }
- //
- // Note that the above relies on the fact that sb_push doesn't
- // evaluate its second argument more than once. The macros do
- // evaluate the *array* argument multiple times, and numeric
- // arguments may be evaluated multiple times, but you can rely
- // on the second argument of sb_push being evaluated only once.
- //
- // Of course, you don't have to store bare objects in the array;
- // if you need the objects to have stable pointers, store an array
- // of pointers instead:
- //
- // SomeStruct **arr = NULL;
- // while (something)
- // {
- // SomeStruct *new_one = malloc(sizeof(*new_one));
- // new_one->whatever = whatever;
- // new_one->whatup = whatup;
- // new_one->foobar = barfoo;
- // sb_push(arr, new_one);
- // }
- //
- // How it works:
- //
- // A long-standing tradition in things like malloc implementations
- // is to store extra data before the beginning of the block returned
- // to the user. The stretchy buffer implementation here uses the
- // same trick; the current-count and current-allocation-size are
- // stored before the beginning of the array returned to the user.
- // (This means you can't directly free() the pointer, because the
- // allocated pointer is different from the type-safe pointer provided
- // to the user.)
- //
- // The details are trivial and implementation is straightforward;
- // the main trick is in realizing in the first place that it's
- // possible to do this in a generic, type-safe way in C.
- //
- // Contributors:
- //
- // Timothy Wright (github:ZenToad)
- //
- // LICENSE
- //
- // See end of file for license information.
- #ifndef STB_STRETCHY_BUFFER_H_INCLUDED
- #define STB_STRETCHY_BUFFER_H_INCLUDED
- #ifndef NO_STRETCHY_BUFFER_SHORT_NAMES
- #define sb_free stb_sb_free
- #define sb_push stb_sb_push
- #define sb_count stb_sb_count
- #define sb_add stb_sb_add
- #define sb_last stb_sb_last
- #endif
- #define stb_sb_free(a) ((a) ? free(stb__sbraw(a)),0 : 0)
- #define stb_sb_push(a,v) (stb__sbmaybegrow(a,1), (a)[stb__sbn(a)++] = (v))
- #define stb_sb_count(a) ((a) ? stb__sbn(a) : 0)
- #define stb_sb_add(a,n) (stb__sbmaybegrow(a,n), stb__sbn(a)+=(n), &(a)[stb__sbn(a)-(n)])
- #define stb_sb_last(a) ((a)[stb__sbn(a)-1])
- #define stb__sbraw(a) ((int *) (void *) (a) - 2)
- #define stb__sbm(a) stb__sbraw(a)[0]
- #define stb__sbn(a) stb__sbraw(a)[1]
- #define stb__sbneedgrow(a,n) ((a)==0 || stb__sbn(a)+(n) >= stb__sbm(a))
- #define stb__sbmaybegrow(a,n) (stb__sbneedgrow(a,(n)) ? stb__sbgrow(a,n) : 0)
- #define stb__sbgrow(a,n) (*((void **)&(a)) = stb__sbgrowf((a), (n), sizeof(*(a))))
- #include <stdlib.h>
- static void * stb__sbgrowf(void *arr, int increment, int itemsize)
- {
- int dbl_cur = arr ? 2*stb__sbm(arr) : 0;
- int min_needed = stb_sb_count(arr) + increment;
- int m = dbl_cur > min_needed ? dbl_cur : min_needed;
- int *p = (int *) realloc(arr ? stb__sbraw(arr) : 0, itemsize * m + sizeof(int)*2);
- if (p) {
- if (!arr)
- p[1] = 0;
- p[0] = m;
- return p+2;
- } else {
- #ifdef STRETCHY_BUFFER_OUT_OF_MEMORY
- STRETCHY_BUFFER_OUT_OF_MEMORY ;
- #endif
- return (void *) (2*sizeof(int)); // try to force a NULL pointer exception later
- }
- }
- #endif // STB_STRETCHY_BUFFER_H_INCLUDED
- /*
- ------------------------------------------------------------------------------
- This software is available under 2 licenses -- choose whichever you prefer.
- ------------------------------------------------------------------------------
- ALTERNATIVE A - MIT License
- Copyright (c) 2017 Sean Barrett
- Permission is hereby granted, free of charge, to any person obtaining a copy of
- this software and associated documentation files (the "Software"), to deal in
- the Software without restriction, including without limitation the rights to
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is furnished to do
- so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- ------------------------------------------------------------------------------
- ALTERNATIVE B - Public Domain (www.unlicense.org)
- This is free and unencumbered software released into the public domain.
- Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
- software, either in source code form or as a compiled binary, for any purpose,
- commercial or non-commercial, and by any means.
- In jurisdictions that recognize copyright laws, the author or authors of this
- software dedicate any and all copyright interest in the software to the public
- domain. We make this dedication for the benefit of the public at large and to
- the detriment of our heirs and successors. We intend this dedication to be an
- overt act of relinquishment in perpetuity of all present and future rights to
- this software under copyright law.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ------------------------------------------------------------------------------
- */
|