| // 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. |
| ------------------------------------------------------------------------------ |
| */ |