|
@@ -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
|