<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
The following standard integer types are defined for use in the API. In your own code you can go ahead and just use the briefer names defined by IntegerTypes.

* unsigned types:
** ''stb_uchar''
** ''stb_uint''
* known-size types:
** ''stb_int8''
** ''stb_uint8''
** ''stb_int16''
** ''stb_uint16''
** ''stb_uint32''
** ''stb_int32''

`deg2rad(a)` -- converts the parameter from degrees to radians
`rad2deg(a)` -- converts the parameter from radians to degrees


@@The definition of these macros is suppressed if [[STB_ONLY]] is defined.@@
{{{
char **stb_getopt       ( int *argc, char **argv              );
char **stb_getopt_param ( int *argc, char **argv, char *param );
void   stb_getopt_free  ( char **opts                         );
}}}
stb_arrcount
`stb_reverse` reverses the order of the elements in an array
`stb_shuffle` randomly sorts an array using an LCG random generator (not mersenne twister, to avoid dealing with large state)
These functions share a single thread which can load data in the background through ~FILE-based I/O.

stb_bgio_read
stb_bgio_readf
stb_bgio_read_to
stb_bigio_readf_to
The BalancedBinaryTree system is a set of macros that allow you to create balanced binary search trees threaded directly into your data structure. (This means each structure cannot appear in multiple trees, unless you make a separate BST'd node structure that points to your actual structure.) @@The tree can only be "sorted" on a single field of your data structure (although that field can itself be a struct with multiple sub-fields.)@@

The implementation uses AA trees for simplicitly (where a ~Red-Black tree turns out to be a representation of 2-3-4 trees, the AA tree is a representation of 2-3 trees, and is reasonable competitive in performance).

You can work with the BST in two ways. You can create an explicit BST 'Tree' object, which represents the root abstractly. This structure will remain fixed in memory and behave like a normal data structure. Alternatively, you can directly operate on nodes of your tree, and keep track of the root yourself.

* BalancedBinaryTreeCompilationMacros
* BalancedBinaryTreeFunctions
You must use two macros to create a new BalancedBinaryTree.

* `stb_bst_fields(NFUNCNAME)` -- place this macro inside your structure; it will declare the fields needed for the BST to be threaded into your structure
* `stb_bst(TYPE,NFUNCNAME, TREE,FUNCNAME, VFIELD,VTYPE,COMPARE)`
** `TYPE` -- the datatype name of the structure you're defined previously, using stb_bst_fields
** `NFUNCNAME` -- a prefix for the functions that operation directly on nodes
** `TREE` -- a name for the tree datatype, which will be declared by the macro
** `FUNCNAME` -- a prefix for the functions that operate on `TREE`s
** `VFIELD` -- the field in TYPE which the tree is ordered on
** `VTYPE` -- the type of the VFIELD. it must be copyable
** `COMPARE` -- a comparison expression which takes inputs `VTYPE a` and `VTYPE b` and produces a value that is <0, 0, or >0 depending on the relative ordering of `a` and `b`

If you are going to do a lot of iteration, there is a variation that maintains parent pointers and might be faster:

* `stb_bst_fields` => `stb_bst_fields_parent`
* `stb_bst` => `stb_bst_parent`

When you define a BalancedBinaryTree, a number of functions are automatically defined.

@@In this example, we'll assume the NFUNCNAME prefix is `node_`, and the FUNCNAME prefix is `tree_`@@. See BalancedBinaryTreeCompilationMacros for more information.

* `tree_Init(tree)` -- initialize an already-allocated tree structure
* `tree_Insert(tree,item)` -- insert an element into the tree
* `tree_Remove(tree,item)` -- remove an element from the tree
* `tree_Next(tree,item)` -- return the successor to `item`
* `tree_Prev(tree,item)` -- return the predecessor to `item`
* `tree_First(tree)` -- return the first node in the tree
* `tree_Last(tree)` -- return the last node in the tree

* `node_insert(root,item)` -- insert `item` in the subtree rooted at `root`, returning the new root
* `node_remove(root,item)` -- remove `item` from the subtree rooted at `root`, returning the new root
* `node_last(root)` -- find the "rightmost" element in the subtree
* `node_first(root)` -- find the "leftmost" element of the subtree
* `node_next(root,node)` -- find the successor of the node
* `node_prev(root,node)` -- find the predecessor of the node
This is a collection of functions designed to let you write binary search code without having to remember the fencepost issues. It works by letting you call it in a loop, passing in the comparison results (rather than you providing a callback function).

To use, first you declare an `stb_search` object. Then you initialize it by calling one of:
* `stb_search_binary` -- search from `minv` to `maxv`, finding the smallest-indexed entry if `find_smallest` is true, else largest-indexed entry
* `stb_search_open` -- search bounded below, but not above; same parameters as above, but no `maxv`

Each of these functions returns a value called a //guess//. This is an index within the range where the target is. You should compare the target to the guess, to compute a `condition` value, which is equal to zero if they're identical, or less than or greater otherwise:

* goal < guess: `compare` < 0
* goal = guess: `compare` = 0
* goal > guess: `compare` > 0

Now, repeatedly call the function `stb_probe` in a loop. The parameters to stb_probe are:
* `s` - the `stb_search` object
* `compare` - the comparison value computed as above, either against the initial value returned from `stb_search_binary`, or returned from the most recent call to `stb_probe`.
* `result` - an int pointer where `stb_probe` stores the next guess

Check the return value of `stb_probe`. If it is non-zero, continue in a loop; if it is zero, you are done, and `*result` holds the last guess, which is either the earliest/latest index that matches the target, or some other element which doesn't match at all.

Then you repeatedly call
* `stb_search_probe`
`stb_bitcount` -- count bits in unsigned int
`stb_bitreverse` -- bitwise reverse of unsigned int
`stb_bitreverse8` -- bitwise reverse of unsigned char
`stb_is_pow2` -- TRUE if argument is a power of two
`stb_log2_floor` -- floor of log2 of argument, i.e. index of highest set bit
`stb_log2_ceil` -- ceiling of log2 of argument
`stb_lowbit8` -- index of lowest set bit
`stb_highbit8` -- index of highest set bit
An array of booleans. Also can think of it as a set of small integers.

For some reason this is written so everywhere it takes the size, you have to pass in the size in 32-bit units, i.e. the number of bits divided by 32. I may change this

`stb_bitset *` - base data type
`stb_bitset_new` - allocate a bit set of a specific size
`stb_bitset_clearall` -- clear all set bits
`stb_bitset_setall` -- set all clear bits
`stb_bitset_setbit` -- set a specific bit
`stb_bitset_clearbit` -- clear a specific bit
`stb_bitset_testbit` -- non-zero if the specified bit is set

`stb_bitset_union` -- allocates a new bitset that is the union of the parameters
`stb_bitset_getlist` -- returns a DynamicallySizedArray of all the set indices in a specific range
`stb_bitset_disjoint` -- returns TRUE if neither parameter has a set bit in the same position
`stb_bitset_disjoint_0` -- returns TRUE if neither parameter has a clear bit in the same position
`stb_bitset_subset` -- returns TRUE if all the set bits in `smaller` are also set in `bigger`.
`stb_bitset_unioneq_changed` -- for each set bit in `p1`, set the corresponding bit in `p0`; returns TRUE if `p0` changed


`stb_ischar` allows creation of new functions like `isspace` and `isdigit` with an extremely simple, convenient API -- essentially identical to `strchr` -- but fast O(1), rather than with the scanning overhead of `strchr`.

* `stb_ischar(char c, char *set)` -- returns non-zero if 'c' appears in 'set'

@@Strings passed to `stb_ischar` must be invariant.@@ They cannot change after they're called (or rather, the results of stb_ischar will be as if they did not change). If they must change, you can flush all cached information by calling `stb_ischar(0,NULL)`.

The intent is for them to be used with constant strings in the source code:
{{{
// skip whitespace
while (stb_ischar(*s, " \r\n\t"))
    ++s;

if (stb_ischar(*s, "0123456789abcdefABCDEF")) {
   // process a hex character
} else if (stb_ischar(*s, "[]{}()<>")) {
   // process a bracket
}
}}}
Behind the scenes, `stb_ischar` does a lot of work the //first// time you call it with a given string (by which I mean it builds a character-indexed bit-table, then caches that).

Successive calls to `stb_ischar` do not run quite as fast as something like `isalpha` because it is not hard-coded to a specific set. Instead, `stb_ischar` hashes the string pointer through a perfect-hashing table (guaranteeing it is found on the first probe), and then uses the result of that to determine the appropriate index table.

This means the first call to `stb_ischar` with a given string can be very slow, as perfect-hash-table generation is not exactly fast.
stb_adler32
stb_crc32
stb_crc32_block

stb_sha1
stb_sha1_file -- MSVC only
stb_sha1_readable
stb_clamp
Sliding-window dictionary compression, with no entropy encoding (stays on byte boundaries).

stb_compress
stb_decompress
stb_decompress_length

stb_compress_tofile
stb_compress_into_file
stb_decompress_fromfile

stb_compress_window
stb_compress_hashsize

stb_compress_stream_start
stb_compress_stream_end
stb_write
Manages a binary configuration file, in the style of the windows registry. 

stb_cfg_open
stb_cfg_close
stb_cfg_read
stb_cfg_read_string
stb_cfg_write
stb_cfg_write_string
stb_cfg_delete

Depends on HierarchicalAllocator, DynamicallySizedArray.
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
[[stb.h]] TagIndex
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
stb_delete_directory_recursive
stb_readdir_files
stb_readdir_files_mask
stb_readdir_subdirs
stb_readdir_free
stb_readdir_recursive
stb_dirtree_get -- caches using registry specification
stb_dirtree_get_dir -- specify the directory to store the cache file
stb_dirtree_get_with_file -- specify the cache file
stb_dirtree_free
''stb_dupe''

The traditional approach to finding a set of duplicate items in a collection is to sort them, then check adjacent pairs.

This requires O(n log n) time, which seems perfectly reasonable, but as computers and memory have gotten larger, the near-constant //log n// overhead has become a significant constant; large sets can be so slow to process that saving a factor of 10x can be worthwhile.

`stb_dupe` addresses this problem by using hashing to do duplicate finding, using O(n log log n) time instead.

stb_dupe_create
stb_dupe_add
stb_dupe_finish
stb_dupe_numsets
stb_dupe_set
stb_dupe_set_count
`stb_arr` is a ''dynamic array'' masquerading as a simple pointer. It is like C++ `vector<>`, but useable in C.

{{{
int *arr = NULL;
stb_arr_push(arr,1000);
stb_arr_push(arr,1002);
for (int i=0; i < stb_arr_len(arr); ++i)
   printf(%d ", arr[i]);
}}}

produces

{{{
1000 1002
}}}

and

{{{
int *arr = NULL;
stb_arr_push(arr,1000);
stb_arr_push(arr,1002);
stb_arr_setlen(arr,4);
arr[2] = 1005;
for (int i=0; i < stb_arr_len(arr); ++i)
   printf(%d ", arr[i]);
}}}

produces

{{{
1000 1002 1005 -834782132
}}}

where the fourth value is undefined, because arr[3] was allocated but never initialized.

See: [[stb_arr operations]], [[stb_arr idioms]]

<<<
Because it is a dynamic array addressed directly, when the array is resized the location of it may change. For this reason, many of these operations are macros which may write to the `stb_arr` parameter. @@You should not keep multiple pointers to the same `stb_arr` if it may change lengths.@@

Because of this use of the macro, it may //appear// that the same pointer is being used everywhere in the code (since the macros are transparently updating the //variable// containing the pointer, which actually changes). This becomes an issue if you //pass `stb_arr` pointers to other functions//, and those functions resize the array. In this situation, you must either pass a pointer to the pointer, or return the new pointer and copy if over the old one:
{{{
int *data = get_some_stb_arr();

data = function_that_updates_the_array(data);
}}}
<<<

Even though these issues are subtle and potentially bug-prone -- this is an extremely leaky abstraction -- I have found that it is nevertheless a massive productivity boost; you just need to be vaguely aware of what's going on under the hood so as to use the appropriate subset of programming techniques that work correctly.
`swap(TYPE,a,b)` -- Swaps an object of a of type TYPE with another object b. This is implemented essentially as
{{{
TYPE t = a; a = b; b = t;
}}}

which makes the macro unsafe, as its arguments are evaluated multiple times.  See [[Swap]] for a safe swap routine.

This macro is not an expression, but a statement.

@@The definition of `swap` is suppressed if [[STB_ONLY]] is defined.@@
stb_big32
stb_big16
stb_little32
stb_little16
stb_smalloc
stb_scalloc
stb_srealloc
stb_sfree
stb_ssize
stb_sstrdup
stb_fatal
stb_copyfile
stb_filelen
stb_file
stb_fileu
stb_filec

stb_stringfile
stb_stringfile_trimmed

stb_filewrite
stb_filewritestr


See also [[stb_stringfile|FileProcessingWholeFile]] and [[stb_stringfile_trimmed|FileProcessingWholeFile]].

* `stb_fgets` -- like `fgets()`, but always has a terminating `\0`
* `stb_fgets_malloc` -- reads to the next newline (using fgets()) and returns the result in a `malloc()`ed buffer
stb_fwrite32 -- write a 32-bit integer in native endian

stb_fput_ranged
stb_fget_ranged
stb_size_ranged

stb_fput_varlen
stb_fget_varlen
stb_size_varlen

stb_fput_varlenu
stb_fget_varlenu
stb_size_varlenu

MSVC only:
stb_fput_varlen64
stb_fget_varlen64
stb_size_varlen64


`stb_fullpath` expands a possibly-relative pathname into a fully-qualified pathname in a provided buffer.
stb_float_eq
stb_pointer_array_free
See [[Checksums]] for ~SHA-1.

* `stb_hash` -- string hash function
* `stb_hashlen` -- hash a string with an explicit length
* `stb_hash_fast` -- Paul Hsieh's string hash function

* `stb_hashptr` -- hash a pointer value (not the contents)
* `stb_hash_number` -- hash an integer

* `stb_rehash` -- rehashes a hash value (poorly), for secondary hashing
* `stb_rehash_improved` -- rehashes a hash value in a better way

The ~HashTable system is a collection of macros which generate new functions and datatypes when compiled, producing a new hash table.

The hash table is a mapping between a set of keys and corresponding values. Mapped pairs can be added and removed on the fly without limitation.  Key lookups, adds, and deletes all proceed at high speed, usually fast (amortized) O(1).

* HashTableCompilationMacros
* HashTableFunctions

Memory usage for a table with n elements is typically bound by 2.5*(sizeof(key)+sizeof(value)).

The implementation uses secondary hashing (by rehashing the first hash value--this limits the number of useful bits) to maintain O(1) performance. The hash table doubles in size when it grows too large, halves in size when it becomes too small, and is rebuilt at the same size if it becomes too full of 'delete markers'.
There are three macros for compiling [[HashTable]]s.

* `stb_define_hash` -- defines a basic hash table
* `stb_declare_hash` -- declares a hash table (e.g. to expose in a header file)
* `stb_define_hash_base` -- provides more control over creation

{{{
stb_define_hash(TYPE, NAME, KEY, EMPTY, DEL, HASH, VALUE)
}}}

The parameters to this macro are:

* `TYPE` -- the name of the hash table datatype (e.g. you elsewhere do `TYPE foo;`)
* `NAME` -- a name that is prefixed onto all the functions defined; typically you will want this to end with '_', the underscore character
* `KEY` -- the type of the key field in each pair; `==` must be useable on this type to determine if two items are equal
* `EMPTY` -- some value of type KEY which is used internally for empty slots (you can actually still use this as a valid key as well; the code just needs to know some value it can use for this purpose)
* `DEL` - some value of type KEY, different from EMPTY, which is also used internally, but can still be mapped
* `HASH` - a sequence of C code, without any unparenthesized commas, which computes the hash function for the variable `k` of type `KEY` and `return`s it
* `VALUE` - the type of the value field in each pair

So, for example:
* `stb_define_hash(int_string_hash, ish_, int, -1, -2, stb_hash_number, char *)`

Will define a typedef `int_string_hash` which maps from `int` to `char *`, using a bunch of functions prefixed with `ish_`. (See HashTableFunctions.)

{{{
stb_declare_hash(PREFIX, TYPE, NAME, KEY, VALUE)
}}}

This declares the datatypes and functions needed to refer to a given hash table, e.g. for use in a header file. The macro parameters are identical to those above.

{{{
stb_define_hash_base(TYPE, FIELDS, N, LOAD_FACTOR, 
    KEY, EMPTY, DEL, COPY, DISPOSE,
    SAFE, COMPARE, HASH,
    VALUE, HASVNULL, VNULL)
}}}

The parameters not described above are:

* `FIELDS` -- any extra fields to be added to the structure `TYPE`, default `STB_nofields`
* `LOAD_FACTOR` -- the load factor at which the hash table doubles in size; default 0.85
* `COPY` -- a function that is called on any key added to the hash table, default `STB_nocopy`
* `DISPOSE` -- a function (or macro) that is called on any key removed from the hash table, default `STB_nodelete`
* `COMPARE` -- an function (or macro) that returns TRUE if two `KEY`s are equal, default `STB_equal` (which just does `==`)
* `SAFE` -- either `STB_safecompare`, if it is safe to call `COMPARE` with the `DEL` key; or the default, `STB_nosafe`. (For example, StringHashTable uses strcmp(), but avoids calling it for DEL, which is `(void *) 1`.)
* `HASVNULL` -- either `STB_nullvalue`, meaining there is a value of type VALUE which you want to behave as a `NULL` sentinel, returned when a key isn't present, or the default `STB_nonullvalue` if there is no such VALUE
* `VNULL` -- an item of type VALUE to serve as a NULL sentinel if `STB_nullvalue`; or anything else otherwise (it is not compiled, but must be valid macro text, so for example `0`)



These functions are created for each [[HashTable]] you define, as well as those hash tables defined by the library.

For expository purposes, we assume a hash table name of `hash_`.

* `hash_create()` -- creates a new hash table and returns it.
* `hash_init(table, size)` -- creates a new hash table into previously-allocated storage, and initializes it to the specified size (it will grow dynamically, though, so don't fret the size too much). Returns 1 on success, 0 if malloc() fails.
* `hash_copy(table)` -- creates a copy of an existing table. Keys will be `COPY`d.

* `hash_destroy(table)` -- destroys an existing hash table (works for both `hash_create` and `hash_init`)
* `hash_memory_usage(table)` -- reports the memory usage of the hash table

* `hash_get_flag(table, key, pvalue)` -- returns TRUE if the key is in the table, and stores the corresponding value to *pvalue; otherwise returns FALSE
* `hash_get(table, key)` -- @@only defined if STB_nullvalue@@ returns the VALUE corresponding to key, or else returns VNULL
* `hash_getkey(table,key,pkey)` -- if key is in the table, returns the version of the key stored in the table (if this sounds odd, consider if the keys are strings)

* `hash_set(table,key,value)` -- maps key to value in the table, regardless of its previous state
* `hash_add(table,key,value)` -- maps key to value in the table //only// if the key isn't already present
* `hash_update(table,key,value)` -- maps key to value in the able //only// if the key //is// already present

* `hash_remove(table,key,pvalue)` -- if the key is not in the table, returns FALSE. Otherwise, returns TRUE after doing all of the following: If pvalue is not-null, stores the corresponding value to *pvalue. Then removes the mapping for the key in the table.
Inspired by http://swapped.cc/halloc

This is an allocator in which you "attach" one allocation to another, forming a tree of allocations. Whenever you free an allocation, the entire allocation subtree below it is also freed. Note that this is not intended for awesome performance or space usage, but to simplify programming, allowing you to omit many `free` operations.

* `stb_free` -- free an allocation made with `stb_malloc`*, and free the subtree below it
*`stb_malloc` -- create an allocation with an explicit parent
*`stb_realloc` -- reallocate a block create with `stb_malloc`*

Everything further is optional:

*`stb_realloc_c` -- if the block exists, reallocates normally; if it doesn't exist, it's created with the specified parent
* `stb_reassign` -- reassign an allocation from one parent to another

*`stb_malloc_global` -- create an allocation with no parent; same as using NULL as the parent to `stb_malloc`
*`stb_malloc_nofree` -- create an allocation with cannot be freed directly, only by freeing its parent (saves space); it also cannot be reassigned
*`stb_malloc_leaf` -- create an allocation which cannot have allocation descendents (saves space)
*`stb_malloc_raw` -- an allocation which cannot be freed directly, and cannot have descendents (saves the most space); it also cannot be reassigned. this allocation behaves like an arena allocator; it has essentially zero overhead.


These functions operate much like `strtok()`, but they require an output buffer, so they do not touch the string that is being scanned.

* `stb_strtok` -- like `strtok`, but copies the token into a separate buffer
* `stb_strtok_keep` -- like `stb_strtok`, but keeps the delimiter as part of the token
* `stb_strtok_invert` -- like `stb_strtok_keep`, but the delimiter character set is the inverse of the passed-in string. //(I don't seem to use this anywhere; why did I think it useful?!)//
* `stb_idict` -- map from integer to integer
** See HashTableFunctions; the  function prefix is `stb_idict_`
** `stb_idict_remove_all` -- deletes all entries from the dictionary without resizing it
@@The definitions of these types are suppressed if [[STB_ONLY]] is defined.@@

The following standard integer types are defined:

* unsigned types:
** ''uchar''
** ''ushort''
** ''uint''
** ''ulong''
* known-size types:
** ''uint8''
** ''int8''
** ''uint16''
** ''int16''
** ''uint32''
** ''int32''
i.e. "lex" from "lex/yacc". Implemented using stb_regex_matcher technology, so performance is nearly as good as lex/flex.

stb_lex_matcher
stb_lex_item
stb_lex_item_wild
stb_lex
stb_lerp
stb_unlerp
stb_linear_remap
stb_
stb_log
stb_log_fileline
stb_log_name
`M_PI` is macro defining a value for //pi//.

@@The definition of `M_PI` is suppressed if [[STB_ONLY]] is defined.@@
[[stb.h]]

Editing:
<<newTiddler label:"new TODO tiddler" tag:todo>>
[[todot]]
[[future possibilities]]
WikiText
stb_array_block_alloc
{{{
stb_malloc_checkall
stb_malloc_check_counter
stb_mcheck
}}}
stb_copy
stb_wrapper_malloc
stb_wrapper_free
stb_wrapper_realloc
stb_wrapper_calloc
stb_wrapper_listall
stb_wrapper_dump
stb_wrapper_allocsize
stb_wrapper_check
These functions use the Mersenne Twister algorithm to generate high-quality random numbers.

`stb_rand` -- returns a random 32-bit number 
`stb_frand` -- returns a random float from 0 to 1 
`stb_srand` -- seeds the random number generator from a 32-bit value

If you need a lighter-weight generator (with a smaller state), LCG generators with only 32-bits of state are available at [[randLCG]].
`stb_min(a,b)` -- computes the minimum of `a` and `b` for types defining > operation
`stb_max(a,b)` -- computes the maximum of `a` and `b` for types defining > operation

The following synonymous names are available unless disabled for [[STB_ONLY]]:
`min(a,b)`
`max(a,b)`
stb_processor_count
stb_force_uniprocessor
stb_newell_normal
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
stb_temp
stb_tempfree
The perfect hashing system lets you map from arbitrary integers (e.g. cast pointers to ints) to very small integers (e.g. appropriate to index a small table). It is used internally in ''stb.h'' in several places to provide extremely high-speed caches for associating information with pointers (for example CharacterSetTest).

`stb_perfect_create` -- create a perfect hash table for `n` values that are `unsigned int`s; each one is assigned a unique, small integer, and the range of those integers are from [0..size), where `size` is returned by stb_perfect_create.

`stb_perfect_hash` -- search for an unsigned int; returns the small integer corresponding to it (appropriate to index into some other table)

`stb_perfect_destroy` -- free memory used by a perfect hash table
`stb_plural` takes an integer `n` and returns either the empty string "" or the one-character string "s", depending on whether `n` objects would be referred to in the plural or not in English.

Sample usage:
{{{
printf("There are %d pig%s remaining.", n, stb_plural_count(n));
}}}
* `stb_ptrmap` -- map from pointer to pointer
** See HashTableFunctions; the function prefix is `stb_ptrmap_`
** `stb_ptrmap_new` -- use this rather than `stb_ptrmap_create`
** `stb_ptrmap_delete` -- use this rather than `stb_ptrmap_destroy`; it takes an additional parmeter which is a free-function to use on the ptrmap values (such as `free`)
** `stb_ptrmap_get` -- this is defined and returns NULL if the key isn't present

`stb_ps *` -- pointer set

`NULL` -- empty stb_ps

stb_ps_find
stb_ps_add
stb_ps_remove
stb_ps_remove_any
stb_ps_delete
stb_ps_count

stb_ps_copy
stb_ps_subset
stb_ps_eq

stb_ps_getlist
stb_ps_writelist

stb_ps_enum
stb_ps_fastlist
stb_ps_fastlist_valid
All of the following tables are implemented using HashTable; see HashTableFunctions for lists of the standard functions.

* [[stb_sdict|StringHashTable]] -- maps `char *` to `void *`
* [[stb_ptrmap|PointerHashTable]] -- maps `void *` to `void *`
* [[stb_idict|IntegerHashTable]] -- maps `int` to `int`
Type the text for 'New Tiddler'
stb_power_of_two_nearest_prime
* MersenneTwister
* [[randLCG]]
* ArrayShuffle
High performance; uses lazily-computed DFA (but doesn't support advanced features)

`stb_regex` -- automatically caches the compiled matcher, best for constant strings specified in the source

stb_regex_matcher
stb_matcher_match
stb_matcher_find
stb_matcher_free
`STB_DEBUG` causes certain operations to do additional debug tracking, or to report file/line information that they wouldn't otherwise.

It is automatically enabled if any of the macros `DEBUG`, `_DEBUG`, or `DBG` are defined.
This macro causes the header file to compile the definitions for all of the functions, rather than just the declarations.

''@@ This macro should be defined in ___exactly___ one C or C++ file, in the following manner: @@''

{{{
#define STB_DEFINE
#include <stb.h>
}}}
On win32 platforms, enables the FastMalloc malloc replacement and causes all references to malloc/realloc/free/calloc/strdup to call the FastMalloc functions. Does not define the functions globally, so won't work with external llibraries.

Enables a MallocWrapper and includes debug padding around each allocation. Implies [[STB_MALLOC_WRAPPER]].
Enables a MallocWrapper and enables the FastMalloc system. Implies [[STB_FASTMALLOC]] and [[STB_MALLOC_WRAPPER]].
Enables a MallocWrapper that places each allocation on a separate page, for debugging. Implies [[STB_MALLOC_WRAPPER_DEBUG]] and [[STB_MALLOC_WRAPPER]].
Disable thread support. Automatically defined on non-windows, since the thread code hasn't been ported yet.
Although almost all public symbols defined by //stb.h// begin with the prefix `stb_`, there are a few macros and types which do not for the sake of convenience and universality. If the macro `STB_ONLY` is defined, these definitions are suppressed, in the interests of avoiding namespace collisions:

<<tagging [[no prefix]]>>
Intended for the author's personal use, its meaning may change over time. Currently it just defines a Bool type for C code.
Compile in support for the Stua language
a portable public domain C/C++ utility library in one header file
stb.h documentation
http://nothings.org/stb/stb_h.html
"Templatized" sort functions implemented using quicksort with median-of-3; probably 2x faster than qsort()?

stb_define_sort
stb_declare_sort
stb_define_sort_static
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
You can implement a stack using the `stb_arr_push` and `stb_arr_pop` operations of DynamicallySizedArray.
* `stb_tolower` -- converts a string to lowercase in-place
* `stb_duplower` -- creates a new copy of a string, lowercased
* `stb_prefix(s,t)` -- does the string `s` start with the string `t`?
* `stb_prefixi(s,t)` -- same as `stb_prefix`, but case-insensitive

* `stb_suffix(s,t)` -- does the string `s` end with the string `t`?
* `stb_suffixi(s,t)` -- same as `stb_suffix`, but case-insensitive

* `stb_prefix_count(s,t)` -- returns the longest shared prefix of `s` & `t` (that is, the number of characters that are identical at the start)
`stb_strncpy` -- exactly like strcpy, but always writes a \0 at the end

See also SubstringMalloced.
*`stb_sdict` -- map from string to pointer
** See HashTableFunctions; the function prefix is `stb_sdict_`
** `stb_sdict_new(use_arena)` -- create a new sdict; if `use_arena` is TRUE, an arena allocator is used to manage the key storage, otherwise each key is `malloc()`ed separately; typically set `use_arena` TRUE if you're not doing any deletions
** `stb_sdict_delete` -- used to destroy an sdict created with `stb_sdict_new`
** `stb_sdict_get()` is avaiable and returns NULL if the key isn't present
** `stb_sdict_change()` -- sets a new value in the mapping for a key, and returns the old value (or NULL if none)
** `stb_sdict_count()` -- returns the number of mappings in the table
** `stb_sdict_for(sdict, ivar, kvar, vvar) { ... }` -- this macro allows you to iterate over the contents of the sdict; `ivar` must be an integer variable that is used internally by the macro; `kvar` is a `char *` and vvar is a `void *` which will be set to each value in turn.

* `stb_fixpath` -- Converts the `\` character to `/` in-place.
* `stb_splitpath` -- Extracts the path, filename, or extension, or any combination thereof, to a user-provided output buffer. Flags are any combination of `STB_PATH`, `STB_FILE`, or `STB_EXT` combined with a bitwise OR. As shorthand there is `STB_FILE_EXT` and {{{STB_PATH_FILE}}}. Returns the output buffer.
* `stb_splitpathdup` -- As above, but `malloc()`s a buffer to store the result in.
* `stb_replacedir` -- Given an output buffer, a filename and a target directory, places in the output buffer the same filename but located in the target directory. Unsafe.
* `stb_replaceext` -- Given an output buffer, a filename and an extension, places in the output buffer the same filename with the extension replaced with the new one. Unsafe.

See also [[stb_fullpath]].
* `stb_dupreplace` -- search and replace a substring with another substring; return value is `malloc()ed`.
* `stb_replaceinplace` -- search and replace a substring with another substring, in-place. The new string must be no longer than the old string.
See also WildcardSearchingAndMatching and RegularExpression.

* `stb_stristr` -- like `strstr()`, but case-insensitive
* `stb_strichr` -- like `strchr()`, but case-insensitive
* `stb_strchr2` -- searches for the presence of either of two characters, whichever is first
* `stb_strrchr2` -- searches for the presence of either of two characters starting from the end of the string, whichever is last. (These two functions are used primarily to search for the presence of either / or \ in paths on Windows.)
(See ImprovedStrtok for functions that do not perform allocations.)

The following functions tokenize a string into many substrings, and return the entire result as an array of strings of type `char **`, and a count of the substrings. To free this result, simply free the array of strings (all the data is packed into a single block to simplify deallocation).

Briefly:

* `stb_tokens` -- omits empty strings
* `stb_tokens_stripwhite` -- strips whitespace from tokens
* `stb_tokens_allowempty` -- allows empty strings
* `stb_tokens_withdelim` -- keeps delimiters at end of strings
* `stb_tokens_quoted` -- allows escaped delimiters in quoted strings

Verbosely:

* `stb_tokens` -- returns all strings separated by characters in `delimit`. If two delimiters are adjacent, an empty string is not produced. Similarly, if the string starts with a delimiter, or ends with one.
* `stb_tokens_stripwhite` -- the same as `stb_tokens`, but whitespace is removed from the beginning and ends of each substring
* `stb_tokens_allowempty` -- the same as `stb_tokens`, but empty tokens are produced between adjacent delimiters, or at the start or end
* `stb_tokens_withdelim` -- the same as `stb_tokens_allowempty`, but each substrings ends with the delimiter character that separated it from the next substring
* `stb_tokens_quoted` -- works like `stb_tokens_stripwhite`, except text within quotation marks do not have whitespace stripped, and the quotation marks are stripped (except two quotation marks in a row is in an escaped question mark--it results in one output quotation mark)
* `stb_skipwhite` -- skips past leading whitespace
* `stb_trimwhite` -- removes leading & trailing whitespace (deletes trailing whitespace in-place, then skips leading whitespace)
* `stb_skipnewline` -- if the string points to a newline, skips it. correctly handles LF, CR, ~CR-LF, and ~LF-CR.
Stua is an in-progress implementation of a Lua-like language. It is included in stb.h because it can be defined in only about 1000 lines of code given the facillities provided by stb.h (e.g. stb_lex, stb_idict).

[[Stua documentation|http://nothings.org/stb/stb_stua.html]]

@@Stua is not compiled in by default. Define STB_STUA to enable it.@@
.popup li a {display:block; padding:0.15em; font-weight:normal; cursor:pointer;}
`stb_substr` -- copies the first `n` characters (and a `\0`) into a `malloc()`ed buffer
stb_swap
Right now the documentation is extremely incomplete; most functions aren't documented at all, and those that are do not provide much detailed info, requiring you to read the header file to get the parameter information.

However, everything has been //tagged//, so you can take a look through the tags and get some sense of what functionality is available.

The following tags offer a good starting place:

* <<tag algorithm>>
* <<tag [[data structure]]>>
* <<tag [[memory management]]>>
* <<tag performance>>
* <<tag math>>
* <<tag strings>>
* <<tag [[memory movement]]>>
* <<tag [[file reading]]>>
* <<tag [[large feature]]>>
* <<tag clib>>



stb_mutex_new
stb_mutex_delete
stb_mutex_begin
stb_mutex_end
Fixed-size queue for sending data between threads. Functions can block or not. Flags to the 'new' function indicate whether there will be more than one quuer, and more than one dequeuer, which allows more efficient queueing and dequeueing (if there is only one of a given type, no synchronization is performed).

stb_threadq_new
stb_threadqueue_delete
stb_threadq_get
stb_threadq_get_block
stb_threadq_add
stb_threadq_add_block
stb_sync_new
stb_sync_delete
stb_sync_set_target
stb_sync_reach_and_wait
stb_sync_reach
stb_sem_new
stb_sem_new_extra
stb_sem_delete
stb_sem_waitfor
stb_sem_release
Global queue:

stb_work_numthreads
stb_work_maxunits
stb_work
stb_work_reach

Multiple queues:
stb_workq_new
stb_workq_new_flags
stb_workq_delete
stb_workq_numthreads
stb_workq
stb_workq_reach
stb_workq_length
"Portable" thread support; see also STB_NO_THREADS and <<tag threading>>.

stb_create_thread
stb_create_thread2
stb_destroy_thread
Like most wikis, ~TiddlyWiki supports a range of simplified character formatting:
| !To get | !Type this |h
| `Monospaced` | {{{`Monospaced`}}} (those are back-quotes) |
| ''Bold'' | {{{''Bold''}}} |
| ---Strikethrough--- | {{{---Strikethrough---}}} |
| ___Underline___ | {{{___Underline___}}} (that's three underline characters) |
| //Italic// | {{{//Italic//}}} |
| Superscript: 2^^3^^=8 | {{{2^^3^^=8}}} |
| Subscript: a~~ij~~ = -a~~ji~~ | {{{a~~ij~~ = -a~~ji~~}}} |
| @@highlight@@ | {{{@@highlight@@}}} |

Use {{{[[this]]}}} to force a link. Use {{{<<tag foo>>}}} to allow a reference to a tag "foo".

<<<
The highlight can also accept CSS syntax to directly style the text:
@@color:green;green coloured@@
@@background-color:#ff0000;color:#ffffff;red coloured@@
@@text-shadow:black 3px 3px 8px;font-size:18pt;display:block;margin:1em 1em 1em 1em;border:1px solid black;Access any CSS style@@
<<<

//For backwards compatibility, the following highlight syntax is also accepted://
{{{
@@bgcolor(#ff0000):color(#ffffff):red coloured@@
}}}
@@bgcolor(#ff0000):color(#ffffff):red coloured@@
stb_wildmatch
stb_wildmatchi
stb_wildfind
stb_wildfindi
stb_reg_open
stb_reg_close
stb_reg_read
stb_reg_read_string
stb_reg_write
stb_reg_write_string
High-quality word-wrapping (monospaced fonts only). Note that "high-quality" here means "better than pretty much every app I've ever looked at when dealing with the hard cases, like splitting a 'word' that is longer than one line".

stb_wordwrap
stb_wordwrapalloc
Most of these functions closely mimic functions in the C library, but typically provide better handling of edge cases, or a more convenient API.

A few of the functions have nothing corresponding the C library, but are obvious extensions of it.
Fix stb_fopen / stb_fclose to use a ptrmap so that we don't run out.

Stream processing: replace fwrite/fread etc. with our own functions as well. Then make stb_fopen_mem that can open a stream from memory, etc.
Components tagged //no prefix// do not have an `stb_` prefix at the beginning of their symbols.
stb_randLCG
stb_srandLCG
stb_frandLCG

stb_randLCG_explicit
stb_rand_define
[[stb.h|http://nothings.org/stb.h]] is a (theoretically) portable C utility library, which provides numerous features. It does not depend on any other libraries, and requires only the single header file, which contains both the declarations and the definitions of the functions.

The functions and systems are designed to simplify common programming tasks, to provide easy-to-use data structures for common tasks, and easy-to-use high performance structures for other cases.

All code can be compiled as either C or C++. (If compiled as C++, everything is given C linkage so it can still be accessed from C as well.) Some of the features are redundant to C++, so it is less interesting there unless you refuse to use the STL or something.

TagIndex is a good place to start exploring the features.


This documentation file is implemented with [[TiddlyWiki|http://www.tiddlywiki.com/]].
stb_arr_push in a loop

using stb_arr to manage memory; stb_arr_push a struct in a loop. can't take address of elements

stb_arr_push malloc()ed pointers in a loop

Set array length, then fill it out--avoids doubling cost, copying, not usually worth it? But less source text.

`NULL` -- an empty array initializer

`stb_arr_free` -- frees the stb_arr

`stb_arr_empty` -- is the array empty? (note the array can be non-NULL and empty, if it grew and shunk)
`stb_arr_len` -- number of elements in the array
`stb_arr_lastn` -- index of the last element of the array
`stb_arr_valid` -- is a given index within the array?
`stb_arr_end` -- is a given index past the end of the array (e.g. for iterating)

`stb_arr_last` -- returns the last element of the array as an lvalue; if the array is empty the results are undefined

`stb_arr_push` -- append an element to the array -- amortized O(1)
`stb_arr_add` -- add an uninitialized element to the end of the array
`stb_arr_addn` -- add `n` uninitialized elements to the end of the array
`stb_arr_insert` -- insert an element in the middle of the array; not O(1)
`stb_arr_insertn` -- insert `n` elements in the middle of the array; not O(1)

`stb_arr_pop` -- removes the last entry from the array, and "returns" it as an lvalue; if the array is empty the results are undefined. amortized O(1)
`stb_arr_delete` -- removes an element from the middle of the array
`stb_arr_deleten` -- removes `n` elements from the middle of the array
`stb_arr_fastdelete` -- removes an element from the middle of the array, swapping the last element over it. O(1), but changes the ordering

`stb_arr_setlen` -- force the length of the array to be a specific length; if this length is longer than the current length, the new entries will be uninitialized
`stb_arr_makevalid` -- force the length of the array to be //at least// a specific length; if this length is longer than the current length, the new entries will be uninitialized

`stb_arr_malloc` -- empty stb_arr with a HierarchicalAllocator parent; note that you don't need to free these specially, as the stb_arr keeps track of how it was allocated so as to reallocate and free correctly
`stb_arr_malloc_parent` -- all future stb_arr allocations get this parent

`stb_arr_storage` -- sizeof() all the array elements
`stb_arr_copy` -- creates a new `stb_arr` identical to the old one

@@The following operations manipulate internals of the stb_arr.@@

`stb_arrcurmax` -- the maximum number of array elements that can be in use without reallocating the array
`stb_arr_atleast` -- expands the internal array length to be at least this large
`stb_arr_setsize` -- sets the internal array length to be exactly this size; the length of the visible array is truncated if necessary


Todo-items that have been tagged, but need description
Functions marked "unsafe" are potential security holes, as they do things like accept an output buffer without an explicit size, so they can write over random memory.
stb_from_utf8
stb_to_utf8

stb__from_utf8
stb__to_utf8
`stb_rename`
`stb_fopen`
`stb_fclose`
`stb_fexists`