diff --git a/README.md b/README.md index 9445117..71a904a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ library | lastest version | category | description **stb_image.c** | 1.35 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 0.8 | graphics | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.93 | graphics | image writing to disk: PNG, TGA, BMP -**stretchy_buffer.h** | 1.0 | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ +**stretchy_buffer.h** | 1.01 | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stb_textedit.h** | 1.2 | UI | guts of a text editor for games etc implementing them from scratch **stb_dxt.h** | 1.04 | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | revised Perlin noise (3D input, 1D output) diff --git a/stretchy_buffer.h b/stretchy_buffer.h index b2fa5f6..967e076 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -1,10 +1,11 @@ -// stretchy_buffer.h - v1.0 - public domain - nothings.org/stb +// stretchy_buffer.h - v1.01 - public domain - nothings.org/stb // a vector<>-like dynamic array for C // // version history: -// 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++ +// 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. // @@ -88,6 +89,63 @@ // 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