1 /* stb.h - v2.35 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h
2 no warranty is offered or implied; use this code at your own risk
3
4 This is a single header file with a bunch of useful utilities
5 for getting stuff done in C/C++.
6
7 Documentation: http://nothings.org/stb/stb_h.html
8 Unit tests: http://nothings.org/stb/stb.c
9
10 ============================================================================
11 You MUST
12
13 #define STB_DEFINE
14
15 in EXACTLY _one_ C or C++ file that includes this header, BEFORE the
16 include, like this:
17
18 #define STB_DEFINE
19 #include "stb.h"
20
21 All other files should just #include "stb.h" without the #define.
22 ============================================================================
23
24 Version History
25
26 2.36 various fixes
27 2.35 fix clang-cl issues with swprintf
28 2.34 fix warnings
29 2.33 more fixes to random numbers
30 2.32 stb_intcmprev, stb_uidict, fix random numbers on Linux
31 2.31 stb_ucharcmp
32 2.30 MinGW fix
33 2.29 attempt to fix use of swprintf()
34 2.28 various new functionality
35 2.27 test _WIN32 not WIN32 in STB_THREADS
36 2.26 various warning & bugfixes
37 2.25 various warning & bugfixes
38 2.24 various warning & bugfixes
39 2.23 fix 2.22
40 2.22 64-bit fixes from '!='; fix stb_sdict_copy() to have preferred name
41 2.21 utf-8 decoder rejects "overlong" encodings; attempted 64-bit improvements
42 2.20 fix to hash "copy" function--reported by someone with handle "!="
43 2.19 ???
44 2.18 stb_readdir_subdirs_mask
45 2.17 stb_cfg_dir
46 2.16 fix stb_bgio_, add stb_bgio_stat(); begin a streaming wrapper
47 2.15 upgraded hash table template to allow:
48 - aggregate keys (explicit comparison func for EMPTY and DEL keys)
49 - "static" implementations (so they can be culled if unused)
50 2.14 stb_mprintf
51 2.13 reduce identifiable strings in STB_NO_STB_STRINGS
52 2.12 fix STB_ONLY -- lots of uint32s, TRUE/FALSE things had crept in
53 2.11 fix bug in stb_dirtree_get() which caused "c://path" sorts of stuff
54 2.10 STB_F(), STB_I() inline constants (also KI,KU,KF,KD)
55 2.09 stb_box_face_vertex_axis_side
56 2.08 bugfix stb_trimwhite()
57 2.07 colored printing in windows (why are we in 1985?)
58 2.06 comparison functions are now functions-that-return-functions and
59 accept a struct-offset as a parameter (not thread-safe)
60 2.05 compile and pass tests under Linux (but no threads); thread cleanup
61 2.04 stb_cubic_bezier_1d, smoothstep, avoid dependency on registry
62 2.03 ?
63 2.02 remove integrated documentation
64 2.01 integrate various fixes; stb_force_uniprocessor
65 2.00 revised stb_dupe to use multiple hashes
66 1.99 stb_charcmp
67 1.98 stb_arr_deleten, stb_arr_insertn
68 1.97 fix stb_newell_normal()
69 1.96 stb_hash_number()
70 1.95 hack stb__rec_max; clean up recursion code to use new functions
71 1.94 stb_dirtree; rename stb_extra to stb_ptrmap
72 1.93 stb_sem_new() API cleanup (no blockflag-starts blocked; use 'extra')
73 1.92 stb_threadqueue--multi reader/writer queue, fixed size or resizeable
74 1.91 stb_bgio_* for reading disk asynchronously
75 1.90 stb_mutex uses CRITICAL_REGION; new stb_sync primitive for thread
76 joining; workqueue supports stb_sync instead of stb_semaphore
77 1.89 support ';' in constant-string wildcards; stb_mutex wrapper (can
78 implement with EnterCriticalRegion eventually)
79 1.88 portable threading API (only for win32 so far); worker thread queue
80 1.87 fix wildcard handling in stb_readdir_recursive
81 1.86 support ';' in wildcards
82 1.85 make stb_regex work with non-constant strings;
83 beginnings of stb_introspect()
84 1.84 (forgot to make notes)
85 1.83 whoops, stb_keep_if_different wasn't deleting the temp file
86 1.82 bring back stb_compress from stb_file.h for cmirror
87 1.81 various bugfixes, STB_FASTMALLOC_INIT inits FASTMALLOC in release
88 1.80 stb_readdir returns utf8; write own utf8-utf16 because lib was wrong
89 1.79 stb_write
90 1.78 calloc() support for malloc wrapper, STB_FASTMALLOC
91 1.77 STB_FASTMALLOC
92 1.76 STB_STUA - Lua-like language; (stb_image, stb_csample, stb_bilinear)
93 1.75 alloc/free array of blocks; stb_hheap bug; a few stb_ps_ funcs;
94 hash*getkey, hash*copy; stb_bitset; stb_strnicmp; bugfix stb_bst
95 1.74 stb_replaceinplace; use stdlib C function to convert utf8 to UTF-16
96 1.73 fix performance bug & leak in stb_ischar (C++ port lost a 'static')
97 1.72 remove stb_block, stb_block_manager, stb_decompress (to stb_file.h)
98 1.71 stb_trimwhite, stb_tokens_nested, etc.
99 1.70 back out 1.69 because it might problemize mixed builds; stb_filec()
100 1.69 (stb_file returns 'char *' in C++)
101 1.68 add a special 'tree root' data type for stb_bst; stb_arr_end
102 1.67 full C++ port. (stb_block_manager)
103 1.66 stb_newell_normal
104 1.65 stb_lex_item_wild -- allow wildcard items which MUST match entirely
105 1.64 stb_data
106 1.63 stb_log_name
107 1.62 stb_define_sort; C++ cleanup
108 1.61 stb_hash_fast -- Paul Hsieh's hash function (beats Bob Jenkins'?)
109 1.60 stb_delete_directory_recursive
110 1.59 stb_readdir_recursive
111 1.58 stb_bst variant with parent pointer for O(1) iteration, not O(log N)
112 1.57 replace LCG random with Mersenne Twister (found a public domain one)
113 1.56 stb_perfect_hash, stb_ischar, stb_regex
114 1.55 new stb_bst API allows multiple BSTs per node (e.g. secondary keys)
115 1.54 bugfix: stb_define_hash, stb_wildmatch, regexp
116 1.53 stb_define_hash; recoded stb_extra, stb_sdict use it
117 1.52 stb_rand_define, stb_bst, stb_reverse
118 1.51 fix 'stb_arr_setlen(NULL, 0)'
119 1.50 stb_wordwrap
120 1.49 minor improvements to enable the scripting language
121 1.48 better approach for stb_arr using stb_malloc; more invasive, clearer
122 1.47 stb_lex (lexes stb.h at 1.5ML/s on 3Ghz P4; 60/70% of optimal/flex)
123 1.46 stb_wrapper_*, STB_MALLOC_WRAPPER
124 1.45 lightly tested DFA acceleration of regexp searching
125 1.44 wildcard matching & searching; regexp matching & searching
126 1.43 stb_temp
127 1.42 allow stb_arr to use stb_malloc/realloc; note this is global
128 1.41 make it compile in C++; (disable stb_arr in C++)
129 1.40 stb_dupe tweak; stb_swap; stb_substr
130 1.39 stb_dupe; improve stb_file_max to be less stupid
131 1.38 stb_sha1_file: generate sha1 for file, even > 4GB
132 1.37 stb_file_max; partial support for utf8 filenames in Windows
133 1.36 remove STB__NO_PREFIX - poor interaction with IDE, not worth it
134 streamline stb_arr to make it separately publishable
135 1.35 bugfixes for stb_sdict, stb_malloc(0), stristr
136 1.34 (streaming interfaces for stb_compress)
137 1.33 stb_alloc; bug in stb_getopt; remove stb_overflow
138 1.32 (stb_compress returns, smaller&faster; encode window & 64-bit len)
139 1.31 stb_prefix_count
140 1.30 (STB__NO_PREFIX - remove stb_ prefixes for personal projects)
141 1.29 stb_fput_varlen64, etc.
142 1.28 stb_sha1
143 1.27 ?
144 1.26 stb_extra
145 1.25 ?
146 1.24 stb_copyfile
147 1.23 stb_readdir
148 1.22 ?
149 1.21 ?
150 1.20 ?
151 1.19 ?
152 1.18 ?
153 1.17 ?
154 1.16 ?
155 1.15 stb_fixpath, stb_splitpath, stb_strchr2
156 1.14 stb_arr
157 1.13 ?stb, stb_log, stb_fatal
158 1.12 ?stb_hash2
159 1.11 miniML
160 1.10 stb_crc32, stb_adler32
161 1.09 stb_sdict
162 1.08 stb_bitreverse, stb_ispow2, stb_big32
163 stb_fopen, stb_fput_varlen, stb_fput_ranged
164 stb_fcmp, stb_feq
165 1.07 (stb_encompress)
166 1.06 stb_compress
167 1.05 stb_tokens, (stb_hheap)
168 1.04 stb_rand
169 1.03 ?(s-strings)
170 1.02 ?stb_filelen, stb_tokens
171 1.01 stb_tolower
172 1.00 stb_hash, stb_intcmp
173 stb_file, stb_stringfile, stb_fgets
174 stb_prefix, stb_strlower, stb_strtok
175 stb_image
176 (stb_array), (stb_arena)
177
178 Parenthesized items have since been removed.
179
180 LICENSE
181
182 See end of file for license information.
183
184 CREDITS
185
186 Written by Sean Barrett.
187
188 Fixes:
189 Philipp Wiesemann
190 Robert Nix
191 r-lyeh
192 blackpawn
193 github:Mojofreem
194 Ryan Whitworth
195 Vincent Isambart
196 Mike Sartain
197 Eugene Opalev
198 Tim Sjostrand
199 github:infatum
200 Dave Butler (Croepha)
201 Ethan Lee (flibitijibibo)
202 Brian Collins
203 */
204
205 #include <stdarg.h>
206
207 #ifndef STB__INCLUDE_STB_H
208 #define STB__INCLUDE_STB_H
209
210 #define STB_VERSION 1
211
212 #ifdef STB_INTROSPECT
213 #define STB_DEFINE
214 #endif
215
216 #ifdef STB_DEFINE_THREADS
217 #ifndef STB_DEFINE
218 #define STB_DEFINE
219 #endif
220 #ifndef STB_THREADS
221 #define STB_THREADS
222 #endif
223 #endif
224
225 #if defined(_WIN32) && !defined(__MINGW32__)
226 #ifndef _CRT_SECURE_NO_WARNINGS
227 #define _CRT_SECURE_NO_WARNINGS
228 #endif
229 #ifndef _CRT_NONSTDC_NO_DEPRECATE
230 #define _CRT_NONSTDC_NO_DEPRECATE
231 #endif
232 #ifndef _CRT_NON_CONFORMING_SWPRINTFS
233 #define _CRT_NON_CONFORMING_SWPRINTFS
234 #endif
235 #if !defined(_MSC_VER) || _MSC_VER > 1700
236 #include <intrin.h> // _BitScanReverse
237 #endif
238 #endif
239
240 #include <stdlib.h> // stdlib could have min/max
241 #include <stdio.h> // need FILE
242 #include <string.h> // stb_define_hash needs memcpy/memset
243 #include <time.h> // stb_dirtree
244 #ifdef __MINGW32__
245 #include <fcntl.h> // O_RDWR
246 #endif
247
248 #ifdef STB_PERSONAL
249 typedef int Bool;
250 #define False 0
251 #define True 1
252 #endif
253
254 #ifdef STB_MALLOC_WRAPPER_PAGED
255 #define STB_MALLOC_WRAPPER_DEBUG
256 #endif
257 #ifdef STB_MALLOC_WRAPPER_DEBUG
258 #define STB_MALLOC_WRAPPER
259 #endif
260 #ifdef STB_MALLOC_WRAPPER_FASTMALLOC
261 #define STB_FASTMALLOC
262 #define STB_MALLOC_WRAPPER
263 #endif
264
265 #ifdef STB_FASTMALLOC
266 #ifndef _WIN32
267 #undef STB_FASTMALLOC
268 #endif
269 #endif
270
271 #ifdef STB_DEFINE
272 #include <assert.h>
273 #include <stdarg.h>
274 #include <stddef.h>
275 #include <ctype.h>
276 #include <math.h>
277 #ifndef _WIN32
278 #include <unistd.h>
279 #else
280 #include <io.h> // _mktemp
281 #include <direct.h> // _rmdir
282 #endif
283 #include <sys/types.h> // stat()/_stat()
284 #include <sys/stat.h> // stat()/_stat()
285 #endif
286
287 #define stb_min(a,b) ((a) < (b) ? (a) : (b))
288 #define stb_max(a,b) ((a) > (b) ? (a) : (b))
289
290 #ifndef STB_ONLY
291 #if !defined(__cplusplus) && !defined(min) && !defined(max)
292 #define min(x,y) stb_min(x,y)
293 #define max(x,y) stb_max(x,y)
294 #endif
295
296 #ifndef M_PI
297 #define M_PI 3.14159265358979323846f
298 #endif
299
300 #ifndef TRUE
301 #define TRUE 1
302 #define FALSE 0
303 #endif
304
305 #ifndef deg2rad
306 #define deg2rad(a) ((a)*(M_PI/180))
307 #endif
308 #ifndef rad2deg
309 #define rad2deg(a) ((a)*(180/M_PI))
310 #endif
311
312 #ifndef swap
313 #ifndef __cplusplus
314 #define swap(TYPE,a,b) \
315 do { TYPE stb__t; stb__t = (a); (a) = (b); (b) = stb__t; } while (0)
316 #endif
317 #endif
318
319 typedef unsigned char uint8 ;
320 typedef signed char int8 ;
321 typedef unsigned short uint16;
322 typedef signed short int16;
323 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
324 typedef unsigned long uint32;
325 typedef signed long int32;
326 #else
327 typedef unsigned int uint32;
328 typedef signed int int32;
329 #endif
330
331 typedef unsigned char uchar ;
332 typedef unsigned short ushort;
333 typedef unsigned int uint ;
334 typedef unsigned long ulong ;
335
336 // produce compile errors if the sizes aren't right
337 typedef char stb__testsize16[sizeof(int16)==2];
338 typedef char stb__testsize32[sizeof(int32)==4];
339 #endif
340
341 #ifndef STB_TRUE
342 #define STB_TRUE 1
343 #define STB_FALSE 0
344 #endif
345
346 // if we're STB_ONLY, can't rely on uint32 or even uint, so all the
347 // variables we'll use herein need typenames prefixed with 'stb':
348 typedef unsigned char stb_uchar;
349 typedef unsigned char stb_uint8;
350 typedef unsigned int stb_uint;
351 typedef unsigned short stb_uint16;
352 typedef short stb_int16;
353 typedef signed char stb_int8;
354 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
355 typedef unsigned long stb_uint32;
356 typedef long stb_int32;
357 #else
358 typedef unsigned int stb_uint32;
359 typedef int stb_int32;
360 #endif
361 typedef char stb__testsize2_16[sizeof(stb_uint16)==2 ? 1 : -1];
362 typedef char stb__testsize2_32[sizeof(stb_uint32)==4 ? 1 : -1];
363
364 #ifdef _MSC_VER
365 typedef unsigned __int64 stb_uint64;
366 typedef __int64 stb_int64;
367 #define STB_IMM_UINT64(literalui64) (literalui64##ui64)
368 #define STB_IMM_INT64(literali64) (literali64##i64)
369 #else
370 // ??
371 typedef unsigned long long stb_uint64;
372 typedef long long stb_int64;
373 #define STB_IMM_UINT64(literalui64) (literalui64##ULL)
374 #define STB_IMM_INT64(literali64) (literali64##LL)
375 #endif
376 typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1];
377
378 // add platform-specific ways of checking for sizeof(char*) == 8,
379 // and make those define STB_PTR64
380 #if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) || defined(__LP64__)
381 #define STB_PTR64
382 #endif
383
384 #ifdef STB_PTR64
385 typedef char stb__testsize2_ptr[sizeof(char *) == 8];
386 typedef stb_uint64 stb_uinta;
387 typedef stb_int64 stb_inta;
388 #else
389 typedef char stb__testsize2_ptr[sizeof(char *) == 4];
390 typedef stb_uint32 stb_uinta;
391 typedef stb_int32 stb_inta;
392 #endif
393 typedef char stb__testsize2_uinta[sizeof(stb_uinta)==sizeof(char*) ? 1 : -1];
394
395 // if so, we should define an int type that is the pointer size. until then,
396 // we'll have to make do with this (which is not the same at all!)
397
398 typedef union
399 {
400 unsigned int i;
401 void * p;
402 } stb_uintptr;
403
404
405 #ifdef __cplusplus
406 #define STB_EXTERN extern "C"
407 #else
408 #define STB_EXTERN extern
409 #endif
410
411 // check for well-known debug defines
412 #if defined(DEBUG) || defined(_DEBUG) || defined(DBG)
413 #ifndef NDEBUG
414 #define STB_DEBUG
415 #endif
416 #endif
417
418 #ifdef STB_DEBUG
419 #include <assert.h>
420 #endif
421
422 //////////////////////////////////////////////////////////////////////////////
423 //
424 // C library function platform handling
425 //
426
427 #ifdef STB_DEFINE
428
429 #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
stb_p_fopen(const char * filename,const char * mode)430 static FILE * stb_p_fopen(const char *filename, const char *mode)
431 {
432 FILE *f;
433 if (0 == fopen_s(&f, filename, mode))
434 return f;
435 else
436 return NULL;
437 }
stb_p_wfopen(const wchar_t * filename,const wchar_t * mode)438 static FILE * stb_p_wfopen(const wchar_t *filename, const wchar_t *mode)
439 {
440 FILE *f;
441 if (0 == _wfopen_s(&f, filename, mode))
442 return f;
443 else
444 return NULL;
445 }
stb_p_strcpy_s(char * a,size_t size,const char * b)446 static char *stb_p_strcpy_s(char *a, size_t size, const char *b)
447 {
448 strcpy_s(a,size,b);
449 return a;
450 }
stb_p_strncpy_s(char * a,size_t size,const char * b,size_t count)451 static char *stb_p_strncpy_s(char *a, size_t size, const char *b, size_t count)
452 {
453 strncpy_s(a,size,b,count);
454 return a;
455 }
456 #define stb_p_mktemp(s) (_mktemp_s(s, strlen(s)+1) == 0)
457 #define stb_p_sprintf sprintf_s
458 #define stb_p_size(x) ,(x)
459 #else
460 #define stb_p_fopen fopen
461 #define stb_p_wfopen _wfopen
462 #define stb_p_strcpy_s(a,s,b) strcpy(a,b)
463 #define stb_p_strncpy_s(a,s,b,c) strncpy(a,b,c)
464 #define stb_p_mktemp(s) (mktemp(s) != NULL)
465
466 #define stb_p_sprintf sprintf
467 #define stb_p_size(x)
468 #endif
469
470 #if defined(_WIN32)
471 #define stb_p_vsnprintf _vsnprintf
472 #else
473 #define stb_p_vsnprintf vsnprintf
474 #endif
475 #endif // STB_DEFINE
476
477 #if defined(_WIN32) && (_MSC_VER >= 1300)
478 #define stb_p_stricmp _stricmp
479 #define stb_p_strnicmp _strnicmp
480 #define stb_p_strdup _strdup
481 #else
482 #define stb_p_strdup strdup
483 #define stb_p_stricmp stricmp
484 #define stb_p_strnicmp strnicmp
485 #endif
486
487 STB_EXTERN void stb_wrapper_malloc(void *newp, size_t sz, char *file, int line);
488 STB_EXTERN void stb_wrapper_free(void *oldp, char *file, int line);
489 STB_EXTERN void stb_wrapper_realloc(void *oldp, void *newp, size_t sz, char *file, int line);
490 STB_EXTERN void stb_wrapper_calloc(size_t num, size_t sz, char *file, int line);
491 STB_EXTERN void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line));
492 STB_EXTERN void stb_wrapper_dump(char *filename);
493 STB_EXTERN size_t stb_wrapper_allocsize(void *oldp);
494 STB_EXTERN void stb_wrapper_check(void *oldp);
495
496 #ifdef STB_DEFINE
497 // this is a special function used inside malloc wrapper
498 // to do allocations that aren't tracked (to avoid
499 // reentrancy). Of course if someone _else_ wraps realloc,
500 // this breaks, but if they're doing that AND the malloc
501 // wrapper they need to explicitly check for reentrancy.
502 //
503 // only define realloc_raw() and we do realloc(NULL,sz)
504 // for malloc() and realloc(p,0) for free().
stb__realloc_raw(void * p,int sz)505 static void * stb__realloc_raw(void *p, int sz)
506 {
507 if (p == NULL) return malloc(sz);
508 if (sz == 0) { free(p); return NULL; }
509 return realloc(p,sz);
510 }
511 #endif
512
513 #ifdef _WIN32
514 STB_EXTERN void * stb_smalloc(size_t sz);
515 STB_EXTERN void stb_sfree(void *p);
516 STB_EXTERN void * stb_srealloc(void *p, size_t sz);
517 STB_EXTERN void * stb_scalloc(size_t n, size_t sz);
518 STB_EXTERN char * stb_sstrdup(char *s);
519 #endif
520
521 #ifdef STB_FASTMALLOC
522 #define malloc stb_smalloc
523 #define free stb_sfree
524 #define realloc stb_srealloc
525 #define strdup stb_sstrdup
526 #define calloc stb_scalloc
527 #endif
528
529 #ifndef STB_MALLOC_ALLCHECK
530 #define stb__check(p) 1
531 #else
532 #ifndef STB_MALLOC_WRAPPER
533 #error STB_MALLOC_ALLCHECK requires STB_MALLOC_WRAPPER
534 #else
535 #define stb__check(p) stb_mcheck(p)
536 #endif
537 #endif
538
539 #ifdef STB_MALLOC_WRAPPER
540 STB_EXTERN void * stb__malloc(size_t, char *, int);
541 STB_EXTERN void * stb__realloc(void *, size_t, char *, int);
542 STB_EXTERN void * stb__calloc(size_t n, size_t s, char *, int);
543 STB_EXTERN void stb__free(void *, char *file, int);
544 STB_EXTERN char * stb__strdup(char *s, char *file, int);
545 STB_EXTERN void stb_malloc_checkall(void);
546 STB_EXTERN void stb_malloc_check_counter(int init_delay, int rep_delay);
547 #ifndef STB_MALLOC_WRAPPER_DEBUG
548 #define stb_mcheck(p) 1
549 #else
550 STB_EXTERN int stb_mcheck(void *);
551 #endif
552
553
554 #ifdef STB_DEFINE
555
556 #ifdef STB_MALLOC_WRAPPER_DEBUG
557 #define STB__PAD 32
558 #define STB__BIAS 16
559 #define STB__SIG 0x51b01234
560 #define STB__FIXSIZE(sz) (((sz+3) & ~3) + STB__PAD)
561 #define STB__ptr(x,y) ((char *) (x) + (y))
562 #else
563 #define STB__ptr(x,y) (x)
564 #define STB__FIXSIZE(sz) (sz)
565 #endif
566
567 #ifdef STB_MALLOC_WRAPPER_DEBUG
stb_mcheck(void * p)568 int stb_mcheck(void *p)
569 {
570 unsigned int sz;
571 if (p == NULL) return 1;
572 p = ((char *) p) - STB__BIAS;
573 sz = * (unsigned int *) p;
574 assert(* (unsigned int *) STB__ptr(p,4) == STB__SIG);
575 assert(* (unsigned int *) STB__ptr(p,8) == STB__SIG);
576 assert(* (unsigned int *) STB__ptr(p,12) == STB__SIG);
577 assert(* (unsigned int *) STB__ptr(p,sz-4) == STB__SIG+1);
578 assert(* (unsigned int *) STB__ptr(p,sz-8) == STB__SIG+1);
579 assert(* (unsigned int *) STB__ptr(p,sz-12) == STB__SIG+1);
580 assert(* (unsigned int *) STB__ptr(p,sz-16) == STB__SIG+1);
581 stb_wrapper_check(STB__ptr(p, STB__BIAS));
582 return 1;
583 }
584
stb__check2(void * p,size_t sz,char * file,int line)585 static void stb__check2(void *p, size_t sz, char *file, int line)
586 {
587 stb_mcheck(p);
588 }
589
stb_malloc_checkall(void)590 void stb_malloc_checkall(void)
591 {
592 stb_wrapper_listall(stb__check2);
593 }
594 #else
stb_malloc_checkall(void)595 void stb_malloc_checkall(void) { }
596 #endif
597
598 static int stb__malloc_wait=(1 << 30), stb__malloc_next_wait = (1 << 30), stb__malloc_iter;
stb_malloc_check_counter(int init_delay,int rep_delay)599 void stb_malloc_check_counter(int init_delay, int rep_delay)
600 {
601 stb__malloc_wait = init_delay;
602 stb__malloc_next_wait = rep_delay;
603 }
604
stb_mcheck_all(void)605 void stb_mcheck_all(void)
606 {
607 #ifdef STB_MALLOC_WRAPPER_DEBUG
608 ++stb__malloc_iter;
609 if (--stb__malloc_wait <= 0) {
610 stb_malloc_checkall();
611 stb__malloc_wait = stb__malloc_next_wait;
612 }
613 #endif
614 }
615
616 #ifdef STB_MALLOC_WRAPPER_PAGED
617 #define STB__WINDOWS_PAGE (1 << 12)
618 #ifndef _WINDOWS_
619 STB_EXTERN __declspec(dllimport) void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
620 STB_EXTERN __declspec(dllimport) int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
621 #endif
622 #endif
623
stb__malloc_final(size_t sz)624 static void *stb__malloc_final(size_t sz)
625 {
626 #ifdef STB_MALLOC_WRAPPER_PAGED
627 size_t aligned = (sz + STB__WINDOWS_PAGE - 1) & ~(STB__WINDOWS_PAGE-1);
628 char *p = VirtualAlloc(NULL, aligned + STB__WINDOWS_PAGE, 0x2000, 0x04); // RESERVE, READWRITE
629 if (p == NULL) return p;
630 VirtualAlloc(p, aligned, 0x1000, 0x04); // COMMIT, READWRITE
631 return p;
632 #else
633 return malloc(sz);
634 #endif
635 }
636
stb__free_final(void * p)637 static void stb__free_final(void *p)
638 {
639 #ifdef STB_MALLOC_WRAPPER_PAGED
640 VirtualFree(p, 0, 0x8000); // RELEASE
641 #else
642 free(p);
643 #endif
644 }
645
646 int stb__malloc_failure;
647 #ifdef STB_MALLOC_WRAPPER_PAGED
stb__realloc_final(void * p,size_t sz,size_t old_sz)648 static void *stb__realloc_final(void *p, size_t sz, size_t old_sz)
649 {
650 void *q = stb__malloc_final(sz);
651 if (q == NULL)
652 return ++stb__malloc_failure, q;
653 // @TODO: deal with p being smaller!
654 memcpy(q, p, sz < old_sz ? sz : old_sz);
655 stb__free_final(p);
656 return q;
657 }
658 #endif
659
stb__free(void * p,char * file,int line)660 void stb__free(void *p, char *file, int line)
661 {
662 stb_mcheck_all();
663 if (!p) return;
664 #ifdef STB_MALLOC_WRAPPER_DEBUG
665 stb_mcheck(p);
666 #endif
667 stb_wrapper_free(p,file,line);
668 #ifdef STB_MALLOC_WRAPPER_DEBUG
669 p = STB__ptr(p,-STB__BIAS);
670 * (unsigned int *) STB__ptr(p,0) = 0xdeadbeef;
671 * (unsigned int *) STB__ptr(p,4) = 0xdeadbeef;
672 * (unsigned int *) STB__ptr(p,8) = 0xdeadbeef;
673 * (unsigned int *) STB__ptr(p,12) = 0xdeadbeef;
674 #endif
675 stb__free_final(p);
676 }
677
stb__malloc(size_t sz,char * file,int line)678 void * stb__malloc(size_t sz, char *file, int line)
679 {
680 void *p;
681 stb_mcheck_all();
682 if (sz == 0) return NULL;
683 p = stb__malloc_final(STB__FIXSIZE(sz));
684 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
685 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
686 if (p == NULL) {
687 ++stb__malloc_failure;
688 #ifdef STB_MALLOC_WRAPPER_DEBUG
689 stb_malloc_checkall();
690 #endif
691 return p;
692 }
693 #ifdef STB_MALLOC_WRAPPER_DEBUG
694 * (int *) STB__ptr(p,0) = STB__FIXSIZE(sz);
695 * (unsigned int *) STB__ptr(p,4) = STB__SIG;
696 * (unsigned int *) STB__ptr(p,8) = STB__SIG;
697 * (unsigned int *) STB__ptr(p,12) = STB__SIG;
698 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-4) = STB__SIG+1;
699 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-8) = STB__SIG+1;
700 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-12) = STB__SIG+1;
701 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-16) = STB__SIG+1;
702 p = STB__ptr(p, STB__BIAS);
703 #endif
704 stb_wrapper_malloc(p,sz,file,line);
705 return p;
706 }
707
stb__realloc(void * p,size_t sz,char * file,int line)708 void * stb__realloc(void *p, size_t sz, char *file, int line)
709 {
710 void *q;
711
712 stb_mcheck_all();
713 if (p == NULL) return stb__malloc(sz,file,line);
714 if (sz == 0 ) { stb__free(p,file,line); return NULL; }
715
716 #ifdef STB_MALLOC_WRAPPER_DEBUG
717 stb_mcheck(p);
718 p = STB__ptr(p,-STB__BIAS);
719 #endif
720 #ifdef STB_MALLOC_WRAPPER_PAGED
721 {
722 size_t n = stb_wrapper_allocsize(STB__ptr(p,STB__BIAS));
723 if (!n)
724 stb_wrapper_check(STB__ptr(p,STB__BIAS));
725 q = stb__realloc_final(p, STB__FIXSIZE(sz), STB__FIXSIZE(n));
726 }
727 #else
728 q = realloc(p, STB__FIXSIZE(sz));
729 #endif
730 if (q == NULL)
731 return ++stb__malloc_failure, q;
732 #ifdef STB_MALLOC_WRAPPER_DEBUG
733 * (int *) STB__ptr(q,0) = STB__FIXSIZE(sz);
734 * (unsigned int *) STB__ptr(q,4) = STB__SIG;
735 * (unsigned int *) STB__ptr(q,8) = STB__SIG;
736 * (unsigned int *) STB__ptr(q,12) = STB__SIG;
737 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-4) = STB__SIG+1;
738 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-8) = STB__SIG+1;
739 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-12) = STB__SIG+1;
740 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-16) = STB__SIG+1;
741
742 q = STB__ptr(q, STB__BIAS);
743 p = STB__ptr(p, STB__BIAS);
744 #endif
745 stb_wrapper_realloc(p,q,sz,file,line);
746 return q;
747 }
748
749 STB_EXTERN int stb_log2_ceil(size_t);
stb__calloc(size_t n,size_t sz,char * file,int line)750 static void *stb__calloc(size_t n, size_t sz, char *file, int line)
751 {
752 void *q;
753 stb_mcheck_all();
754 if (n == 0 || sz == 0) return NULL;
755 if (stb_log2_ceil(n) + stb_log2_ceil(sz) >= 32) return NULL;
756 q = stb__malloc(n*sz, file, line);
757 if (q) memset(q, 0, n*sz);
758 return q;
759 }
760
stb__strdup(char * s,char * file,int line)761 char * stb__strdup(char *s, char *file, int line)
762 {
763 char *p;
764 stb_mcheck_all();
765 p = stb__malloc(strlen(s)+1, file, line);
766 if (!p) return p;
767 stb_p_strcpy_s(p, strlen(s)+1, s);
768 return p;
769 }
770 #endif // STB_DEFINE
771
772 #ifdef STB_FASTMALLOC
773 #undef malloc
774 #undef realloc
775 #undef free
776 #undef strdup
777 #undef calloc
778 #endif
779
780 // include everything that might define these, BEFORE making macros
781 #include <stdlib.h>
782 #include <string.h>
783 #include <malloc.h>
784
785 #define malloc(s) stb__malloc ( s, __FILE__, __LINE__)
786 #define realloc(p,s) stb__realloc(p,s, __FILE__, __LINE__)
787 #define calloc(n,s) stb__calloc (n,s, __FILE__, __LINE__)
788 #define free(p) stb__free (p, __FILE__, __LINE__)
789 #define strdup(p) stb__strdup (p, __FILE__, __LINE__)
790 #endif
791
792 //////////////////////////////////////////////////////////////////////////////
793 //
794 // Windows pretty display
795 //
796
797 STB_EXTERN void stbprint(const char *fmt, ...);
798 STB_EXTERN char *stb_sprintf(const char *fmt, ...);
799 STB_EXTERN char *stb_mprintf(const char *fmt, ...);
800 STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...);
801 STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v);
802
803 #ifdef STB_DEFINE
stb_vsnprintf(char * s,size_t n,const char * fmt,va_list v)804 int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v)
805 {
806 int res;
807 #ifdef _WIN32
808 #ifdef __STDC_WANT_SECURE_LIB__
809 res = _vsnprintf_s(s, n, _TRUNCATE, fmt, v);
810 #else
811 res = stb_p_vsnprintf(s,n,fmt,v);
812 #endif
813 #else
814 res = vsnprintf(s,n,fmt,v);
815 #endif
816 if (n) s[n-1] = 0;
817 // Unix returns length output would require, Windows returns negative when truncated.
818 return (res >= (int) n || res < 0) ? -1 : res;
819 }
820
stb_snprintf(char * s,size_t n,const char * fmt,...)821 int stb_snprintf(char *s, size_t n, const char *fmt, ...)
822 {
823 int res;
824 va_list v;
825 va_start(v,fmt);
826 res = stb_vsnprintf(s, n, fmt, v);
827 va_end(v);
828 return res;
829 }
830
stb_sprintf(const char * fmt,...)831 char *stb_sprintf(const char *fmt, ...)
832 {
833 static char buffer[1024];
834 va_list v;
835 va_start(v,fmt);
836 stb_vsnprintf(buffer,1024,fmt,v);
837 va_end(v);
838 return buffer;
839 }
840
stb_mprintf(const char * fmt,...)841 char *stb_mprintf(const char *fmt, ...)
842 {
843 static char buffer[1024];
844 va_list v;
845 va_start(v,fmt);
846 stb_vsnprintf(buffer,1024,fmt,v);
847 va_end(v);
848 return stb_p_strdup(buffer);
849 }
850
851 #ifdef _WIN32
852
853 #ifndef _WINDOWS_
854 STB_EXTERN __declspec(dllimport) int __stdcall WriteConsoleA(void *, const void *, unsigned int, unsigned int *, void *);
855 STB_EXTERN __declspec(dllimport) void * __stdcall GetStdHandle(unsigned int);
856 STB_EXTERN __declspec(dllimport) int __stdcall SetConsoleTextAttribute(void *, unsigned short);
857 #endif
858
stb__print_one(void * handle,char * s,ptrdiff_t len)859 static void stb__print_one(void *handle, char *s, ptrdiff_t len)
860 {
861 if (len)
862 if (0==WriteConsoleA(handle, s, (unsigned) len, NULL,NULL))
863 // if it fails, maybe redirected, so output normally...
864 // but it's supriously reporting failure now on Win7 and later
865 {}//fwrite(s, 1, (unsigned) len, stdout);
866 }
867
stb__print(char * s)868 static void stb__print(char *s)
869 {
870 void *handle = GetStdHandle((unsigned int) -11); // STD_OUTPUT_HANDLE
871 int pad=0; // number of padding characters to add
872
873 char *t = s;
874 while (*s) {
875 int lpad;
876 while (*s && *s != '{') {
877 if (pad) {
878 if (*s == '\r' || *s == '\n')
879 pad = 0;
880 else if (s[0] == ' ' && s[1] == ' ') {
881 stb__print_one(handle, t, s-t);
882 t = s;
883 while (pad) {
884 stb__print_one(handle, t, 1);
885 --pad;
886 }
887 }
888 }
889 ++s;
890 }
891 if (!*s) break;
892 stb__print_one(handle, t, s-t);
893 if (s[1] == '{') {
894 ++s;
895 continue;
896 }
897
898 if (s[1] == '#') {
899 t = s+3;
900 if (isxdigit(s[2]))
901 if (isdigit(s[2]))
902 SetConsoleTextAttribute(handle, s[2] - '0');
903 else
904 SetConsoleTextAttribute(handle, tolower(s[2]) - 'a' + 10);
905 else {
906 SetConsoleTextAttribute(handle, 0x0f);
907 t=s+2;
908 }
909 } else if (s[1] == '!') {
910 SetConsoleTextAttribute(handle, 0x0c);
911 t = s+2;
912 } else if (s[1] == '@') {
913 SetConsoleTextAttribute(handle, 0x09);
914 t = s+2;
915 } else if (s[1] == '$') {
916 SetConsoleTextAttribute(handle, 0x0a);
917 t = s+2;
918 } else {
919 SetConsoleTextAttribute(handle, 0x08); // 0,7,8,15 => shades of grey
920 t = s+1;
921 }
922
923 lpad = (int) (t-s);
924 s = t;
925 while (*s && *s != '}') ++s;
926 if (!*s) break;
927 stb__print_one(handle, t, s-t);
928 if (s[1] == '}') {
929 t = s+2;
930 } else {
931 pad += 1+lpad;
932 t = s+1;
933 }
934 s=t;
935 SetConsoleTextAttribute(handle, 0x07);
936 }
937 stb__print_one(handle, t, s-t);
938 SetConsoleTextAttribute(handle, 0x07);
939 }
940
stbprint(const char * fmt,...)941 void stbprint(const char *fmt, ...)
942 {
943 int res;
944 char buffer[1024];
945 char *tbuf = buffer;
946 va_list v;
947
948 va_start(v,fmt);
949 res = stb_vsnprintf(buffer, sizeof(buffer), fmt, v);
950 va_end(v);
951
952 if (res < 0) {
953 tbuf = (char *) malloc(16384);
954 va_start(v,fmt);
955 res = stb_vsnprintf(tbuf,16384, fmt, v);
956 va_end(v);
957 tbuf[16383] = 0;
958 }
959
960 stb__print(tbuf);
961
962 if (tbuf != buffer)
963 free(tbuf);
964 }
965
966 #else // _WIN32
stbprint(const char * fmt,...)967 void stbprint(const char *fmt, ...)
968 {
969 va_list v;
970 va_start(v,fmt);
971 vprintf(fmt,v);
972 va_end(v);
973 }
974 #endif // _WIN32
975 #endif // STB_DEFINE
976
977
978
979 //////////////////////////////////////////////////////////////////////////////
980 //
981 // Windows UTF8 filename handling
982 //
983 // Windows stupidly treats 8-bit filenames as some dopey code page,
984 // rather than utf-8. If we want to use utf8 filenames, we have to
985 // convert them to WCHAR explicitly and call WCHAR versions of the
986 // file functions. So, ok, we do.
987
988
989 #ifdef _WIN32
990 #define stb__fopen(x,y) stb_p_wfopen((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
991 #define stb__windows(x,y) x
992 #else
993 #define stb__fopen(x,y) stb_p_fopen(x,y)
994 #define stb__windows(x,y) y
995 #endif
996
997
998 typedef unsigned short stb__wchar;
999
1000 STB_EXTERN stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *str, int n);
1001 STB_EXTERN char * stb_to_utf8 (char *buffer, const stb__wchar *str, int n);
1002
1003 STB_EXTERN stb__wchar *stb__from_utf8(const char *str);
1004 STB_EXTERN stb__wchar *stb__from_utf8_alt(const char *str);
1005 STB_EXTERN char *stb__to_utf8(const stb__wchar *str);
1006
1007
1008 #ifdef STB_DEFINE
stb_from_utf8(stb__wchar * buffer,const char * ostr,int n)1009 stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *ostr, int n)
1010 {
1011 unsigned char *str = (unsigned char *) ostr;
1012 stb_uint32 c;
1013 int i=0;
1014 --n;
1015 while (*str) {
1016 if (i >= n)
1017 return NULL;
1018 if (!(*str & 0x80))
1019 buffer[i++] = *str++;
1020 else if ((*str & 0xe0) == 0xc0) {
1021 if (*str < 0xc2) return NULL;
1022 c = (*str++ & 0x1f) << 6;
1023 if ((*str & 0xc0) != 0x80) return NULL;
1024 buffer[i++] = c + (*str++ & 0x3f);
1025 } else if ((*str & 0xf0) == 0xe0) {
1026 if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return NULL;
1027 if (*str == 0xed && str[1] > 0x9f) return NULL; // str[1] < 0x80 is checked below
1028 c = (*str++ & 0x0f) << 12;
1029 if ((*str & 0xc0) != 0x80) return NULL;
1030 c += (*str++ & 0x3f) << 6;
1031 if ((*str & 0xc0) != 0x80) return NULL;
1032 buffer[i++] = c + (*str++ & 0x3f);
1033 } else if ((*str & 0xf8) == 0xf0) {
1034 if (*str > 0xf4) return NULL;
1035 if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return NULL;
1036 if (*str == 0xf4 && str[1] > 0x8f) return NULL; // str[1] < 0x80 is checked below
1037 c = (*str++ & 0x07) << 18;
1038 if ((*str & 0xc0) != 0x80) return NULL;
1039 c += (*str++ & 0x3f) << 12;
1040 if ((*str & 0xc0) != 0x80) return NULL;
1041 c += (*str++ & 0x3f) << 6;
1042 if ((*str & 0xc0) != 0x80) return NULL;
1043 c += (*str++ & 0x3f);
1044 // utf-8 encodings of values used in surrogate pairs are invalid
1045 if ((c & 0xFFFFF800) == 0xD800) return NULL;
1046 if (c >= 0x10000) {
1047 c -= 0x10000;
1048 if (i + 2 > n) return NULL;
1049 buffer[i++] = 0xD800 | (0x3ff & (c >> 10));
1050 buffer[i++] = 0xDC00 | (0x3ff & (c ));
1051 }
1052 } else
1053 return NULL;
1054 }
1055 buffer[i] = 0;
1056 return buffer;
1057 }
1058
stb_to_utf8(char * buffer,const stb__wchar * str,int n)1059 char * stb_to_utf8(char *buffer, const stb__wchar *str, int n)
1060 {
1061 int i=0;
1062 --n;
1063 while (*str) {
1064 if (*str < 0x80) {
1065 if (i+1 > n) return NULL;
1066 buffer[i++] = (char) *str++;
1067 } else if (*str < 0x800) {
1068 if (i+2 > n) return NULL;
1069 buffer[i++] = 0xc0 + (*str >> 6);
1070 buffer[i++] = 0x80 + (*str & 0x3f);
1071 str += 1;
1072 } else if (*str >= 0xd800 && *str < 0xdc00) {
1073 stb_uint32 c;
1074 if (i+4 > n) return NULL;
1075 c = ((str[0] - 0xd800) << 10) + ((str[1]) - 0xdc00) + 0x10000;
1076 buffer[i++] = 0xf0 + (c >> 18);
1077 buffer[i++] = 0x80 + ((c >> 12) & 0x3f);
1078 buffer[i++] = 0x80 + ((c >> 6) & 0x3f);
1079 buffer[i++] = 0x80 + ((c ) & 0x3f);
1080 str += 2;
1081 } else if (*str >= 0xdc00 && *str < 0xe000) {
1082 return NULL;
1083 } else {
1084 if (i+3 > n) return NULL;
1085 buffer[i++] = 0xe0 + (*str >> 12);
1086 buffer[i++] = 0x80 + ((*str >> 6) & 0x3f);
1087 buffer[i++] = 0x80 + ((*str ) & 0x3f);
1088 str += 1;
1089 }
1090 }
1091 buffer[i] = 0;
1092 return buffer;
1093 }
1094
stb__from_utf8(const char * str)1095 stb__wchar *stb__from_utf8(const char *str)
1096 {
1097 static stb__wchar buffer[4096];
1098 return stb_from_utf8(buffer, str, 4096);
1099 }
1100
stb__from_utf8_alt(const char * str)1101 stb__wchar *stb__from_utf8_alt(const char *str)
1102 {
1103 static stb__wchar buffer[4096];
1104 return stb_from_utf8(buffer, str, 4096);
1105 }
1106
stb__to_utf8(const stb__wchar * str)1107 char *stb__to_utf8(const stb__wchar *str)
1108 {
1109 static char buffer[4096];
1110 return stb_to_utf8(buffer, str, 4096);
1111 }
1112
1113 #endif
1114
1115 //////////////////////////////////////////////////////////////////////////////
1116 //
1117 // Miscellany
1118 //
1119
1120 STB_EXTERN void stb_fatal(const char *fmt, ...);
1121 STB_EXTERN void stb_(char *fmt, ...);
1122 STB_EXTERN void stb_append_to_file(char *file, char *fmt, ...);
1123 STB_EXTERN void stb_log(int active);
1124 STB_EXTERN void stb_log_fileline(int active);
1125 STB_EXTERN void stb_log_name(char *filename);
1126
1127 STB_EXTERN void stb_swap(void *p, void *q, size_t sz);
1128 STB_EXTERN void *stb_copy(void *p, size_t sz);
1129 STB_EXTERN void stb_pointer_array_free(void *p, int len);
1130 STB_EXTERN void **stb_array_block_alloc(int count, int blocksize);
1131
1132 #define stb_arrcount(x) (sizeof(x)/sizeof((x)[0]))
1133
1134
1135 STB_EXTERN int stb__record_fileline(const char *f, int n);
1136
1137 #ifdef STB_DEFINE
1138
1139 static char *stb__file;
1140 static int stb__line;
1141
stb__record_fileline(const char * f,int n)1142 int stb__record_fileline(const char *f, int n)
1143 {
1144 stb__file = (char*) f;
1145 stb__line = n;
1146 return 0;
1147 }
1148
stb_fatal(const char * s,...)1149 void stb_fatal(const char *s, ...)
1150 {
1151 va_list a;
1152 if (stb__file)
1153 fprintf(stderr, "[%s:%d] ", stb__file, stb__line);
1154 va_start(a,s);
1155 fputs("Fatal error: ", stderr);
1156 vfprintf(stderr, s, a);
1157 va_end(a);
1158 fputs("\n", stderr);
1159 #ifdef STB_DEBUG
1160 #ifdef _MSC_VER
1161 #ifndef STB_PTR64
1162 __asm int 3; // trap to debugger!
1163 #else
1164 __debugbreak();
1165 #endif
1166 #else
1167 __builtin_trap();
1168 #endif
1169 #endif
1170 exit(1);
1171 }
1172
1173 static int stb__log_active=1, stb__log_fileline=1;
1174
stb_log(int active)1175 void stb_log(int active)
1176 {
1177 stb__log_active = active;
1178 }
1179
stb_log_fileline(int active)1180 void stb_log_fileline(int active)
1181 {
1182 stb__log_fileline = active;
1183 }
1184
1185 #ifdef STB_NO_STB_STRINGS
1186 const char *stb__log_filename = "temp.log";
1187 #else
1188 const char *stb__log_filename = "stb.log";
1189 #endif
1190
stb_log_name(char * s)1191 void stb_log_name(char *s)
1192 {
1193 stb__log_filename = s;
1194 }
1195
stb_(char * s,...)1196 void stb_(char *s, ...)
1197 {
1198 if (stb__log_active) {
1199 FILE *f = stb_p_fopen(stb__log_filename, "a");
1200 if (f) {
1201 va_list a;
1202 if (stb__log_fileline && stb__file)
1203 fprintf(f, "[%s:%4d] ", stb__file, stb__line);
1204 va_start(a,s);
1205 vfprintf(f, s, a);
1206 va_end(a);
1207 fputs("\n", f);
1208 fclose(f);
1209 }
1210 }
1211 }
1212
stb_append_to_file(char * filename,char * s,...)1213 void stb_append_to_file(char *filename, char *s, ...)
1214 {
1215 FILE *f = stb_p_fopen(filename, "a");
1216 if (f) {
1217 va_list a;
1218 va_start(a,s);
1219 vfprintf(f, s, a);
1220 va_end(a);
1221 fputs("\n", f);
1222 fclose(f);
1223 }
1224 }
1225
1226
1227 typedef struct { char d[4]; } stb__4;
1228 typedef struct { char d[8]; } stb__8;
1229
1230 // optimize the small cases, though you shouldn't be calling this for those!
stb_swap(void * p,void * q,size_t sz)1231 void stb_swap(void *p, void *q, size_t sz)
1232 {
1233 char buffer[256];
1234 if (p == q) return;
1235 if (sz == 4) {
1236 stb__4 temp = * ( stb__4 *) p;
1237 * (stb__4 *) p = * ( stb__4 *) q;
1238 * (stb__4 *) q = temp;
1239 return;
1240 } else if (sz == 8) {
1241 stb__8 temp = * ( stb__8 *) p;
1242 * (stb__8 *) p = * ( stb__8 *) q;
1243 * (stb__8 *) q = temp;
1244 return;
1245 }
1246
1247 while (sz > sizeof(buffer)) {
1248 stb_swap(p, q, sizeof(buffer));
1249 p = (char *) p + sizeof(buffer);
1250 q = (char *) q + sizeof(buffer);
1251 sz -= sizeof(buffer);
1252 }
1253
1254 memcpy(buffer, p , sz);
1255 memcpy(p , q , sz);
1256 memcpy(q , buffer, sz);
1257 }
1258
stb_copy(void * p,size_t sz)1259 void *stb_copy(void *p, size_t sz)
1260 {
1261 void *q = malloc(sz);
1262 memcpy(q, p, sz);
1263 return q;
1264 }
1265
stb_pointer_array_free(void * q,int len)1266 void stb_pointer_array_free(void *q, int len)
1267 {
1268 void **p = (void **) q;
1269 int i;
1270 for (i=0; i < len; ++i)
1271 free(p[i]);
1272 }
1273
stb_array_block_alloc(int count,int blocksize)1274 void **stb_array_block_alloc(int count, int blocksize)
1275 {
1276 int i;
1277 char *p = (char *) malloc(sizeof(void *) * count + count * blocksize);
1278 void **q;
1279 if (p == NULL) return NULL;
1280 q = (void **) p;
1281 p += sizeof(void *) * count;
1282 for (i=0; i < count; ++i)
1283 q[i] = p + i * blocksize;
1284 return q;
1285 }
1286 #endif
1287
1288 #ifdef STB_DEBUG
1289 // tricky hack to allow recording FILE,LINE even in varargs functions
1290 #define STB__RECORD_FILE(x) (stb__record_fileline(__FILE__, __LINE__),(x))
1291 #define stb_log STB__RECORD_FILE(stb_log)
1292 #define stb_ STB__RECORD_FILE(stb_)
1293 #ifndef STB_FATAL_CLEAN
1294 #define stb_fatal STB__RECORD_FILE(stb_fatal)
1295 #endif
1296 #define STB__DEBUG(x) x
1297 #else
1298 #define STB__DEBUG(x)
1299 #endif
1300
1301 //////////////////////////////////////////////////////////////////////////////
1302 //
1303 // stb_temp
1304 //
1305
1306 #define stb_temp(block, sz) stb__temp(block, sizeof(block), (sz))
1307
1308 STB_EXTERN void * stb__temp(void *b, int b_sz, int want_sz);
1309 STB_EXTERN void stb_tempfree(void *block, void *ptr);
1310
1311 #ifdef STB_DEFINE
1312
stb__temp(void * b,int b_sz,int want_sz)1313 void * stb__temp(void *b, int b_sz, int want_sz)
1314 {
1315 if (b_sz >= want_sz)
1316 return b;
1317 else
1318 return malloc(want_sz);
1319 }
1320
stb_tempfree(void * b,void * p)1321 void stb_tempfree(void *b, void *p)
1322 {
1323 if (p != b)
1324 free(p);
1325 }
1326 #endif
1327
1328
1329 //////////////////////////////////////////////////////////////////////////////
1330 //
1331 // math/sampling operations
1332 //
1333
1334
1335 #define stb_lerp(t,a,b) ( (a) + (t) * (float) ((b)-(a)) )
1336 #define stb_unlerp(t,a,b) ( ((t) - (a)) / (float) ((b) - (a)) )
1337
1338 #define stb_clamp(x,xmin,xmax) ((x) < (xmin) ? (xmin) : (x) > (xmax) ? (xmax) : (x))
1339
1340 STB_EXTERN void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize);
1341 STB_EXTERN int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis);
1342 STB_EXTERN void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt);
1343
1344 STB_EXTERN int stb_float_eq(float x, float y, float delta, int max_ulps);
1345 STB_EXTERN int stb_is_prime(unsigned int m);
1346 STB_EXTERN unsigned int stb_power_of_two_nearest_prime(int n);
1347
1348 STB_EXTERN float stb_smoothstep(float t);
1349 STB_EXTERN float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3);
1350
1351 STB_EXTERN double stb_linear_remap(double x, double a, double b,
1352 double c, double d);
1353
1354 #ifdef STB_DEFINE
stb_smoothstep(float t)1355 float stb_smoothstep(float t)
1356 {
1357 return (3 - 2*t)*(t*t);
1358 }
1359
stb_cubic_bezier_1d(float t,float p0,float p1,float p2,float p3)1360 float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3)
1361 {
1362 float it = 1-t;
1363 return it*it*it*p0 + 3*it*it*t*p1 + 3*it*t*t*p2 + t*t*t*p3;
1364 }
1365
stb_newell_normal(float * normal,int num_vert,float ** vert,int normalize)1366 void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize)
1367 {
1368 int i,j;
1369 float p;
1370 normal[0] = normal[1] = normal[2] = 0;
1371 for (i=num_vert-1,j=0; j < num_vert; i=j++) {
1372 float *u = vert[i];
1373 float *v = vert[j];
1374 normal[0] += (u[1] - v[1]) * (u[2] + v[2]);
1375 normal[1] += (u[2] - v[2]) * (u[0] + v[0]);
1376 normal[2] += (u[0] - v[0]) * (u[1] + v[1]);
1377 }
1378 if (normalize) {
1379 p = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
1380 p = (float) (1.0 / sqrt(p));
1381 normal[0] *= p;
1382 normal[1] *= p;
1383 normal[2] *= p;
1384 }
1385 }
1386
stb_box_face_vertex_axis_side(int face_number,int vertex_number,int axis)1387 int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis)
1388 {
1389 static int box_vertices[6][4][3] =
1390 {
1391 { { 1,1,1 }, { 1,0,1 }, { 1,0,0 }, { 1,1,0 } },
1392 { { 0,0,0 }, { 0,0,1 }, { 0,1,1 }, { 0,1,0 } },
1393 { { 0,0,0 }, { 0,1,0 }, { 1,1,0 }, { 1,0,0 } },
1394 { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 } },
1395 { { 1,1,1 }, { 0,1,1 }, { 0,0,1 }, { 1,0,1 } },
1396 { { 1,1,1 }, { 1,1,0 }, { 0,1,0 }, { 0,1,1 } },
1397 };
1398 assert(face_number >= 0 && face_number < 6);
1399 assert(vertex_number >= 0 && vertex_number < 4);
1400 assert(axis >= 0 && axis < 3);
1401 return box_vertices[face_number][vertex_number][axis];
1402 }
1403
stb_linear_controller(float * curpos,float target_pos,float acc,float deacc,float dt)1404 void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt)
1405 {
1406 float sign = 1, p, cp = *curpos;
1407 if (cp == target_pos) return;
1408 if (target_pos < cp) {
1409 target_pos = -target_pos;
1410 cp = -cp;
1411 sign = -1;
1412 }
1413 // first decelerate
1414 if (cp < 0) {
1415 p = cp + deacc * dt;
1416 if (p > 0) {
1417 p = 0;
1418 dt = dt - cp / deacc;
1419 if (dt < 0) dt = 0;
1420 } else {
1421 dt = 0;
1422 }
1423 cp = p;
1424 }
1425 // now accelerate
1426 p = cp + acc*dt;
1427 if (p > target_pos) p = target_pos;
1428 *curpos = p * sign;
1429 // @TODO: testing
1430 }
1431
stb_quadratic_controller(float target_pos,float curpos,float maxvel,float maxacc,float dt,float * curvel)1432 float stb_quadratic_controller(float target_pos, float curpos, float maxvel, float maxacc, float dt, float *curvel)
1433 {
1434 return 0; // @TODO
1435 }
1436
stb_float_eq(float x,float y,float delta,int max_ulps)1437 int stb_float_eq(float x, float y, float delta, int max_ulps)
1438 {
1439 if (fabs(x-y) <= delta) return 1;
1440 if (abs(*(int *)&x - *(int *)&y) <= max_ulps) return 1;
1441 return 0;
1442 }
1443
stb_is_prime(unsigned int m)1444 int stb_is_prime(unsigned int m)
1445 {
1446 unsigned int i,j;
1447 if (m < 2) return 0;
1448 if (m == 2) return 1;
1449 if (!(m & 1)) return 0;
1450 if (m % 3 == 0) return (m == 3);
1451 for (i=5; (j=i*i), j <= m && j > i; i += 6) {
1452 if (m % i == 0) return 0;
1453 if (m % (i+2) == 0) return 0;
1454 }
1455 return 1;
1456 }
1457
stb_power_of_two_nearest_prime(int n)1458 unsigned int stb_power_of_two_nearest_prime(int n)
1459 {
1460 static signed char tab[32] = { 0,0,0,0,1,0,-1,0,1,-1,-1,3,-1,0,-1,2,1,
1461 0,2,0,-1,-4,-1,5,-1,18,-2,15,2,-1,2,0 };
1462 if (!tab[0]) {
1463 int i;
1464 for (i=0; i < 32; ++i)
1465 tab[i] = (1 << i) + 2*tab[i] - 1;
1466 tab[1] = 2;
1467 tab[0] = 1;
1468 }
1469 if (n >= 32) return 0xfffffffb;
1470 return tab[n];
1471 }
1472
stb_linear_remap(double x,double x_min,double x_max,double out_min,double out_max)1473 double stb_linear_remap(double x, double x_min, double x_max,
1474 double out_min, double out_max)
1475 {
1476 return stb_lerp(stb_unlerp(x,x_min,x_max),out_min,out_max);
1477 }
1478 #endif
1479
1480 // create a macro so it's faster, but you can get at the function pointer
1481 #define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d)
1482
1483
1484 //////////////////////////////////////////////////////////////////////////////
1485 //
1486 // bit operations
1487 //
1488
1489 #define stb_big32(c) (((c)[0]<<24) + (c)[1]*65536 + (c)[2]*256 + (c)[3])
1490 #define stb_little32(c) (((c)[3]<<24) + (c)[2]*65536 + (c)[1]*256 + (c)[0])
1491 #define stb_big16(c) ((c)[0]*256 + (c)[1])
1492 #define stb_little16(c) ((c)[1]*256 + (c)[0])
1493
1494 STB_EXTERN int stb_bitcount(unsigned int a);
1495 STB_EXTERN unsigned int stb_bitreverse8(unsigned char n);
1496 STB_EXTERN unsigned int stb_bitreverse(unsigned int n);
1497
1498 STB_EXTERN int stb_is_pow2(size_t);
1499 STB_EXTERN int stb_log2_ceil(size_t);
1500 STB_EXTERN int stb_log2_floor(size_t);
1501
1502 STB_EXTERN int stb_lowbit8(unsigned int n);
1503 STB_EXTERN int stb_highbit8(unsigned int n);
1504
1505 #ifdef STB_DEFINE
stb_bitcount(unsigned int a)1506 int stb_bitcount(unsigned int a)
1507 {
1508 a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
1509 a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
1510 a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
1511 a = (a + (a >> 8)); // max 16 per 8 bits
1512 a = (a + (a >> 16)); // max 32 per 8 bits
1513 return a & 0xff;
1514 }
1515
stb_bitreverse8(unsigned char n)1516 unsigned int stb_bitreverse8(unsigned char n)
1517 {
1518 n = ((n & 0xAA) >> 1) + ((n & 0x55) << 1);
1519 n = ((n & 0xCC) >> 2) + ((n & 0x33) << 2);
1520 return (unsigned char) ((n >> 4) + (n << 4));
1521 }
1522
stb_bitreverse(unsigned int n)1523 unsigned int stb_bitreverse(unsigned int n)
1524 {
1525 n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
1526 n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
1527 n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
1528 n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
1529 return (n >> 16) | (n << 16);
1530 }
1531
stb_is_pow2(size_t n)1532 int stb_is_pow2(size_t n)
1533 {
1534 return (n & (n-1)) == 0;
1535 }
1536
1537 // tricky use of 4-bit table to identify 5 bit positions (note the '-1')
1538 // 3-bit table would require another tree level; 5-bit table wouldn't save one
1539 #if defined(_WIN32) && !defined(__MINGW32__)
1540 #pragma warning(push)
1541 #pragma warning(disable: 4035) // disable warning about no return value
stb_log2_floor(size_t n)1542 int stb_log2_floor(size_t n)
1543 {
1544 #if _MSC_VER > 1700
1545 unsigned long i;
1546 #ifdef STB_PTR64
1547 _BitScanReverse64(&i, n);
1548 #else
1549 _BitScanReverse(&i, n);
1550 #endif
1551 return i != 0 ? i : -1;
1552 #else
1553 __asm {
1554 bsr eax,n
1555 jnz done
1556 mov eax,-1
1557 }
1558 done:;
1559 #endif
1560 }
1561 #pragma warning(pop)
1562 #else
stb_log2_floor(size_t n)1563 int stb_log2_floor(size_t n)
1564 {
1565 static signed char log2_4[16] = { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3 };
1566
1567 #ifdef STB_PTR64
1568 if (n >= ((size_t) 1u << 32))
1569 return stb_log2_floor(n >> 32);
1570 #endif
1571
1572 // 2 compares if n < 16, 3 compares otherwise
1573 if (n < (1U << 14))
1574 if (n < (1U << 4)) return 0 + log2_4[n ];
1575 else if (n < (1U << 9)) return 5 + log2_4[n >> 5];
1576 else return 10 + log2_4[n >> 10];
1577 else if (n < (1U << 24))
1578 if (n < (1U << 19)) return 15 + log2_4[n >> 15];
1579 else return 20 + log2_4[n >> 20];
1580 else if (n < (1U << 29)) return 25 + log2_4[n >> 25];
1581 else return 30 + log2_4[n >> 30];
1582 }
1583 #endif
1584
1585 // define ceil from floor
stb_log2_ceil(size_t n)1586 int stb_log2_ceil(size_t n)
1587 {
1588 if (stb_is_pow2(n)) return stb_log2_floor(n);
1589 else return 1 + stb_log2_floor(n);
1590 }
1591
stb_highbit8(unsigned int n)1592 int stb_highbit8(unsigned int n)
1593 {
1594 return stb_log2_ceil(n&255);
1595 }
1596
stb_lowbit8(unsigned int n)1597 int stb_lowbit8(unsigned int n)
1598 {
1599 static signed char lowbit4[16] = { -1,0,1,0, 2,0,1,0, 3,0,1,0, 2,0,1,0 };
1600 int k = lowbit4[n & 15];
1601 if (k >= 0) return k;
1602 k = lowbit4[(n >> 4) & 15];
1603 if (k >= 0) return k+4;
1604 return k;
1605 }
1606 #endif
1607
1608
1609
1610 //////////////////////////////////////////////////////////////////////////////
1611 //
1612 // qsort Compare Routines
1613 //
1614
1615 #ifdef _WIN32
1616 #define stb_stricmp(a,b) stb_p_stricmp(a,b)
1617 #define stb_strnicmp(a,b,n) stb_p_strnicmp(a,b,n)
1618 #else
1619 #define stb_stricmp(a,b) strcasecmp(a,b)
1620 #define stb_strnicmp(a,b,n) strncasecmp(a,b,n)
1621 #endif
1622
1623
1624 STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b);
1625 STB_EXTERN int (*stb_intcmprev(int offset))(const void *a, const void *b);
1626 STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b);
1627 STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b);
1628 STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b);
1629 STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b);
1630 STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b);
1631
1632 #ifdef STB_DEFINE
1633 static int stb__intcmpoffset, stb__ucharcmpoffset, stb__strcmpoffset;
1634 static int stb__floatcmpoffset, stb__doublecmpoffset;
1635 static int stb__memcmpoffset, stb__memcmpsize;
1636
stb__intcmp(const void * a,const void * b)1637 int stb__intcmp(const void *a, const void *b)
1638 {
1639 const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
1640 const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
1641 return p < q ? -1 : p > q;
1642 }
1643
stb__intcmprev(const void * a,const void * b)1644 int stb__intcmprev(const void *a, const void *b)
1645 {
1646 const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
1647 const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
1648 return q < p ? -1 : q > p;
1649 }
1650
stb__ucharcmp(const void * a,const void * b)1651 int stb__ucharcmp(const void *a, const void *b)
1652 {
1653 const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset);
1654 const int q = *(const unsigned char *) ((const char *) b + stb__ucharcmpoffset);
1655 return p < q ? -1 : p > q;
1656 }
1657
stb__floatcmp(const void * a,const void * b)1658 int stb__floatcmp(const void *a, const void *b)
1659 {
1660 const float p = *(const float *) ((const char *) a + stb__floatcmpoffset);
1661 const float q = *(const float *) ((const char *) b + stb__floatcmpoffset);
1662 return p < q ? -1 : p > q;
1663 }
1664
stb__doublecmp(const void * a,const void * b)1665 int stb__doublecmp(const void *a, const void *b)
1666 {
1667 const double p = *(const double *) ((const char *) a + stb__doublecmpoffset);
1668 const double q = *(const double *) ((const char *) b + stb__doublecmpoffset);
1669 return p < q ? -1 : p > q;
1670 }
1671
stb__qsort_strcmp(const void * a,const void * b)1672 int stb__qsort_strcmp(const void *a, const void *b)
1673 {
1674 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1675 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1676 return strcmp(p,q);
1677 }
1678
stb__qsort_stricmp(const void * a,const void * b)1679 int stb__qsort_stricmp(const void *a, const void *b)
1680 {
1681 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1682 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1683 return stb_stricmp(p,q);
1684 }
1685
stb__memcmp(const void * a,const void * b)1686 int stb__memcmp(const void *a, const void *b)
1687 {
1688 return memcmp((char *) a + stb__memcmpoffset, (char *) b + stb__memcmpoffset, stb__memcmpsize);
1689 }
1690
stb_intcmp(int offset)1691 int (*stb_intcmp(int offset))(const void *, const void *)
1692 {
1693 stb__intcmpoffset = offset;
1694 return &stb__intcmp;
1695 }
1696
stb_intcmprev(int offset)1697 int (*stb_intcmprev(int offset))(const void *, const void *)
1698 {
1699 stb__intcmpoffset = offset;
1700 return &stb__intcmprev;
1701 }
1702
stb_ucharcmp(int offset)1703 int (*stb_ucharcmp(int offset))(const void *, const void *)
1704 {
1705 stb__ucharcmpoffset = offset;
1706 return &stb__ucharcmp;
1707 }
1708
stb_qsort_strcmp(int offset)1709 int (*stb_qsort_strcmp(int offset))(const void *, const void *)
1710 {
1711 stb__strcmpoffset = offset;
1712 return &stb__qsort_strcmp;
1713 }
1714
stb_qsort_stricmp(int offset)1715 int (*stb_qsort_stricmp(int offset))(const void *, const void *)
1716 {
1717 stb__strcmpoffset = offset;
1718 return &stb__qsort_stricmp;
1719 }
1720
stb_floatcmp(int offset)1721 int (*stb_floatcmp(int offset))(const void *, const void *)
1722 {
1723 stb__floatcmpoffset = offset;
1724 return &stb__floatcmp;
1725 }
1726
stb_doublecmp(int offset)1727 int (*stb_doublecmp(int offset))(const void *, const void *)
1728 {
1729 stb__doublecmpoffset = offset;
1730 return &stb__doublecmp;
1731 }
1732
stb_memcmp(int offset,int size)1733 int (*stb_memcmp(int offset, int size))(const void *, const void *)
1734 {
1735 stb__memcmpoffset = offset;
1736 stb__memcmpsize = size;
1737 return &stb__memcmp;
1738 }
1739 #endif
1740
1741 //////////////////////////////////////////////////////////////////////////////
1742 //
1743 // Binary Search Toolkit
1744 //
1745
1746 typedef struct
1747 {
1748 int minval, maxval, guess;
1749 int mode, step;
1750 } stb_search;
1751
1752 STB_EXTERN int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest);
1753 STB_EXTERN int stb_search_open(stb_search *s, int minv, int find_smallest);
1754 STB_EXTERN int stb_probe(stb_search *s, int compare, int *result); // return 0 when done
1755
1756 #ifdef STB_DEFINE
1757 enum
1758 {
1759 STB_probe_binary_smallest,
1760 STB_probe_binary_largest,
1761 STB_probe_open_smallest,
1762 STB_probe_open_largest,
1763 };
1764
stb_probe_guess(stb_search * s,int * result)1765 static int stb_probe_guess(stb_search *s, int *result)
1766 {
1767 switch(s->mode) {
1768 case STB_probe_binary_largest:
1769 if (s->minval == s->maxval) {
1770 *result = s->minval;
1771 return 0;
1772 }
1773 assert(s->minval < s->maxval);
1774 // if a < b, then a < p <= b
1775 s->guess = s->minval + (((unsigned) s->maxval - s->minval + 1) >> 1);
1776 break;
1777
1778 case STB_probe_binary_smallest:
1779 if (s->minval == s->maxval) {
1780 *result = s->minval;
1781 return 0;
1782 }
1783 assert(s->minval < s->maxval);
1784 // if a < b, then a <= p < b
1785 s->guess = s->minval + (((unsigned) s->maxval - s->minval) >> 1);
1786 break;
1787 case STB_probe_open_smallest:
1788 case STB_probe_open_largest:
1789 s->guess = s->maxval; // guess the current maxval
1790 break;
1791 }
1792 *result = s->guess;
1793 return 1;
1794 }
1795
stb_probe(stb_search * s,int compare,int * result)1796 int stb_probe(stb_search *s, int compare, int *result)
1797 {
1798 switch(s->mode) {
1799 case STB_probe_open_smallest:
1800 case STB_probe_open_largest: {
1801 if (compare <= 0) {
1802 // then it lies within minval & maxval
1803 if (s->mode == STB_probe_open_smallest)
1804 s->mode = STB_probe_binary_smallest;
1805 else
1806 s->mode = STB_probe_binary_largest;
1807 } else {
1808 // otherwise, we need to probe larger
1809 s->minval = s->maxval + 1;
1810 s->maxval = s->minval + s->step;
1811 s->step += s->step;
1812 }
1813 break;
1814 }
1815 case STB_probe_binary_smallest: {
1816 // if compare < 0, then s->minval <= a < p
1817 // if compare = 0, then s->minval <= a <= p
1818 // if compare > 0, then p < a <= s->maxval
1819 if (compare <= 0)
1820 s->maxval = s->guess;
1821 else
1822 s->minval = s->guess+1;
1823 break;
1824 }
1825 case STB_probe_binary_largest: {
1826 // if compare < 0, then s->minval <= a < p
1827 // if compare = 0, then p <= a <= s->maxval
1828 // if compare > 0, then p < a <= s->maxval
1829 if (compare < 0)
1830 s->maxval = s->guess-1;
1831 else
1832 s->minval = s->guess;
1833 break;
1834 }
1835 }
1836 return stb_probe_guess(s, result);
1837 }
1838
stb_search_binary(stb_search * s,int minv,int maxv,int find_smallest)1839 int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest)
1840 {
1841 int r;
1842 if (maxv < minv) return minv-1;
1843 s->minval = minv;
1844 s->maxval = maxv;
1845 s->mode = find_smallest ? STB_probe_binary_smallest : STB_probe_binary_largest;
1846 stb_probe_guess(s, &r);
1847 return r;
1848 }
1849
stb_search_open(stb_search * s,int minv,int find_smallest)1850 int stb_search_open(stb_search *s, int minv, int find_smallest)
1851 {
1852 int r;
1853 s->step = 4;
1854 s->minval = minv;
1855 s->maxval = minv+s->step;
1856 s->mode = find_smallest ? STB_probe_open_smallest : STB_probe_open_largest;
1857 stb_probe_guess(s, &r);
1858 return r;
1859 }
1860 #endif
1861
1862 //////////////////////////////////////////////////////////////////////////////
1863 //
1864 // String Processing
1865 //
1866
1867 #define stb_prefixi(s,t) (0==stb_strnicmp((s),(t),strlen(t)))
1868
1869 enum stb_splitpath_flag
1870 {
1871 STB_PATH = 1,
1872 STB_FILE = 2,
1873 STB_EXT = 4,
1874 STB_PATH_FILE = STB_PATH + STB_FILE,
1875 STB_FILE_EXT = STB_FILE + STB_EXT,
1876 STB_EXT_NO_PERIOD = 8,
1877 };
1878
1879 STB_EXTERN char * stb_skipwhite(char *s);
1880 STB_EXTERN char * stb_trimwhite(char *s);
1881 STB_EXTERN char * stb_skipnewline(char *s);
1882 STB_EXTERN char * stb_strncpy(char *s, char *t, int n);
1883 STB_EXTERN char * stb_substr(char *t, int n);
1884 STB_EXTERN char * stb_duplower(char *s);
1885 STB_EXTERN void stb_tolower (char *s);
1886 STB_EXTERN char * stb_strchr2 (char *s, char p1, char p2);
1887 STB_EXTERN char * stb_strrchr2(char *s, char p1, char p2);
1888 STB_EXTERN char * stb_strtok(char *output, char *src, char *delimit);
1889 STB_EXTERN char * stb_strtok_keep(char *output, char *src, char *delimit);
1890 STB_EXTERN char * stb_strtok_invert(char *output, char *src, char *allowed);
1891 STB_EXTERN char * stb_dupreplace(char *s, char *find, char *replace);
1892 STB_EXTERN void stb_replaceinplace(char *s, char *find, char *replace);
1893 STB_EXTERN char * stb_splitpath(char *output, char *src, int flag);
1894 STB_EXTERN char * stb_splitpathdup(char *src, int flag);
1895 STB_EXTERN char * stb_replacedir(char *output, char *src, char *dir);
1896 STB_EXTERN char * stb_replaceext(char *output, char *src, char *ext);
1897 STB_EXTERN void stb_fixpath(char *path);
1898 STB_EXTERN char * stb_shorten_path_readable(char *path, int max_len);
1899 STB_EXTERN int stb_suffix (char *s, char *t);
1900 STB_EXTERN int stb_suffixi(char *s, char *t);
1901 STB_EXTERN int stb_prefix (char *s, char *t);
1902 STB_EXTERN char * stb_strichr(char *s, char t);
1903 STB_EXTERN char * stb_stristr(char *s, char *t);
1904 STB_EXTERN int stb_prefix_count(char *s, char *t);
1905 STB_EXTERN const char * stb_plural(int n); // "s" or ""
1906 STB_EXTERN size_t stb_strscpy(char *d, const char *s, size_t n);
1907
1908 STB_EXTERN char **stb_tokens(char *src, char *delimit, int *count);
1909 STB_EXTERN char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1910 STB_EXTERN char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1911 STB_EXTERN char **stb_tokens_allowempty(char *src, char *delimit, int *count);
1912 STB_EXTERN char **stb_tokens_stripwhite(char *src, char *delimit, int *count);
1913 STB_EXTERN char **stb_tokens_withdelim(char *src, char *delimit, int *count);
1914 STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count);
1915 // with 'quoted', allow delimiters to appear inside quotation marks, and don't
1916 // strip whitespace inside them (and we delete the quotation marks unless they
1917 // appear back to back, in which case they're considered escaped)
1918
1919 #ifdef STB_DEFINE
1920
stb_strscpy(char * d,const char * s,size_t n)1921 size_t stb_strscpy(char *d, const char *s, size_t n)
1922 {
1923 size_t len = strlen(s);
1924 if (len >= n) {
1925 if (n) d[0] = 0;
1926 return 0;
1927 }
1928 stb_p_strcpy_s(d,n+1,s);
1929 return len + 1;
1930 }
1931
stb_plural(int n)1932 const char *stb_plural(int n)
1933 {
1934 return n == 1 ? "" : "s";
1935 }
1936
stb_prefix(char * s,char * t)1937 int stb_prefix(char *s, char *t)
1938 {
1939 while (*t)
1940 if (*s++ != *t++)
1941 return STB_FALSE;
1942 return STB_TRUE;
1943 }
1944
stb_prefix_count(char * s,char * t)1945 int stb_prefix_count(char *s, char *t)
1946 {
1947 int c=0;
1948 while (*t) {
1949 if (*s++ != *t++)
1950 break;
1951 ++c;
1952 }
1953 return c;
1954 }
1955
stb_suffix(char * s,char * t)1956 int stb_suffix(char *s, char *t)
1957 {
1958 size_t n = strlen(s);
1959 size_t m = strlen(t);
1960 if (m <= n)
1961 return 0 == strcmp(s+n-m, t);
1962 else
1963 return 0;
1964 }
1965
stb_suffixi(char * s,char * t)1966 int stb_suffixi(char *s, char *t)
1967 {
1968 size_t n = strlen(s);
1969 size_t m = strlen(t);
1970 if (m <= n)
1971 return 0 == stb_stricmp(s+n-m, t);
1972 else
1973 return 0;
1974 }
1975
1976 // originally I was using this table so that I could create known sentinel
1977 // values--e.g. change whitetable[0] to be true if I was scanning for whitespace,
1978 // and false if I was scanning for nonwhite. I don't appear to be using that
1979 // functionality anymore (I do for tokentable, though), so just replace it
1980 // with isspace()
stb_skipwhite(char * s)1981 char *stb_skipwhite(char *s)
1982 {
1983 while (isspace((unsigned char) *s)) ++s;
1984 return s;
1985 }
1986
stb_skipnewline(char * s)1987 char *stb_skipnewline(char *s)
1988 {
1989 if (s[0] == '\r' || s[0] == '\n') {
1990 if (s[0]+s[1] == '\r' + '\n') ++s;
1991 ++s;
1992 }
1993 return s;
1994 }
1995
stb_trimwhite(char * s)1996 char *stb_trimwhite(char *s)
1997 {
1998 int i,n;
1999 s = stb_skipwhite(s);
2000 n = (int) strlen(s);
2001 for (i=n-1; i >= 0; --i)
2002 if (!isspace(s[i]))
2003 break;
2004 s[i+1] = 0;
2005 return s;
2006 }
2007
stb_strncpy(char * s,char * t,int n)2008 char *stb_strncpy(char *s, char *t, int n)
2009 {
2010 stb_p_strncpy_s(s,n+1,t,n);
2011 s[n] = 0;
2012 return s;
2013 }
2014
stb_substr(char * t,int n)2015 char *stb_substr(char *t, int n)
2016 {
2017 char *a;
2018 int z = (int) strlen(t);
2019 if (z < n) n = z;
2020 a = (char *) malloc(n+1);
2021 stb_p_strncpy_s(a,n+1,t,n);
2022 a[n] = 0;
2023 return a;
2024 }
2025
stb_duplower(char * s)2026 char *stb_duplower(char *s)
2027 {
2028 char *p = stb_p_strdup(s), *q = p;
2029 while (*q) {
2030 *q = tolower(*q);
2031 ++q;
2032 }
2033 return p;
2034 }
2035
stb_tolower(char * s)2036 void stb_tolower(char *s)
2037 {
2038 while (*s) {
2039 *s = tolower(*s);
2040 ++s;
2041 }
2042 }
2043
stb_strchr2(char * s,char x,char y)2044 char *stb_strchr2(char *s, char x, char y)
2045 {
2046 for(; *s; ++s)
2047 if (*s == x || *s == y)
2048 return s;
2049 return NULL;
2050 }
2051
stb_strrchr2(char * s,char x,char y)2052 char *stb_strrchr2(char *s, char x, char y)
2053 {
2054 char *r = NULL;
2055 for(; *s; ++s)
2056 if (*s == x || *s == y)
2057 r = s;
2058 return r;
2059 }
2060
stb_strichr(char * s,char t)2061 char *stb_strichr(char *s, char t)
2062 {
2063 if (tolower(t) == toupper(t))
2064 return strchr(s,t);
2065 return stb_strchr2(s, (char) tolower(t), (char) toupper(t));
2066 }
2067
stb_stristr(char * s,char * t)2068 char *stb_stristr(char *s, char *t)
2069 {
2070 size_t n = strlen(t);
2071 char *z;
2072 if (n==0) return s;
2073 while ((z = stb_strichr(s, *t)) != NULL) {
2074 if (0==stb_strnicmp(z, t, n))
2075 return z;
2076 s = z+1;
2077 }
2078 return NULL;
2079 }
2080
stb_strtok_raw(char * output,char * src,char * delimit,int keep,int invert)2081 static char *stb_strtok_raw(char *output, char *src, char *delimit, int keep, int invert)
2082 {
2083 if (invert) {
2084 while (*src && strchr(delimit, *src) != NULL) {
2085 *output++ = *src++;
2086 }
2087 } else {
2088 while (*src && strchr(delimit, *src) == NULL) {
2089 *output++ = *src++;
2090 }
2091 }
2092 *output = 0;
2093 if (keep)
2094 return src;
2095 else
2096 return *src ? src+1 : src;
2097 }
2098
stb_strtok(char * output,char * src,char * delimit)2099 char *stb_strtok(char *output, char *src, char *delimit)
2100 {
2101 return stb_strtok_raw(output, src, delimit, 0, 0);
2102 }
2103
stb_strtok_keep(char * output,char * src,char * delimit)2104 char *stb_strtok_keep(char *output, char *src, char *delimit)
2105 {
2106 return stb_strtok_raw(output, src, delimit, 1, 0);
2107 }
2108
stb_strtok_invert(char * output,char * src,char * delimit)2109 char *stb_strtok_invert(char *output, char *src, char *delimit)
2110 {
2111 return stb_strtok_raw(output, src, delimit, 1,1);
2112 }
2113
stb_tokens_raw(char * src_,char * delimit,int * count,int stripwhite,int allow_empty,char * start,char * end)2114 static char **stb_tokens_raw(char *src_, char *delimit, int *count,
2115 int stripwhite, int allow_empty, char *start, char *end)
2116 {
2117 int nested = 0;
2118 unsigned char *src = (unsigned char *) src_;
2119 static char stb_tokentable[256]; // rely on static initializion to 0
2120 static char stable[256],etable[256];
2121 char *out;
2122 char **result;
2123 int num=0;
2124 unsigned char *s;
2125
2126 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 1;
2127 if (start) {
2128 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2129 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2130 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2131 }
2132 stable[0] = 1;
2133
2134 // two passes through: the first time, counting how many
2135 s = (unsigned char *) src;
2136 while (*s) {
2137 // state: just found delimiter
2138 // skip further delimiters
2139 if (!allow_empty) {
2140 stb_tokentable[0] = 0;
2141 while (stb_tokentable[*s])
2142 ++s;
2143 if (!*s) break;
2144 }
2145 ++num;
2146 // skip further non-delimiters
2147 stb_tokentable[0] = 1;
2148 if (stripwhite == 2) { // quoted strings
2149 while (!stb_tokentable[*s]) {
2150 if (*s != '"')
2151 ++s;
2152 else {
2153 ++s;
2154 if (*s == '"')
2155 ++s; // "" -> ", not start a string
2156 else {
2157 // begin a string
2158 while (*s) {
2159 if (s[0] == '"') {
2160 if (s[1] == '"') s += 2; // "" -> "
2161 else { ++s; break; } // terminating "
2162 } else
2163 ++s;
2164 }
2165 }
2166 }
2167 }
2168 } else
2169 while (nested || !stb_tokentable[*s]) {
2170 if (stable[*s]) {
2171 if (!*s) break;
2172 if (end ? etable[*s] : nested)
2173 --nested;
2174 else
2175 ++nested;
2176 }
2177 ++s;
2178 }
2179 if (allow_empty) {
2180 if (*s) ++s;
2181 }
2182 }
2183 // now num has the actual count... malloc our output structure
2184 // need space for all the strings: strings won't be any longer than
2185 // original input, since for every '\0' there's at least one delimiter
2186 result = (char **) malloc(sizeof(*result) * (num+1) + (s-src+1));
2187 if (result == NULL) return result;
2188 out = (char *) (result + (num+1));
2189 // second pass: copy out the data
2190 s = (unsigned char *) src;
2191 num = 0;
2192 nested = 0;
2193 while (*s) {
2194 char *last_nonwhite;
2195 // state: just found delimiter
2196 // skip further delimiters
2197 if (!allow_empty) {
2198 stb_tokentable[0] = 0;
2199 if (stripwhite)
2200 while (stb_tokentable[*s] || isspace(*s))
2201 ++s;
2202 else
2203 while (stb_tokentable[*s])
2204 ++s;
2205 } else if (stripwhite) {
2206 while (isspace(*s)) ++s;
2207 }
2208 if (!*s) break;
2209 // we're past any leading delimiters and whitespace
2210 result[num] = out;
2211 ++num;
2212 // copy non-delimiters
2213 stb_tokentable[0] = 1;
2214 last_nonwhite = out-1;
2215 if (stripwhite == 2) {
2216 while (!stb_tokentable[*s]) {
2217 if (*s != '"') {
2218 if (!isspace(*s)) last_nonwhite = out;
2219 *out++ = *s++;
2220 } else {
2221 ++s;
2222 if (*s == '"') {
2223 if (!isspace(*s)) last_nonwhite = out;
2224 *out++ = *s++; // "" -> ", not start string
2225 } else {
2226 // begin a quoted string
2227 while (*s) {
2228 if (s[0] == '"') {
2229 if (s[1] == '"') { *out++ = *s; s += 2; }
2230 else { ++s; break; } // terminating "
2231 } else
2232 *out++ = *s++;
2233 }
2234 last_nonwhite = out-1; // all in quotes counts as non-white
2235 }
2236 }
2237 }
2238 } else {
2239 while (nested || !stb_tokentable[*s]) {
2240 if (!isspace(*s)) last_nonwhite = out;
2241 if (stable[*s]) {
2242 if (!*s) break;
2243 if (end ? etable[*s] : nested)
2244 --nested;
2245 else
2246 ++nested;
2247 }
2248 *out++ = *s++;
2249 }
2250 }
2251
2252 if (stripwhite) // rewind to last non-whitespace char
2253 out = last_nonwhite+1;
2254 *out++ = '\0';
2255
2256 if (*s) ++s; // skip delimiter
2257 }
2258 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 0;
2259 if (start) {
2260 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2261 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2262 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2263 }
2264 if (count != NULL) *count = num;
2265 result[num] = 0;
2266 return result;
2267 }
2268
stb_tokens(char * src,char * delimit,int * count)2269 char **stb_tokens(char *src, char *delimit, int *count)
2270 {
2271 return stb_tokens_raw(src,delimit,count,0,0,0,0);
2272 }
2273
stb_tokens_nested(char * src,char * delimit,int * count,char * nest_in,char * nest_out)2274 char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2275 {
2276 return stb_tokens_raw(src,delimit,count,0,0,nest_in,nest_out);
2277 }
2278
stb_tokens_nested_empty(char * src,char * delimit,int * count,char * nest_in,char * nest_out)2279 char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2280 {
2281 return stb_tokens_raw(src,delimit,count,0,1,nest_in,nest_out);
2282 }
2283
stb_tokens_allowempty(char * src,char * delimit,int * count)2284 char **stb_tokens_allowempty(char *src, char *delimit, int *count)
2285 {
2286 return stb_tokens_raw(src,delimit,count,0,1,0,0);
2287 }
2288
stb_tokens_stripwhite(char * src,char * delimit,int * count)2289 char **stb_tokens_stripwhite(char *src, char *delimit, int *count)
2290 {
2291 return stb_tokens_raw(src,delimit,count,1,1,0,0);
2292 }
2293
stb_tokens_quoted(char * src,char * delimit,int * count)2294 char **stb_tokens_quoted(char *src, char *delimit, int *count)
2295 {
2296 return stb_tokens_raw(src,delimit,count,2,1,0,0);
2297 }
2298
stb_dupreplace(char * src,char * find,char * replace)2299 char *stb_dupreplace(char *src, char *find, char *replace)
2300 {
2301 size_t len_find = strlen(find);
2302 size_t len_replace = strlen(replace);
2303 int count = 0;
2304
2305 char *s,*p,*q;
2306
2307 s = strstr(src, find);
2308 if (s == NULL) return stb_p_strdup(src);
2309 do {
2310 ++count;
2311 s = strstr(s + len_find, find);
2312 } while (s != NULL);
2313
2314 p = (char *) malloc(strlen(src) + count * (len_replace - len_find) + 1);
2315 if (p == NULL) return p;
2316 q = p;
2317 s = src;
2318 for (;;) {
2319 char *t = strstr(s, find);
2320 if (t == NULL) {
2321 stb_p_strcpy_s(q,strlen(src)+count*(len_replace-len_find)+1,s);
2322 assert(strlen(p) == strlen(src) + count*(len_replace-len_find));
2323 return p;
2324 }
2325 memcpy(q, s, t-s);
2326 q += t-s;
2327 memcpy(q, replace, len_replace);
2328 q += len_replace;
2329 s = t + len_find;
2330 }
2331 }
2332
stb_replaceinplace(char * src,char * find,char * replace)2333 void stb_replaceinplace(char *src, char *find, char *replace)
2334 {
2335 size_t len_find = strlen(find);
2336 size_t len_replace = strlen(replace);
2337 int delta;
2338
2339 char *s,*p,*q;
2340
2341 delta = (int) (len_replace - len_find);
2342 assert(delta <= 0);
2343 if (delta > 0) return;
2344
2345 p = strstr(src, find);
2346 if (p == NULL) return;
2347
2348 s = q = p;
2349 while (*s) {
2350 memcpy(q, replace, len_replace);
2351 p += len_find;
2352 q += len_replace;
2353 s = strstr(p, find);
2354 if (s == NULL) s = p + strlen(p);
2355 memmove(q, p, s-p);
2356 q += s-p;
2357 p = s;
2358 }
2359 *q = 0;
2360 }
2361
stb_fixpath(char * path)2362 void stb_fixpath(char *path)
2363 {
2364 for(; *path; ++path)
2365 if (*path == '\\')
2366 *path = '/';
2367 }
2368
stb__add_section(char * buffer,char * data,ptrdiff_t curlen,ptrdiff_t newlen)2369 void stb__add_section(char *buffer, char *data, ptrdiff_t curlen, ptrdiff_t newlen)
2370 {
2371 if (newlen < curlen) {
2372 ptrdiff_t z1 = newlen >> 1, z2 = newlen-z1;
2373 memcpy(buffer, data, z1-1);
2374 buffer[z1-1] = '.';
2375 buffer[z1-0] = '.';
2376 memcpy(buffer+z1+1, data+curlen-z2+1, z2-1);
2377 } else
2378 memcpy(buffer, data, curlen);
2379 }
2380
stb_shorten_path_readable(char * path,int len)2381 char * stb_shorten_path_readable(char *path, int len)
2382 {
2383 static char buffer[1024];
2384 ptrdiff_t n = strlen(path),n1,n2,r1,r2;
2385 char *s;
2386 if (n <= len) return path;
2387 if (len > 1024) return path;
2388 s = stb_strrchr2(path, '/', '\\');
2389 if (s) {
2390 n1 = s - path + 1;
2391 n2 = n - n1;
2392 ++s;
2393 } else {
2394 n1 = 0;
2395 n2 = n;
2396 s = path;
2397 }
2398 // now we need to reduce r1 and r2 so that they fit in len
2399 if (n1 < len>>1) {
2400 r1 = n1;
2401 r2 = len - r1;
2402 } else if (n2 < len >> 1) {
2403 r2 = n2;
2404 r1 = len - r2;
2405 } else {
2406 r1 = n1 * len / n;
2407 r2 = n2 * len / n;
2408 if (r1 < len>>2) r1 = len>>2, r2 = len-r1;
2409 if (r2 < len>>2) r2 = len>>2, r1 = len-r2;
2410 }
2411 assert(r1 <= n1 && r2 <= n2);
2412 if (n1)
2413 stb__add_section(buffer, path, n1, r1);
2414 stb__add_section(buffer+r1, s, n2, r2);
2415 buffer[len] = 0;
2416 return buffer;
2417 }
2418
stb__splitpath_raw(char * buffer,char * path,int flag)2419 static char *stb__splitpath_raw(char *buffer, char *path, int flag)
2420 {
2421 ptrdiff_t len=0,x,y, n = (int) strlen(path), f1,f2;
2422 char *s = stb_strrchr2(path, '/', '\\');
2423 char *t = strrchr(path, '.');
2424 if (s && t && t < s) t = NULL;
2425 if (s) ++s;
2426
2427 if (flag == STB_EXT_NO_PERIOD)
2428 flag |= STB_EXT;
2429
2430 if (!(flag & (STB_PATH | STB_FILE | STB_EXT))) return NULL;
2431
2432 f1 = s == NULL ? 0 : s-path; // start of filename
2433 f2 = t == NULL ? n : t-path; // just past end of filename
2434
2435 if (flag & STB_PATH) {
2436 x = 0; if (f1 == 0 && flag == STB_PATH) len=2;
2437 } else if (flag & STB_FILE) {
2438 x = f1;
2439 } else {
2440 x = f2;
2441 if (flag & STB_EXT_NO_PERIOD)
2442 if (path[x] == '.')
2443 ++x;
2444 }
2445
2446 if (flag & STB_EXT)
2447 y = n;
2448 else if (flag & STB_FILE)
2449 y = f2;
2450 else
2451 y = f1;
2452
2453 if (buffer == NULL) {
2454 buffer = (char *) malloc(y-x + len + 1);
2455 if (!buffer) return NULL;
2456 }
2457
2458 if (len) { stb_p_strcpy_s(buffer, 3, "./"); return buffer; }
2459 stb_strncpy(buffer, path+(int)x, (int)(y-x));
2460 return buffer;
2461 }
2462
stb_splitpath(char * output,char * src,int flag)2463 char *stb_splitpath(char *output, char *src, int flag)
2464 {
2465 return stb__splitpath_raw(output, src, flag);
2466 }
2467
stb_splitpathdup(char * src,int flag)2468 char *stb_splitpathdup(char *src, int flag)
2469 {
2470 return stb__splitpath_raw(NULL, src, flag);
2471 }
2472
stb_replacedir(char * output,char * src,char * dir)2473 char *stb_replacedir(char *output, char *src, char *dir)
2474 {
2475 char buffer[4096];
2476 stb_splitpath(buffer, src, STB_FILE | STB_EXT);
2477 if (dir)
2478 stb_p_sprintf(output stb_p_size(9999), "%s/%s", dir, buffer);
2479 else
2480 stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
2481 return output;
2482 }
2483
stb_replaceext(char * output,char * src,char * ext)2484 char *stb_replaceext(char *output, char *src, char *ext)
2485 {
2486 char buffer[4096];
2487 stb_splitpath(buffer, src, STB_PATH | STB_FILE);
2488 if (ext)
2489 stb_p_sprintf(output stb_p_size(9999), "%s.%s", buffer, ext[0] == '.' ? ext+1 : ext);
2490 else
2491 stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
2492 return output;
2493 }
2494 #endif
2495
2496 //////////////////////////////////////////////////////////////////////////////
2497 //
2498 // stb_alloc - hierarchical allocator
2499 //
2500 // inspired by http://swapped.cc/halloc
2501 //
2502 //
2503 // When you alloc a given block through stb_alloc, you have these choices:
2504 //
2505 // 1. does it have a parent?
2506 // 2. can it have children?
2507 // 3. can it be freed directly?
2508 // 4. is it transferrable?
2509 // 5. what is its alignment?
2510 //
2511 // Here are interesting combinations of those:
2512 //
2513 // children free transfer alignment
2514 // arena Y Y N n/a
2515 // no-overhead, chunked N N N normal
2516 // string pool alloc N N N 1
2517 // parent-ptr, chunked Y N N normal
2518 // low-overhead, unchunked N Y Y normal
2519 // general purpose alloc Y Y Y normal
2520 //
2521 // Unchunked allocations will probably return 16-aligned pointers. If
2522 // we 16-align the results, we have room for 4 pointers. For smaller
2523 // allocations that allow finer alignment, we can reduce the pointers.
2524 //
2525 // The strategy is that given a pointer, assuming it has a header (only
2526 // the no-overhead allocations have no header), we can determine the
2527 // type of the header fields, and the number of them, by stepping backwards
2528 // through memory and looking at the tags in the bottom bits.
2529 //
2530 // Implementation strategy:
2531 // chunked allocations come from the middle of chunks, and can't
2532 // be freed. thefore they do not need to be on a sibling chain.
2533 // they may need child pointers if they have children.
2534 //
2535 // chunked, with-children
2536 // void *parent;
2537 //
2538 // unchunked, no-children -- reduced storage
2539 // void *next_sibling;
2540 // void *prev_sibling_nextp;
2541 //
2542 // unchunked, general
2543 // void *first_child;
2544 // void *next_sibling;
2545 // void *prev_sibling_nextp;
2546 // void *chunks;
2547 //
2548 // so, if we code each of these fields with different bit patterns
2549 // (actually same one for next/prev/child), then we can identify which
2550 // each one is from the last field.
2551
2552 STB_EXTERN void stb_free(void *p);
2553 STB_EXTERN void *stb_malloc_global(size_t size);
2554 STB_EXTERN void *stb_malloc(void *context, size_t size);
2555 STB_EXTERN void *stb_malloc_nofree(void *context, size_t size);
2556 STB_EXTERN void *stb_malloc_leaf(void *context, size_t size);
2557 STB_EXTERN void *stb_malloc_raw(void *context, size_t size);
2558 STB_EXTERN void *stb_realloc(void *ptr, size_t newsize);
2559
2560 STB_EXTERN void stb_reassign(void *new_context, void *ptr);
2561 STB_EXTERN void stb_malloc_validate(void *p, void *parent);
2562
2563 extern int stb_alloc_chunk_size ;
2564 extern int stb_alloc_count_free ;
2565 extern int stb_alloc_count_alloc;
2566 extern int stb_alloc_alignment ;
2567
2568 #ifdef STB_DEFINE
2569
2570 int stb_alloc_chunk_size = 65536;
2571 int stb_alloc_count_free = 0;
2572 int stb_alloc_count_alloc = 0;
2573 int stb_alloc_alignment = -16;
2574
2575 typedef struct stb__chunk
2576 {
2577 struct stb__chunk *next;
2578 int data_left;
2579 int alloc;
2580 } stb__chunk;
2581
2582 typedef struct
2583 {
2584 void * next;
2585 void ** prevn;
2586 } stb__nochildren;
2587
2588 typedef struct
2589 {
2590 void ** prevn;
2591 void * child;
2592 void * next;
2593 stb__chunk *chunks;
2594 } stb__alloc;
2595
2596 typedef struct
2597 {
2598 stb__alloc *parent;
2599 } stb__chunked;
2600
2601 #define STB__PARENT 1
2602 #define STB__CHUNKS 2
2603
2604 typedef enum
2605 {
2606 STB__nochildren = 0,
2607 STB__chunked = STB__PARENT,
2608 STB__alloc = STB__CHUNKS,
2609
2610 STB__chunk_raw = 4,
2611 } stb__alloc_type;
2612
2613 // these functions set the bottom bits of a pointer efficiently
2614 #define STB__DECODE(x,v) ((void *) ((char *) (x) - (v)))
2615 #define STB__ENCODE(x,v) ((void *) ((char *) (x) + (v)))
2616
2617 #define stb__parent(z) (stb__alloc *) STB__DECODE((z)->parent, STB__PARENT)
2618 #define stb__chunks(z) (stb__chunk *) STB__DECODE((z)->chunks, STB__CHUNKS)
2619
2620 #define stb__setparent(z,p) (z)->parent = (stb__alloc *) STB__ENCODE((p), STB__PARENT)
2621 #define stb__setchunks(z,c) (z)->chunks = (stb__chunk *) STB__ENCODE((c), STB__CHUNKS)
2622
2623 static stb__alloc stb__alloc_global =
2624 {
2625 NULL,
2626 NULL,
2627 NULL,
2628 (stb__chunk *) STB__ENCODE(NULL, STB__CHUNKS)
2629 };
2630
stb__identify(void * p)2631 static stb__alloc_type stb__identify(void *p)
2632 {
2633 void **q = (void **) p;
2634 return (stb__alloc_type) ((stb_uinta) q[-1] & 3);
2635 }
2636
stb__prevn(void * p)2637 static void *** stb__prevn(void *p)
2638 {
2639 if (stb__identify(p) == STB__alloc) {
2640 stb__alloc *s = (stb__alloc *) p - 1;
2641 return &s->prevn;
2642 } else {
2643 stb__nochildren *s = (stb__nochildren *) p - 1;
2644 return &s->prevn;
2645 }
2646 }
2647
stb_free(void * p)2648 void stb_free(void *p)
2649 {
2650 if (p == NULL) return;
2651
2652 // count frees so that unit tests can see what's happening
2653 ++stb_alloc_count_free;
2654
2655 switch(stb__identify(p)) {
2656 case STB__chunked:
2657 // freeing a chunked-block with children does nothing;
2658 // they only get freed when the parent does
2659 // surely this is wrong, and it should free them immediately?
2660 // otherwise how are they getting put on the right chain?
2661 return;
2662 case STB__nochildren: {
2663 stb__nochildren *s = (stb__nochildren *) p - 1;
2664 // unlink from sibling chain
2665 *(s->prevn) = s->next;
2666 if (s->next)
2667 *stb__prevn(s->next) = s->prevn;
2668 free(s);
2669 return;
2670 }
2671 case STB__alloc: {
2672 stb__alloc *s = (stb__alloc *) p - 1;
2673 stb__chunk *c, *n;
2674 void *q;
2675
2676 // unlink from sibling chain, if any
2677 *(s->prevn) = s->next;
2678 if (s->next)
2679 *stb__prevn(s->next) = s->prevn;
2680
2681 // first free chunks
2682 c = (stb__chunk *) stb__chunks(s);
2683 while (c != NULL) {
2684 n = c->next;
2685 stb_alloc_count_free += c->alloc;
2686 free(c);
2687 c = n;
2688 }
2689
2690 // validating
2691 stb__setchunks(s,NULL);
2692 s->prevn = NULL;
2693 s->next = NULL;
2694
2695 // now free children
2696 while ((q = s->child) != NULL) {
2697 stb_free(q);
2698 }
2699
2700 // now free self
2701 free(s);
2702 return;
2703 }
2704 default:
2705 assert(0); /* NOTREACHED */
2706 }
2707 }
2708
stb_malloc_validate(void * p,void * parent)2709 void stb_malloc_validate(void *p, void *parent)
2710 {
2711 if (p == NULL) return;
2712
2713 switch(stb__identify(p)) {
2714 case STB__chunked:
2715 return;
2716 case STB__nochildren: {
2717 stb__nochildren *n = (stb__nochildren *) p - 1;
2718 if (n->prevn)
2719 assert(*n->prevn == p);
2720 if (n->next) {
2721 assert(*stb__prevn(n->next) == &n->next);
2722 stb_malloc_validate(n, parent);
2723 }
2724 return;
2725 }
2726 case STB__alloc: {
2727 stb__alloc *s = (stb__alloc *) p - 1;
2728
2729 if (s->prevn)
2730 assert(*s->prevn == p);
2731
2732 if (s->child) {
2733 assert(*stb__prevn(s->child) == &s->child);
2734 stb_malloc_validate(s->child, p);
2735 }
2736
2737 if (s->next) {
2738 assert(*stb__prevn(s->next) == &s->next);
2739 stb_malloc_validate(s->next, parent);
2740 }
2741 return;
2742 }
2743 default:
2744 assert(0); /* NOTREACHED */
2745 }
2746 }
2747
stb__try_chunk(stb__chunk * c,int size,int align,int pre_align)2748 static void * stb__try_chunk(stb__chunk *c, int size, int align, int pre_align)
2749 {
2750 char *memblock = (char *) (c+1), *q;
2751 stb_inta iq;
2752 int start_offset;
2753
2754 // we going to allocate at the end of the chunk, not the start. confusing,
2755 // but it means we don't need both a 'limit' and a 'cur', just a 'cur'.
2756 // the block ends at: p + c->data_left
2757 // then we move back by size
2758 start_offset = c->data_left - size;
2759
2760 // now we need to check the alignment of that
2761 q = memblock + start_offset;
2762 iq = (stb_inta) q;
2763 assert(sizeof(q) == sizeof(iq));
2764
2765 // suppose align = 2
2766 // then we need to retreat iq far enough that (iq & (2-1)) == 0
2767 // to get (iq & (align-1)) = 0 requires subtracting (iq & (align-1))
2768
2769 start_offset -= iq & (align-1);
2770 assert(((stb_uinta) (memblock+start_offset) & (align-1)) == 0);
2771
2772 // now, if that + pre_align works, go for it!
2773 start_offset -= pre_align;
2774
2775 if (start_offset >= 0) {
2776 c->data_left = start_offset;
2777 return memblock + start_offset;
2778 }
2779
2780 return NULL;
2781 }
2782
stb__sort_chunks(stb__alloc * src)2783 static void stb__sort_chunks(stb__alloc *src)
2784 {
2785 // of the first two chunks, put the chunk with more data left in it first
2786 stb__chunk *c = stb__chunks(src), *d;
2787 if (c == NULL) return;
2788 d = c->next;
2789 if (d == NULL) return;
2790 if (c->data_left > d->data_left) return;
2791
2792 c->next = d->next;
2793 d->next = c;
2794 stb__setchunks(src, d);
2795 }
2796
stb__alloc_chunk(stb__alloc * src,int size,int align,int pre_align)2797 static void * stb__alloc_chunk(stb__alloc *src, int size, int align, int pre_align)
2798 {
2799 void *p;
2800 stb__chunk *c = stb__chunks(src);
2801
2802 if (c && size <= stb_alloc_chunk_size) {
2803
2804 p = stb__try_chunk(c, size, align, pre_align);
2805 if (p) { ++c->alloc; return p; }
2806
2807 // try a second chunk to reduce wastage
2808 if (c->next) {
2809 p = stb__try_chunk(c->next, size, align, pre_align);
2810 if (p) { ++c->alloc; return p; }
2811
2812 // put the bigger chunk first, since the second will get buried
2813 // the upshot of this is that, until it gets allocated from, chunk #2
2814 // is always the largest remaining chunk. (could formalize
2815 // this with a heap!)
2816 stb__sort_chunks(src);
2817 c = stb__chunks(src);
2818 }
2819 }
2820
2821 // allocate a new chunk
2822 {
2823 stb__chunk *n;
2824
2825 int chunk_size = stb_alloc_chunk_size;
2826 // we're going to allocate a new chunk to put this in
2827 if (size > chunk_size)
2828 chunk_size = size;
2829
2830 assert(sizeof(*n) + pre_align <= 16);
2831
2832 // loop trying to allocate a large enough chunk
2833 // the loop is because the alignment may cause problems if it's big...
2834 // and we don't know what our chunk alignment is going to be
2835 while (1) {
2836 n = (stb__chunk *) malloc(16 + chunk_size);
2837 if (n == NULL) return NULL;
2838
2839 n->data_left = chunk_size - sizeof(*n);
2840
2841 p = stb__try_chunk(n, size, align, pre_align);
2842 if (p != NULL) {
2843 n->next = c;
2844 stb__setchunks(src, n);
2845
2846 // if we just used up the whole block immediately,
2847 // move the following chunk up
2848 n->alloc = 1;
2849 if (size == chunk_size)
2850 stb__sort_chunks(src);
2851
2852 return p;
2853 }
2854
2855 free(n);
2856 chunk_size += 16+align;
2857 }
2858 }
2859 }
2860
stb__get_context(void * context)2861 static stb__alloc * stb__get_context(void *context)
2862 {
2863 if (context == NULL) {
2864 return &stb__alloc_global;
2865 } else {
2866 int u = stb__identify(context);
2867 // if context is chunked, grab parent
2868 if (u == STB__chunked) {
2869 stb__chunked *s = (stb__chunked *) context - 1;
2870 return stb__parent(s);
2871 } else {
2872 return (stb__alloc *) context - 1;
2873 }
2874 }
2875 }
2876
stb__insert_alloc(stb__alloc * src,stb__alloc * s)2877 static void stb__insert_alloc(stb__alloc *src, stb__alloc *s)
2878 {
2879 s->prevn = &src->child;
2880 s->next = src->child;
2881 src->child = s+1;
2882 if (s->next)
2883 *stb__prevn(s->next) = &s->next;
2884 }
2885
stb__insert_nochild(stb__alloc * src,stb__nochildren * s)2886 static void stb__insert_nochild(stb__alloc *src, stb__nochildren *s)
2887 {
2888 s->prevn = &src->child;
2889 s->next = src->child;
2890 src->child = s+1;
2891 if (s->next)
2892 *stb__prevn(s->next) = &s->next;
2893 }
2894
malloc_base(void * context,size_t size,stb__alloc_type t,int align)2895 static void * malloc_base(void *context, size_t size, stb__alloc_type t, int align)
2896 {
2897 void *p;
2898
2899 stb__alloc *src = stb__get_context(context);
2900
2901 if (align <= 0) {
2902 // compute worst-case C packed alignment
2903 // e.g. a 24-byte struct is 8-aligned
2904 int align_proposed = 1 << stb_lowbit8((unsigned int) size);
2905
2906 if (align_proposed < 0)
2907 align_proposed = 4;
2908
2909 if (align_proposed == 0) {
2910 if (size == 0)
2911 align_proposed = 1;
2912 else
2913 align_proposed = 256;
2914 }
2915
2916 // a negative alignment means 'don't align any larger
2917 // than this'; so -16 means we align 1,2,4,8, or 16
2918
2919 if (align < 0) {
2920 if (align_proposed > -align)
2921 align_proposed = -align;
2922 }
2923
2924 align = align_proposed;
2925 }
2926
2927 assert(stb_is_pow2(align));
2928
2929 // don't cause misalignment when allocating nochildren
2930 if (t == STB__nochildren && align > 8)
2931 t = STB__alloc;
2932
2933 switch (t) {
2934 case STB__alloc: {
2935 stb__alloc *s = (stb__alloc *) malloc(size + sizeof(*s));
2936 if (s == NULL) return NULL;
2937 p = s+1;
2938 s->child = NULL;
2939 stb__insert_alloc(src, s);
2940
2941 stb__setchunks(s,NULL);
2942 break;
2943 }
2944
2945 case STB__nochildren: {
2946 stb__nochildren *s = (stb__nochildren *) malloc(size + sizeof(*s));
2947 if (s == NULL) return NULL;
2948 p = s+1;
2949 stb__insert_nochild(src, s);
2950 break;
2951 }
2952
2953 case STB__chunk_raw: {
2954 p = stb__alloc_chunk(src, (int) size, align, 0);
2955 if (p == NULL) return NULL;
2956 break;
2957 }
2958
2959 case STB__chunked: {
2960 stb__chunked *s;
2961 if (align < sizeof(stb_uintptr)) align = sizeof(stb_uintptr);
2962 s = (stb__chunked *) stb__alloc_chunk(src, (int) size, align, sizeof(*s));
2963 if (s == NULL) return NULL;
2964 stb__setparent(s, src);
2965 p = s+1;
2966 break;
2967 }
2968
2969 default: p = NULL; assert(0); /* NOTREACHED */
2970 }
2971
2972 ++stb_alloc_count_alloc;
2973 return p;
2974 }
2975
stb_malloc_global(size_t size)2976 void *stb_malloc_global(size_t size)
2977 {
2978 return malloc_base(NULL, size, STB__alloc, stb_alloc_alignment);
2979 }
2980
stb_malloc(void * context,size_t size)2981 void *stb_malloc(void *context, size_t size)
2982 {
2983 return malloc_base(context, size, STB__alloc, stb_alloc_alignment);
2984 }
2985
stb_malloc_nofree(void * context,size_t size)2986 void *stb_malloc_nofree(void *context, size_t size)
2987 {
2988 return malloc_base(context, size, STB__chunked, stb_alloc_alignment);
2989 }
2990
stb_malloc_leaf(void * context,size_t size)2991 void *stb_malloc_leaf(void *context, size_t size)
2992 {
2993 return malloc_base(context, size, STB__nochildren, stb_alloc_alignment);
2994 }
2995
stb_malloc_raw(void * context,size_t size)2996 void *stb_malloc_raw(void *context, size_t size)
2997 {
2998 return malloc_base(context, size, STB__chunk_raw, stb_alloc_alignment);
2999 }
3000
stb_malloc_string(void * context,size_t size)3001 char *stb_malloc_string(void *context, size_t size)
3002 {
3003 return (char *) malloc_base(context, size, STB__chunk_raw, 1);
3004 }
3005
stb_realloc(void * ptr,size_t newsize)3006 void *stb_realloc(void *ptr, size_t newsize)
3007 {
3008 stb__alloc_type t;
3009
3010 if (ptr == NULL) return stb_malloc(NULL, newsize);
3011 if (newsize == 0) { stb_free(ptr); return NULL; }
3012
3013 t = stb__identify(ptr);
3014 assert(t == STB__alloc || t == STB__nochildren);
3015
3016 if (t == STB__alloc) {
3017 stb__alloc *s = (stb__alloc *) ptr - 1;
3018
3019 s = (stb__alloc *) realloc(s, newsize + sizeof(*s));
3020 if (s == NULL) return NULL;
3021
3022 ptr = s+1;
3023
3024 // update pointers
3025 (*s->prevn) = ptr;
3026 if (s->next)
3027 *stb__prevn(s->next) = &s->next;
3028
3029 if (s->child)
3030 *stb__prevn(s->child) = &s->child;
3031
3032 return ptr;
3033 } else {
3034 stb__nochildren *s = (stb__nochildren *) ptr - 1;
3035
3036 s = (stb__nochildren *) realloc(ptr, newsize + sizeof(s));
3037 if (s == NULL) return NULL;
3038
3039 // update pointers
3040 (*s->prevn) = s+1;
3041 if (s->next)
3042 *stb__prevn(s->next) = &s->next;
3043
3044 return s+1;
3045 }
3046 }
3047
stb_realloc_c(void * context,void * ptr,size_t newsize)3048 void *stb_realloc_c(void *context, void *ptr, size_t newsize)
3049 {
3050 if (ptr == NULL) return stb_malloc(context, newsize);
3051 if (newsize == 0) { stb_free(ptr); return NULL; }
3052 // @TODO: verify you haven't changed contexts
3053 return stb_realloc(ptr, newsize);
3054 }
3055
stb_reassign(void * new_context,void * ptr)3056 void stb_reassign(void *new_context, void *ptr)
3057 {
3058 stb__alloc *src = stb__get_context(new_context);
3059
3060 stb__alloc_type t = stb__identify(ptr);
3061 assert(t == STB__alloc || t == STB__nochildren);
3062
3063 if (t == STB__alloc) {
3064 stb__alloc *s = (stb__alloc *) ptr - 1;
3065
3066 // unlink from old
3067 *(s->prevn) = s->next;
3068 if (s->next)
3069 *stb__prevn(s->next) = s->prevn;
3070
3071 stb__insert_alloc(src, s);
3072 } else {
3073 stb__nochildren *s = (stb__nochildren *) ptr - 1;
3074
3075 // unlink from old
3076 *(s->prevn) = s->next;
3077 if (s->next)
3078 *stb__prevn(s->next) = s->prevn;
3079
3080 stb__insert_nochild(src, s);
3081 }
3082 }
3083
3084 #endif
3085
3086
3087 //////////////////////////////////////////////////////////////////////////////
3088 //
3089 // stb_arr
3090 //
3091 // An stb_arr is directly useable as a pointer (use the actual type in your
3092 // definition), but when it resizes, it returns a new pointer and you can't
3093 // use the old one, so you have to be careful to copy-in-out as necessary.
3094 //
3095 // Use a NULL pointer as a 0-length array.
3096 //
3097 // float *my_array = NULL, *temp;
3098 //
3099 // // add elements on the end one at a time
3100 // stb_arr_push(my_array, 0.0f);
3101 // stb_arr_push(my_array, 1.0f);
3102 // stb_arr_push(my_array, 2.0f);
3103 //
3104 // assert(my_array[1] == 2.0f);
3105 //
3106 // // add an uninitialized element at the end, then assign it
3107 // *stb_arr_add(my_array) = 3.0f;
3108 //
3109 // // add three uninitialized elements at the end
3110 // temp = stb_arr_addn(my_array,3);
3111 // temp[0] = 4.0f;
3112 // temp[1] = 5.0f;
3113 // temp[2] = 6.0f;
3114 //
3115 // assert(my_array[5] == 5.0f);
3116 //
3117 // // remove the last one
3118 // stb_arr_pop(my_array);
3119 //
3120 // assert(stb_arr_len(my_array) == 6);
3121
3122
3123 #ifdef STB_MALLOC_WRAPPER
3124 #define STB__PARAMS , char *file, int line
3125 #define STB__ARGS , file, line
3126 #else
3127 #define STB__PARAMS
3128 #define STB__ARGS
3129 #endif
3130
3131 // calling this function allocates an empty stb_arr attached to p
3132 // (whereas NULL isn't attached to anything)
3133 STB_EXTERN void stb_arr_malloc(void **target, void *context);
3134
3135 // call this function with a non-NULL value to have all successive
3136 // stbs that are created be attached to the associated parent. Note
3137 // that once a given stb_arr is non-empty, it stays attached to its
3138 // current parent, even if you call this function again.
3139 // it turns the previous value, so you can restore it
3140 STB_EXTERN void* stb_arr_malloc_parent(void *p);
3141
3142 // simple functions written on top of other functions
3143 #define stb_arr_empty(a) ( stb_arr_len(a) == 0 )
3144 #define stb_arr_add(a) ( stb_arr_addn((a),1) )
3145 #define stb_arr_push(a,v) ( *stb_arr_add(a)=(v) )
3146
3147 typedef struct
3148 {
3149 int len, limit;
3150 int stb_malloc;
3151 unsigned int signature;
3152 } stb__arr;
3153
3154 #define stb_arr_signature 0x51bada7b // ends with 0123 in decimal
3155
3156 // access the header block stored before the data
3157 #define stb_arrhead(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3158 #define stb_arrhead2(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3159
3160 #ifdef STB_DEBUG
3161 #define stb_arr_check(a) assert(!a || stb_arrhead(a)->signature == stb_arr_signature)
3162 #define stb_arr_check2(a) assert(!a || stb_arrhead2(a)->signature == stb_arr_signature)
3163 #else
3164 #define stb_arr_check(a) ((void) 0)
3165 #define stb_arr_check2(a) ((void) 0)
3166 #endif
3167
3168 // ARRAY LENGTH
3169
3170 // get the array length; special case if pointer is NULL
3171 #define stb_arr_len(a) (a ? stb_arrhead(a)->len : 0)
3172 #define stb_arr_len2(a) ((stb__arr *) (a) ? stb_arrhead2(a)->len : 0)
3173 #define stb_arr_lastn(a) (stb_arr_len(a)-1)
3174
3175 // check whether a given index is valid -- tests 0 <= i < stb_arr_len(a)
3176 #define stb_arr_valid(a,i) (a ? (int) (i) < stb_arrhead(a)->len : 0)
3177
3178 // change the array length so is is exactly N entries long, creating
3179 // uninitialized entries as needed
3180 #define stb_arr_setlen(a,n) \
3181 (stb__arr_setlen((void **) &(a), sizeof(a[0]), (n)))
3182
3183 // change the array length so that N is a valid index (that is, so
3184 // it is at least N entries long), creating uninitialized entries as needed
3185 #define stb_arr_makevalid(a,n) \
3186 (stb_arr_len(a) < (n)+1 ? stb_arr_setlen(a,(n)+1),(a) : (a))
3187
3188 // remove the last element of the array, returning it
3189 #define stb_arr_pop(a) ((stb_arr_check(a), (a))[--stb_arrhead(a)->len])
3190
3191 // access the last element in the array
3192 #define stb_arr_last(a) ((stb_arr_check(a), (a))[stb_arr_len(a)-1])
3193
3194 // is iterator at end of list?
3195 #define stb_arr_end(a,i) ((i) >= &(a)[stb_arr_len(a)])
3196
3197 // (internal) change the allocated length of the array
3198 #define stb_arr__grow(a,n) (stb_arr_check(a), stb_arrhead(a)->len += (n))
3199
3200 // add N new uninitialized elements to the end of the array
3201 #define stb_arr__addn(a,n) /*lint --e(826)*/ \
3202 ((stb_arr_len(a)+(n) > stb_arrcurmax(a)) \
3203 ? (stb__arr_addlen((void **) &(a),sizeof(*a),(n)),0) \
3204 : ((stb_arr__grow(a,n), 0)))
3205
3206 // add N new uninitialized elements to the end of the array, and return
3207 // a pointer to the first new one
3208 #define stb_arr_addn(a,n) (stb_arr__addn((a),n),(a)+stb_arr_len(a)-(n))
3209
3210 // add N new uninitialized elements starting at index 'i'
3211 #define stb_arr_insertn(a,i,n) (stb__arr_insertn((void **) &(a), sizeof(*a), (i), (n)))
3212
3213 // insert an element at i
3214 #define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), (i), (1)), ((a)[i] = v))
3215
3216 // delete N elements from the middle starting at index 'i'
3217 #define stb_arr_deleten(a,i,n) (stb__arr_deleten((void **) &(a), sizeof(*a), (i), (n)))
3218
3219 // delete the i'th element
3220 #define stb_arr_delete(a,i) stb_arr_deleten(a,i,1)
3221
3222 // delete the i'th element, swapping down from the end
3223 #define stb_arr_fastdelete(a,i) \
3224 (stb_swap(&a[i], &a[stb_arrhead(a)->len-1], sizeof(*a)), stb_arr_pop(a))
3225
3226
3227 // ARRAY STORAGE
3228
3229 // get the array maximum storage; special case if NULL
3230 #define stb_arrcurmax(a) (a ? stb_arrhead(a)->limit : 0)
3231 #define stb_arrcurmax2(a) (a ? stb_arrhead2(a)->limit : 0)
3232
3233 // set the maxlength of the array to n in anticipation of further growth
3234 #define stb_arr_setsize(a,n) (stb_arr_check(a), stb__arr_setsize((void **) &(a),sizeof((a)[0]),n))
3235
3236 // make sure maxlength is large enough for at least N new allocations
3237 #define stb_arr_atleast(a,n) (stb_arr_len(a)+(n) > stb_arrcurmax(a) \
3238 ? stb_arr_setsize((a), (n)) : 0)
3239
3240 // make a copy of a given array (copies contents via 'memcpy'!)
3241 #define stb_arr_copy(a) stb__arr_copy(a, sizeof((a)[0]))
3242
3243 // compute the storage needed to store all the elements of the array
3244 #define stb_arr_storage(a) (stb_arr_len(a) * sizeof((a)[0]))
3245
3246 #define stb_arr_for(v,arr) for((v)=(arr); (v) < (arr)+stb_arr_len(arr); ++(v))
3247
3248 // IMPLEMENTATION
3249
3250 STB_EXTERN void stb_arr_free_(void **p);
3251 STB_EXTERN void *stb__arr_copy_(void *p, int elem_size);
3252 STB_EXTERN void stb__arr_setsize_(void **p, int size, int limit STB__PARAMS);
3253 STB_EXTERN void stb__arr_setlen_(void **p, int size, int newlen STB__PARAMS);
3254 STB_EXTERN void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS);
3255 STB_EXTERN void stb__arr_deleten_(void **p, int size, int loc, int n STB__PARAMS);
3256 STB_EXTERN void stb__arr_insertn_(void **p, int size, int loc, int n STB__PARAMS);
3257
3258 #define stb_arr_free(p) stb_arr_free_((void **) &(p))
3259 #define stb__arr_copy stb__arr_copy_
3260
3261 #ifndef STB_MALLOC_WRAPPER
3262 #define stb__arr_setsize stb__arr_setsize_
3263 #define stb__arr_setlen stb__arr_setlen_
3264 #define stb__arr_addlen stb__arr_addlen_
3265 #define stb__arr_deleten stb__arr_deleten_
3266 #define stb__arr_insertn stb__arr_insertn_
3267 #else
3268 #define stb__arr_addlen(p,s,n) stb__arr_addlen_(p,s,n,__FILE__,__LINE__)
3269 #define stb__arr_setlen(p,s,n) stb__arr_setlen_(p,s,n,__FILE__,__LINE__)
3270 #define stb__arr_setsize(p,s,n) stb__arr_setsize_(p,s,n,__FILE__,__LINE__)
3271 #define stb__arr_deleten(p,s,i,n) stb__arr_deleten_(p,s,i,n,__FILE__,__LINE__)
3272 #define stb__arr_insertn(p,s,i,n) stb__arr_insertn_(p,s,i,n,__FILE__,__LINE__)
3273 #endif
3274
3275 #ifdef STB_DEFINE
3276 static void *stb__arr_context;
3277
stb_arr_malloc_parent(void * p)3278 void *stb_arr_malloc_parent(void *p)
3279 {
3280 void *q = stb__arr_context;
3281 stb__arr_context = p;
3282 return q;
3283 }
3284
stb_arr_malloc(void ** target,void * context)3285 void stb_arr_malloc(void **target, void *context)
3286 {
3287 stb__arr *q = (stb__arr *) stb_malloc(context, sizeof(*q));
3288 q->len = q->limit = 0;
3289 q->stb_malloc = 1;
3290 q->signature = stb_arr_signature;
3291 *target = (void *) (q+1);
3292 }
3293
stb__arr_malloc(int size)3294 static void * stb__arr_malloc(int size)
3295 {
3296 if (stb__arr_context)
3297 return stb_malloc(stb__arr_context, size);
3298 return malloc(size);
3299 }
3300
stb__arr_copy_(void * p,int elem_size)3301 void * stb__arr_copy_(void *p, int elem_size)
3302 {
3303 stb__arr *q;
3304 if (p == NULL) return p;
3305 q = (stb__arr *) stb__arr_malloc(sizeof(*q) + elem_size * stb_arrhead2(p)->limit);
3306 stb_arr_check2(p);
3307 memcpy(q, stb_arrhead2(p), sizeof(*q) + elem_size * stb_arrhead2(p)->len);
3308 q->stb_malloc = !!stb__arr_context;
3309 return q+1;
3310 }
3311
stb_arr_free_(void ** pp)3312 void stb_arr_free_(void **pp)
3313 {
3314 void *p = *pp;
3315 stb_arr_check2(p);
3316 if (p) {
3317 stb__arr *q = stb_arrhead2(p);
3318 if (q->stb_malloc)
3319 stb_free(q);
3320 else
3321 free(q);
3322 }
3323 *pp = NULL;
3324 }
3325
stb__arrsize_(void ** pp,int size,int limit,int len STB__PARAMS)3326 static void stb__arrsize_(void **pp, int size, int limit, int len STB__PARAMS)
3327 {
3328 void *p = *pp;
3329 stb__arr *a;
3330 stb_arr_check2(p);
3331 if (p == NULL) {
3332 if (len == 0 && size == 0) return;
3333 a = (stb__arr *) stb__arr_malloc(sizeof(*a) + size*limit);
3334 a->limit = limit;
3335 a->len = len;
3336 a->stb_malloc = !!stb__arr_context;
3337 a->signature = stb_arr_signature;
3338 } else {
3339 a = stb_arrhead2(p);
3340 a->len = len;
3341 if (a->limit < limit) {
3342 void *p;
3343 if (a->limit >= 4 && limit < a->limit * 2)
3344 limit = a->limit * 2;
3345 if (a->stb_malloc)
3346 p = stb_realloc(a, sizeof(*a) + limit*size);
3347 else
3348 #ifdef STB_MALLOC_WRAPPER
3349 p = stb__realloc(a, sizeof(*a) + limit*size, file, line);
3350 #else
3351 p = realloc(a, sizeof(*a) + limit*size);
3352 #endif
3353 if (p) {
3354 a = (stb__arr *) p;
3355 a->limit = limit;
3356 } else {
3357 // throw an error!
3358 }
3359 }
3360 }
3361 a->len = stb_min(a->len, a->limit);
3362 *pp = a+1;
3363 }
3364
stb__arr_setsize_(void ** pp,int size,int limit STB__PARAMS)3365 void stb__arr_setsize_(void **pp, int size, int limit STB__PARAMS)
3366 {
3367 void *p = *pp;
3368 stb_arr_check2(p);
3369 stb__arrsize_(pp, size, limit, stb_arr_len2(p) STB__ARGS);
3370 }
3371
stb__arr_setlen_(void ** pp,int size,int newlen STB__PARAMS)3372 void stb__arr_setlen_(void **pp, int size, int newlen STB__PARAMS)
3373 {
3374 void *p = *pp;
3375 stb_arr_check2(p);
3376 if (stb_arrcurmax2(p) < newlen || p == NULL) {
3377 stb__arrsize_(pp, size, newlen, newlen STB__ARGS);
3378 } else {
3379 stb_arrhead2(p)->len = newlen;
3380 }
3381 }
3382
stb__arr_addlen_(void ** p,int size,int addlen STB__PARAMS)3383 void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS)
3384 {
3385 stb__arr_setlen_(p, size, stb_arr_len2(*p) + addlen STB__ARGS);
3386 }
3387
stb__arr_insertn_(void ** pp,int size,int i,int n STB__PARAMS)3388 void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS)
3389 {
3390 void *p = *pp;
3391 if (n) {
3392 int z;
3393
3394 if (p == NULL) {
3395 stb__arr_addlen_(pp, size, n STB__ARGS);
3396 return;
3397 }
3398
3399 z = stb_arr_len2(p);
3400 stb__arr_addlen_(&p, size, n STB__ARGS);
3401 memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i));
3402 }
3403 *pp = p;
3404 }
3405
stb__arr_deleten_(void ** pp,int size,int i,int n STB__PARAMS)3406 void stb__arr_deleten_(void **pp, int size, int i, int n STB__PARAMS)
3407 {
3408 void *p = *pp;
3409 if (n) {
3410 memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n)));
3411 stb_arrhead2(p)->len -= n;
3412 }
3413 *pp = p;
3414 }
3415
3416 #endif
3417
3418 //////////////////////////////////////////////////////////////////////////////
3419 //
3420 // Hashing
3421 //
3422 // typical use for this is to make a power-of-two hash table.
3423 //
3424 // let N = size of table (2^n)
3425 // let H = stb_hash(str)
3426 // let S = stb_rehash(H) | 1
3427 //
3428 // then hash probe sequence P(i) for i=0..N-1
3429 // P(i) = (H + S*i) & (N-1)
3430 //
3431 // the idea is that H has 32 bits of hash information, but the
3432 // table has only, say, 2^20 entries so only uses 20 of the bits.
3433 // then by rehashing the original H we get 2^12 different probe
3434 // sequences for a given initial probe location. (So it's optimal
3435 // for 64K tables and its optimality decreases past that.)
3436 //
3437 // ok, so I've added something that generates _two separate_
3438 // 32-bit hashes simultaneously which should scale better to
3439 // very large tables.
3440
3441
3442 STB_EXTERN unsigned int stb_hash(char *str);
3443 STB_EXTERN unsigned int stb_hashptr(void *p);
3444 STB_EXTERN unsigned int stb_hashlen(char *str, int len);
3445 STB_EXTERN unsigned int stb_rehash_improved(unsigned int v);
3446 STB_EXTERN unsigned int stb_hash_fast(void *p, int len);
3447 STB_EXTERN unsigned int stb_hash2(char *str, unsigned int *hash2_ptr);
3448 STB_EXTERN unsigned int stb_hash_number(unsigned int hash);
3449
3450 #define stb_rehash(x) ((x) + ((x) >> 6) + ((x) >> 19))
3451
3452 #ifdef STB_DEFINE
stb_hash(char * str)3453 unsigned int stb_hash(char *str)
3454 {
3455 unsigned int hash = 0;
3456 while (*str)
3457 hash = (hash << 7) + (hash >> 25) + *str++;
3458 return hash + (hash >> 16);
3459 }
3460
stb_hashlen(char * str,int len)3461 unsigned int stb_hashlen(char *str, int len)
3462 {
3463 unsigned int hash = 0;
3464 while (len-- > 0 && *str)
3465 hash = (hash << 7) + (hash >> 25) + *str++;
3466 return hash + (hash >> 16);
3467 }
3468
stb_hashptr(void * p)3469 unsigned int stb_hashptr(void *p)
3470 {
3471 unsigned int x = (unsigned int)(size_t) p;
3472
3473 // typically lacking in low bits and high bits
3474 x = stb_rehash(x);
3475 x += x << 16;
3476
3477 // pearson's shuffle
3478 x ^= x << 3;
3479 x += x >> 5;
3480 x ^= x << 2;
3481 x += x >> 15;
3482 x ^= x << 10;
3483 return stb_rehash(x);
3484 }
3485
stb_rehash_improved(unsigned int v)3486 unsigned int stb_rehash_improved(unsigned int v)
3487 {
3488 return stb_hashptr((void *)(size_t) v);
3489 }
3490
stb_hash2(char * str,unsigned int * hash2_ptr)3491 unsigned int stb_hash2(char *str, unsigned int *hash2_ptr)
3492 {
3493 unsigned int hash1 = 0x3141592c;
3494 unsigned int hash2 = 0x77f044ed;
3495 while (*str) {
3496 hash1 = (hash1 << 7) + (hash1 >> 25) + *str;
3497 hash2 = (hash2 << 11) + (hash2 >> 21) + *str;
3498 ++str;
3499 }
3500 *hash2_ptr = hash2 + (hash1 >> 16);
3501 return hash1 + (hash2 >> 16);
3502 }
3503
3504 // Paul Hsieh hash
3505 #define stb__get16(p) ((p)[0] | ((p)[1] << 8))
3506
stb_hash_fast(void * p,int len)3507 unsigned int stb_hash_fast(void *p, int len)
3508 {
3509 unsigned char *q = (unsigned char *) p;
3510 unsigned int hash = len;
3511
3512 if (len <= 0 || q == NULL) return 0;
3513
3514 /* Main loop */
3515 for (;len > 3; len -= 4) {
3516 unsigned int val;
3517 hash += stb__get16(q);
3518 val = (stb__get16(q+2) << 11);
3519 hash = (hash << 16) ^ hash ^ val;
3520 q += 4;
3521 hash += hash >> 11;
3522 }
3523
3524 /* Handle end cases */
3525 switch (len) {
3526 case 3: hash += stb__get16(q);
3527 hash ^= hash << 16;
3528 hash ^= q[2] << 18;
3529 hash += hash >> 11;
3530 break;
3531 case 2: hash += stb__get16(q);
3532 hash ^= hash << 11;
3533 hash += hash >> 17;
3534 break;
3535 case 1: hash += q[0];
3536 hash ^= hash << 10;
3537 hash += hash >> 1;
3538 break;
3539 case 0: break;
3540 }
3541
3542 /* Force "avalanching" of final 127 bits */
3543 hash ^= hash << 3;
3544 hash += hash >> 5;
3545 hash ^= hash << 4;
3546 hash += hash >> 17;
3547 hash ^= hash << 25;
3548 hash += hash >> 6;
3549
3550 return hash;
3551 }
3552
stb_hash_number(unsigned int hash)3553 unsigned int stb_hash_number(unsigned int hash)
3554 {
3555 hash ^= hash << 3;
3556 hash += hash >> 5;
3557 hash ^= hash << 4;
3558 hash += hash >> 17;
3559 hash ^= hash << 25;
3560 hash += hash >> 6;
3561 return hash;
3562 }
3563
3564 #endif
3565
3566 #ifdef STB_PERFECT_HASH
3567 //////////////////////////////////////////////////////////////////////////////
3568 //
3569 // Perfect hashing for ints/pointers
3570 //
3571 // This is mainly useful for making faster pointer-indexed tables
3572 // that don't change frequently. E.g. for stb_ischar().
3573 //
3574
3575 typedef struct
3576 {
3577 stb_uint32 addend;
3578 stb_uint multiplicand;
3579 stb_uint b_mask;
3580 stb_uint8 small_bmap[16];
3581 stb_uint16 *large_bmap;
3582
3583 stb_uint table_mask;
3584 stb_uint32 *table;
3585 } stb_perfect;
3586
3587 STB_EXTERN int stb_perfect_create(stb_perfect *,unsigned int*,int n);
3588 STB_EXTERN void stb_perfect_destroy(stb_perfect *);
3589 STB_EXTERN int stb_perfect_hash(stb_perfect *, unsigned int x);
3590 extern int stb_perfect_hash_max_failures;
3591
3592 #ifdef STB_DEFINE
3593
3594 int stb_perfect_hash_max_failures;
3595
stb_perfect_hash(stb_perfect * p,unsigned int x)3596 int stb_perfect_hash(stb_perfect *p, unsigned int x)
3597 {
3598 stb_uint m = x * p->multiplicand;
3599 stb_uint y = x >> 16;
3600 stb_uint bv = (m >> 24) + y;
3601 stb_uint av = (m + y) >> 12;
3602 if (p->table == NULL) return -1; // uninitialized table fails
3603 bv &= p->b_mask;
3604 av &= p->table_mask;
3605 if (p->large_bmap)
3606 av ^= p->large_bmap[bv];
3607 else
3608 av ^= p->small_bmap[bv];
3609 return p->table[av] == x ? av : -1;
3610 }
3611
stb__perfect_prehash(stb_perfect * p,stb_uint x,stb_uint16 * a,stb_uint16 * b)3612 static void stb__perfect_prehash(stb_perfect *p, stb_uint x, stb_uint16 *a, stb_uint16 *b)
3613 {
3614 stb_uint m = x * p->multiplicand;
3615 stb_uint y = x >> 16;
3616 stb_uint bv = (m >> 24) + y;
3617 stb_uint av = (m + y) >> 12;
3618 bv &= p->b_mask;
3619 av &= p->table_mask;
3620 *b = bv;
3621 *a = av;
3622 }
3623
stb__perfect_rand(void)3624 static unsigned long stb__perfect_rand(void)
3625 {
3626 static unsigned long stb__rand;
3627 stb__rand = stb__rand * 2147001325 + 715136305;
3628 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16));
3629 }
3630
3631 typedef struct {
3632 unsigned short count;
3633 unsigned short b;
3634 unsigned short map;
3635 unsigned short *entries;
3636 } stb__slot;
3637
stb__slot_compare(const void * p,const void * q)3638 static int stb__slot_compare(const void *p, const void *q)
3639 {
3640 stb__slot *a = (stb__slot *) p;
3641 stb__slot *b = (stb__slot *) q;
3642 return a->count > b->count ? -1 : a->count < b->count; // sort large to small
3643 }
3644
stb_perfect_create(stb_perfect * p,unsigned int * v,int n)3645 int stb_perfect_create(stb_perfect *p, unsigned int *v, int n)
3646 {
3647 unsigned int buffer1[64], buffer2[64], buffer3[64], buffer4[64], buffer5[32];
3648 unsigned short *as = (unsigned short *) stb_temp(buffer1, sizeof(*v)*n);
3649 unsigned short *bs = (unsigned short *) stb_temp(buffer2, sizeof(*v)*n);
3650 unsigned short *entries = (unsigned short *) stb_temp(buffer4, sizeof(*entries) * n);
3651 int size = 1 << stb_log2_ceil(n), bsize=8;
3652 int failure = 0,i,j,k;
3653
3654 assert(n <= 32768);
3655 p->large_bmap = NULL;
3656
3657 for(;;) {
3658 stb__slot *bcount = (stb__slot *) stb_temp(buffer3, sizeof(*bcount) * bsize);
3659 unsigned short *bloc = (unsigned short *) stb_temp(buffer5, sizeof(*bloc) * bsize);
3660 unsigned short *e;
3661 int bad=0;
3662
3663 p->addend = stb__perfect_rand();
3664 p->multiplicand = stb__perfect_rand() | 1;
3665 p->table_mask = size-1;
3666 p->b_mask = bsize-1;
3667 p->table = (stb_uint32 *) malloc(size * sizeof(*p->table));
3668
3669 for (i=0; i < bsize; ++i) {
3670 bcount[i].b = i;
3671 bcount[i].count = 0;
3672 bcount[i].map = 0;
3673 }
3674 for (i=0; i < n; ++i) {
3675 stb__perfect_prehash(p, v[i], as+i, bs+i);
3676 ++bcount[bs[i]].count;
3677 }
3678 qsort(bcount, bsize, sizeof(*bcount), stb__slot_compare);
3679 e = entries; // now setup up their entries index
3680 for (i=0; i < bsize; ++i) {
3681 bcount[i].entries = e;
3682 e += bcount[i].count;
3683 bcount[i].count = 0;
3684 bloc[bcount[i].b] = i;
3685 }
3686 // now fill them out
3687 for (i=0; i < n; ++i) {
3688 int b = bs[i];
3689 int w = bloc[b];
3690 bcount[w].entries[bcount[w].count++] = i;
3691 }
3692 stb_tempfree(buffer5,bloc);
3693 // verify
3694 for (i=0; i < bsize; ++i)
3695 for (j=0; j < bcount[i].count; ++j)
3696 assert(bs[bcount[i].entries[j]] == bcount[i].b);
3697 memset(p->table, 0, size*sizeof(*p->table));
3698
3699 // check if any b has duplicate a
3700 for (i=0; i < bsize; ++i) {
3701 if (bcount[i].count > 1) {
3702 for (j=0; j < bcount[i].count; ++j) {
3703 if (p->table[as[bcount[i].entries[j]]])
3704 bad = 1;
3705 p->table[as[bcount[i].entries[j]]] = 1;
3706 }
3707 for (j=0; j < bcount[i].count; ++j) {
3708 p->table[as[bcount[i].entries[j]]] = 0;
3709 }
3710 if (bad) break;
3711 }
3712 }
3713
3714 if (!bad) {
3715 // go through the bs and populate the table, first fit
3716 for (i=0; i < bsize; ++i) {
3717 if (bcount[i].count) {
3718 // go through the candidate table[b] values
3719 for (j=0; j < size; ++j) {
3720 // go through the a values and see if they fit
3721 for (k=0; k < bcount[i].count; ++k) {
3722 int a = as[bcount[i].entries[k]];
3723 if (p->table[(a^j)&p->table_mask]) {
3724 break; // fails
3725 }
3726 }
3727 // if succeeded, accept
3728 if (k == bcount[i].count) {
3729 bcount[i].map = j;
3730 for (k=0; k < bcount[i].count; ++k) {
3731 int a = as[bcount[i].entries[k]];
3732 p->table[(a^j)&p->table_mask] = 1;
3733 }
3734 break;
3735 }
3736 }
3737 if (j == size)
3738 break; // no match for i'th entry, so break out in failure
3739 }
3740 }
3741 if (i == bsize) {
3742 // success... fill out map
3743 if (bsize <= 16 && size <= 256) {
3744 p->large_bmap = NULL;
3745 for (i=0; i < bsize; ++i)
3746 p->small_bmap[bcount[i].b] = (stb_uint8) bcount[i].map;
3747 } else {
3748 p->large_bmap = (unsigned short *) malloc(sizeof(*p->large_bmap) * bsize);
3749 for (i=0; i < bsize; ++i)
3750 p->large_bmap[bcount[i].b] = bcount[i].map;
3751 }
3752
3753 // initialize table to v[0], so empty slots will fail
3754 for (i=0; i < size; ++i)
3755 p->table[i] = v[0];
3756
3757 for (i=0; i < n; ++i)
3758 if (p->large_bmap)
3759 p->table[as[i] ^ p->large_bmap[bs[i]]] = v[i];
3760 else
3761 p->table[as[i] ^ p->small_bmap[bs[i]]] = v[i];
3762
3763 // and now validate that none of them collided
3764 for (i=0; i < n; ++i)
3765 assert(stb_perfect_hash(p, v[i]) >= 0);
3766
3767 stb_tempfree(buffer3, bcount);
3768 break;
3769 }
3770 }
3771 free(p->table);
3772 p->table = NULL;
3773 stb_tempfree(buffer3, bcount);
3774
3775 ++failure;
3776 if (failure >= 4 && bsize < size) bsize *= 2;
3777 if (failure >= 8 && (failure & 3) == 0 && size < 4*n) {
3778 size *= 2;
3779 bsize *= 2;
3780 }
3781 if (failure == 6) {
3782 // make sure the input data is unique, so we don't infinite loop
3783 unsigned int *data = (unsigned int *) stb_temp(buffer3, n * sizeof(*data));
3784 memcpy(data, v, sizeof(*data) * n);
3785 qsort(data, n, sizeof(*data), stb_intcmp(0));
3786 for (i=1; i < n; ++i) {
3787 if (data[i] == data[i-1])
3788 size = 0; // size is return value, so 0 it
3789 }
3790 stb_tempfree(buffer3, data);
3791 if (!size) break;
3792 }
3793 }
3794
3795 if (failure > stb_perfect_hash_max_failures)
3796 stb_perfect_hash_max_failures = failure;
3797
3798 stb_tempfree(buffer1, as);
3799 stb_tempfree(buffer2, bs);
3800 stb_tempfree(buffer4, entries);
3801
3802 return size;
3803 }
3804
stb_perfect_destroy(stb_perfect * p)3805 void stb_perfect_destroy(stb_perfect *p)
3806 {
3807 if (p->large_bmap) free(p->large_bmap);
3808 if (p->table ) free(p->table);
3809 p->large_bmap = NULL;
3810 p->table = NULL;
3811 p->b_mask = 0;
3812 p->table_mask = 0;
3813 }
3814 #endif
3815
3816 //////////////////////////////////////////////////////////////////////////////
3817 //
3818 // Perfect hash clients
3819
3820 STB_EXTERN int stb_ischar(char s, char *set);
3821
3822 #ifdef STB_DEFINE
3823
stb_ischar(char c,char * set)3824 int stb_ischar(char c, char *set)
3825 {
3826 static unsigned char bit[8] = { 1,2,4,8,16,32,64,128 };
3827 static stb_perfect p;
3828 static unsigned char (*tables)[256];
3829 static char ** sets = NULL;
3830
3831 int z = stb_perfect_hash(&p, (int)(size_t) set);
3832 if (z < 0) {
3833 int i,k,n,j,f;
3834 // special code that means free all existing data
3835 if (set == NULL) {
3836 stb_arr_free(sets);
3837 free(tables);
3838 tables = NULL;
3839 stb_perfect_destroy(&p);
3840 return 0;
3841 }
3842 stb_arr_push(sets, set);
3843 stb_perfect_destroy(&p);
3844 n = stb_perfect_create(&p, (unsigned int *) (char **) sets, stb_arr_len(sets));
3845 assert(n != 0);
3846 k = (n+7) >> 3;
3847 tables = (unsigned char (*)[256]) realloc(tables, sizeof(*tables) * k);
3848 memset(tables, 0, sizeof(*tables) * k);
3849 for (i=0; i < stb_arr_len(sets); ++i) {
3850 k = stb_perfect_hash(&p, (int)(size_t) sets[i]);
3851 assert(k >= 0);
3852 n = k >> 3;
3853 f = bit[k&7];
3854 for (j=0; !j || sets[i][j]; ++j) {
3855 tables[n][(unsigned char) sets[i][j]] |= f;
3856 }
3857 }
3858 z = stb_perfect_hash(&p, (int)(size_t) set);
3859 }
3860 return tables[z >> 3][(unsigned char) c] & bit[z & 7];
3861 }
3862
3863 #endif
3864 #endif
3865
3866 //////////////////////////////////////////////////////////////////////////////
3867 //
3868 // Instantiated data structures
3869 //
3870 // This is an attempt to implement a templated data structure.
3871 //
3872 // Hash table: call stb_define_hash(TYPE,N,KEY,K1,K2,HASH,VALUE)
3873 // TYPE -- will define a structure type containing the hash table
3874 // N -- the name, will prefix functions named:
3875 // N create
3876 // N destroy
3877 // N get
3878 // N set, N add, N update,
3879 // N remove
3880 // KEY -- the type of the key. 'x == y' must be valid
3881 // K1,K2 -- keys never used by the app, used as flags in the hashtable
3882 // HASH -- a piece of code ending with 'return' that hashes key 'k'
3883 // VALUE -- the type of the value. 'x = y' must be valid
3884 //
3885 // Note that stb_define_hash_base can be used to define more sophisticated
3886 // hash tables, e.g. those that make copies of the key or use special
3887 // comparisons (e.g. strcmp).
3888
3889 #define STB_(prefix,name) stb__##prefix##name
3890 #define STB__(prefix,name) prefix##name
3891 #define STB__use(x) x
3892 #define STB__skip(x)
3893
3894 #define stb_declare_hash(PREFIX,TYPE,N,KEY,VALUE) \
3895 typedef struct stb__st_##TYPE TYPE;\
3896 PREFIX int STB__(N, init)(TYPE *h, int count);\
3897 PREFIX int STB__(N, memory_usage)(TYPE *h);\
3898 PREFIX TYPE * STB__(N, create)(void);\
3899 PREFIX TYPE * STB__(N, copy)(TYPE *h);\
3900 PREFIX void STB__(N, destroy)(TYPE *h);\
3901 PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v);\
3902 PREFIX VALUE STB__(N,get)(TYPE *a, KEY k);\
3903 PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v);\
3904 PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v);\
3905 PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v);\
3906 PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v);
3907
3908 #define STB_nocopy(x) (x)
3909 #define STB_nodelete(x) 0
3910 #define STB_nofields
3911 #define STB_nonullvalue(x)
3912 #define STB_nullvalue(x) x
3913 #define STB_safecompare(x) x
3914 #define STB_nosafe(x)
3915 #define STB_noprefix
3916
3917 #ifdef __GNUC__
3918 #define STB__nogcc(x)
3919 #else
3920 #define STB__nogcc(x) x
3921 #endif
3922
3923 #define stb_define_hash_base(PREFIX,TYPE,FIELDS,N,NC,LOAD_FACTOR, \
3924 KEY,EMPTY,DEL,COPY,DISPOSE,SAFE, \
3925 VCOMPARE,CCOMPARE,HASH, \
3926 VALUE,HASVNULL,VNULL) \
3927 \
3928 typedef struct \
3929 { \
3930 KEY k; \
3931 VALUE v; \
3932 } STB_(N,_hashpair); \
3933 \
3934 STB__nogcc( typedef struct stb__st_##TYPE TYPE; ) \
3935 struct stb__st_##TYPE { \
3936 FIELDS \
3937 STB_(N,_hashpair) *table; \
3938 unsigned int mask; \
3939 int count, limit; \
3940 int deleted; \
3941 \
3942 int delete_threshhold; \
3943 int grow_threshhold; \
3944 int shrink_threshhold; \
3945 unsigned char alloced, has_empty, has_del; \
3946 VALUE ev; VALUE dv; \
3947 }; \
3948 \
3949 static unsigned int STB_(N, hash)(KEY k) \
3950 { \
3951 HASH \
3952 } \
3953 \
3954 PREFIX int STB__(N, init)(TYPE *h, int count) \
3955 { \
3956 int i; \
3957 if (count < 4) count = 4; \
3958 h->limit = count; \
3959 h->count = 0; \
3960 h->mask = count-1; \
3961 h->deleted = 0; \
3962 h->grow_threshhold = (int) (count * LOAD_FACTOR); \
3963 h->has_empty = h->has_del = 0; \
3964 h->alloced = 0; \
3965 if (count <= 64) \
3966 h->shrink_threshhold = 0; \
3967 else \
3968 h->shrink_threshhold = (int) (count * (LOAD_FACTOR/2.25)); \
3969 h->delete_threshhold = (int) (count * (1-LOAD_FACTOR)/2); \
3970 h->table = (STB_(N,_hashpair)*) malloc(sizeof(h->table[0]) * count); \
3971 if (h->table == NULL) return 0; \
3972 /* ideally this gets turned into a memset32 automatically */ \
3973 for (i=0; i < count; ++i) \
3974 h->table[i].k = EMPTY; \
3975 return 1; \
3976 } \
3977 \
3978 PREFIX int STB__(N, memory_usage)(TYPE *h) \
3979 { \
3980 return sizeof(*h) + h->limit * sizeof(h->table[0]); \
3981 } \
3982 \
3983 PREFIX TYPE * STB__(N, create)(void) \
3984 { \
3985 TYPE *h = (TYPE *) malloc(sizeof(*h)); \
3986 if (h) { \
3987 if (STB__(N, init)(h, 16)) \
3988 h->alloced = 1; \
3989 else { free(h); h=NULL; } \
3990 } \
3991 return h; \
3992 } \
3993 \
3994 PREFIX void STB__(N, destroy)(TYPE *a) \
3995 { \
3996 int i; \
3997 for (i=0; i < a->limit; ++i) \
3998 if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k, DEL)) \
3999 DISPOSE(a->table[i].k); \
4000 free(a->table); \
4001 if (a->alloced) \
4002 free(a); \
4003 } \
4004 \
4005 static void STB_(N, rehash)(TYPE *a, int count); \
4006 \
4007 PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v) \
4008 { \
4009 unsigned int h = STB_(N, hash)(k); \
4010 unsigned int n = h & a->mask, s; \
4011 if (CCOMPARE(k,EMPTY)){ if (a->has_empty) *v = a->ev; return a->has_empty;}\
4012 if (CCOMPARE(k,DEL)) { if (a->has_del ) *v = a->dv; return a->has_del; }\
4013 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4014 SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
4015 if (VCOMPARE(a->table[n].k,k)) { *v = a->table[n].v; return 1; } \
4016 s = stb_rehash(h) | 1; \
4017 for(;;) { \
4018 n = (n + s) & a->mask; \
4019 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4020 SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
4021 if (VCOMPARE(a->table[n].k,k)) \
4022 { *v = a->table[n].v; return 1; } \
4023 } \
4024 } \
4025 \
4026 HASVNULL( \
4027 PREFIX VALUE STB__(N,get)(TYPE *a, KEY k) \
4028 { \
4029 VALUE v; \
4030 if (STB__(N,get_flag)(a,k,&v)) return v; \
4031 else return VNULL; \
4032 } \
4033 ) \
4034 \
4035 PREFIX int STB__(N,getkey)(TYPE *a, KEY k, KEY *kout) \
4036 { \
4037 unsigned int h = STB_(N, hash)(k); \
4038 unsigned int n = h & a->mask, s; \
4039 if (CCOMPARE(k,EMPTY)||CCOMPARE(k,DEL)) return 0; \
4040 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4041 SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
4042 if (VCOMPARE(a->table[n].k,k)) { *kout = a->table[n].k; return 1; } \
4043 s = stb_rehash(h) | 1; \
4044 for(;;) { \
4045 n = (n + s) & a->mask; \
4046 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4047 SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
4048 if (VCOMPARE(a->table[n].k,k)) \
4049 { *kout = a->table[n].k; return 1; } \
4050 } \
4051 } \
4052 \
4053 static int STB_(N,addset)(TYPE *a, KEY k, VALUE v, \
4054 int allow_new, int allow_old, int copy) \
4055 { \
4056 unsigned int h = STB_(N, hash)(k); \
4057 unsigned int n = h & a->mask; \
4058 int b = -1; \
4059 if (CCOMPARE(k,EMPTY)) { \
4060 if (a->has_empty ? allow_old : allow_new) { \
4061 n=a->has_empty; a->ev = v; a->has_empty = 1; return !n; \
4062 } else return 0; \
4063 } \
4064 if (CCOMPARE(k,DEL)) { \
4065 if (a->has_del ? allow_old : allow_new) { \
4066 n=a->has_del; a->dv = v; a->has_del = 1; return !n; \
4067 } else return 0; \
4068 } \
4069 if (!CCOMPARE(a->table[n].k, EMPTY)) { \
4070 unsigned int s; \
4071 if (CCOMPARE(a->table[n].k, DEL)) \
4072 b = n; \
4073 else if (VCOMPARE(a->table[n].k,k)) { \
4074 if (allow_old) \
4075 a->table[n].v = v; \
4076 return !allow_new; \
4077 } \
4078 s = stb_rehash(h) | 1; \
4079 for(;;) { \
4080 n = (n + s) & a->mask; \
4081 if (CCOMPARE(a->table[n].k, EMPTY)) break; \
4082 if (CCOMPARE(a->table[n].k, DEL)) { \
4083 if (b < 0) b = n; \
4084 } else if (VCOMPARE(a->table[n].k,k)) { \
4085 if (allow_old) \
4086 a->table[n].v = v; \
4087 return !allow_new; \
4088 } \
4089 } \
4090 } \
4091 if (!allow_new) return 0; \
4092 if (b < 0) b = n; else --a->deleted; \
4093 a->table[b].k = copy ? COPY(k) : k; \
4094 a->table[b].v = v; \
4095 ++a->count; \
4096 if (a->count > a->grow_threshhold) \
4097 STB_(N,rehash)(a, a->limit*2); \
4098 return 1; \
4099 } \
4100 \
4101 PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,1,1);}\
4102 PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,0,1);}\
4103 PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v){return STB_(N,addset)(a,k,v,0,1,1);}\
4104 \
4105 PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v) \
4106 { \
4107 unsigned int h = STB_(N, hash)(k); \
4108 unsigned int n = h & a->mask, s; \
4109 if (CCOMPARE(k,EMPTY)) { if (a->has_empty) { if(v)*v = a->ev; a->has_empty=0; return 1; } return 0; } \
4110 if (CCOMPARE(k,DEL)) { if (a->has_del ) { if(v)*v = a->dv; a->has_del =0; return 1; } return 0; } \
4111 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4112 if (SAFE(CCOMPARE(a->table[n].k,DEL) || ) !VCOMPARE(a->table[n].k,k)) { \
4113 s = stb_rehash(h) | 1; \
4114 for(;;) { \
4115 n = (n + s) & a->mask; \
4116 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4117 SAFE(if (CCOMPARE(a->table[n].k, DEL)) continue;) \
4118 if (VCOMPARE(a->table[n].k,k)) break; \
4119 } \
4120 } \
4121 DISPOSE(a->table[n].k); \
4122 a->table[n].k = DEL; \
4123 --a->count; \
4124 ++a->deleted; \
4125 if (v != NULL) \
4126 *v = a->table[n].v; \
4127 if (a->count < a->shrink_threshhold) \
4128 STB_(N, rehash)(a, a->limit >> 1); \
4129 else if (a->deleted > a->delete_threshhold) \
4130 STB_(N, rehash)(a, a->limit); \
4131 return 1; \
4132 } \
4133 \
4134 PREFIX TYPE * STB__(NC, copy)(TYPE *a) \
4135 { \
4136 int i; \
4137 TYPE *h = (TYPE *) malloc(sizeof(*h)); \
4138 if (!h) return NULL; \
4139 if (!STB__(N, init)(h, a->limit)) { free(h); return NULL; } \
4140 h->count = a->count; \
4141 h->deleted = a->deleted; \
4142 h->alloced = 1; \
4143 h->ev = a->ev; h->dv = a->dv; \
4144 h->has_empty = a->has_empty; h->has_del = a->has_del; \
4145 memcpy(h->table, a->table, h->limit * sizeof(h->table[0])); \
4146 for (i=0; i < a->limit; ++i) \
4147 if (!CCOMPARE(h->table[i].k,EMPTY) && !CCOMPARE(h->table[i].k,DEL)) \
4148 h->table[i].k = COPY(h->table[i].k); \
4149 return h; \
4150 } \
4151 \
4152 static void STB_(N, rehash)(TYPE *a, int count) \
4153 { \
4154 int i; \
4155 TYPE b; \
4156 STB__(N, init)(&b, count); \
4157 for (i=0; i < a->limit; ++i) \
4158 if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k,DEL)) \
4159 STB_(N,addset)(&b, a->table[i].k, a->table[i].v,1,1,0); \
4160 free(a->table); \
4161 a->table = b.table; \
4162 a->mask = b.mask; \
4163 a->count = b.count; \
4164 a->limit = b.limit; \
4165 a->deleted = b.deleted; \
4166 a->delete_threshhold = b.delete_threshhold; \
4167 a->grow_threshhold = b.grow_threshhold; \
4168 a->shrink_threshhold = b.shrink_threshhold; \
4169 }
4170
4171 #define STB_equal(a,b) ((a) == (b))
4172
4173 #define stb_define_hash(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE) \
4174 stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
4175 KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
4176 STB_equal,STB_equal,HASH, \
4177 VALUE,STB_nonullvalue,0)
4178
4179 #define stb_define_hash_vnull(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE,VNULL) \
4180 stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
4181 KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
4182 STB_equal,STB_equal,HASH, \
4183 VALUE,STB_nullvalue,VNULL)
4184
4185 //////////////////////////////////////////////////////////////////////////////
4186 //
4187 // stb_ptrmap
4188 //
4189 // An stb_ptrmap data structure is an O(1) hash table between pointers. One
4190 // application is to let you store "extra" data associated with pointers,
4191 // which is why it was originally called stb_extra.
4192
4193 stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *)
4194 stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32)
4195 stb_declare_hash(STB_EXTERN, stb_uidict, stbi_uidict_, stb_uint32, stb_uint32)
4196
4197 STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *));
4198 STB_EXTERN stb_ptrmap *stb_ptrmap_new(void);
4199
4200 STB_EXTERN stb_idict * stb_idict_new_size(int size);
4201 STB_EXTERN void stb_idict_remove_all(stb_idict *e);
4202 STB_EXTERN void stb_uidict_reset(stb_uidict *e);
4203
4204 #ifdef STB_DEFINE
4205
4206 #define STB_EMPTY ((void *) 2)
4207 #define STB_EDEL ((void *) 6)
4208
4209 stb_define_hash_base(STB_noprefix,stb_ptrmap, STB_nofields, stb_ptrmap_,stb_ptrmap_,0.85f,
4210 void *,STB_EMPTY,STB_EDEL,STB_nocopy,STB_nodelete,STB_nosafe,
4211 STB_equal,STB_equal,return stb_hashptr(k);,
4212 void *,STB_nullvalue,NULL)
4213
stb_ptrmap_new(void)4214 stb_ptrmap *stb_ptrmap_new(void)
4215 {
4216 return stb_ptrmap_create();
4217 }
4218
stb_ptrmap_delete(stb_ptrmap * e,void (* free_func)(void *))4219 void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *))
4220 {
4221 int i;
4222 if (free_func)
4223 for (i=0; i < e->limit; ++i)
4224 if (e->table[i].k != STB_EMPTY && e->table[i].k != STB_EDEL) {
4225 if (free_func == free)
4226 free(e->table[i].v); // allow STB_MALLOC_WRAPPER to operate
4227 else
4228 free_func(e->table[i].v);
4229 }
4230 stb_ptrmap_destroy(e);
4231 }
4232
4233 // extra fields needed for stua_dict
4234 #define STB_IEMPTY ((int) 1)
4235 #define STB_IDEL ((int) 3)
4236 stb_define_hash_base(STB_noprefix, stb_idict, short type; short gc; STB_nofields, stb_idict_,stb_idict_,0.95f,
4237 stb_int32,STB_IEMPTY,STB_IDEL,STB_nocopy,STB_nodelete,STB_nosafe,
4238 STB_equal,STB_equal,
4239 return stb_rehash_improved(k);,stb_int32,STB_nonullvalue,0)
4240
stb_idict_new_size(int size)4241 stb_idict * stb_idict_new_size(int size)
4242 {
4243 stb_idict *e = (stb_idict *) malloc(sizeof(*e));
4244 if (e) {
4245 if (!stb_is_pow2(size))
4246 size = 1 << stb_log2_ceil(size);
4247 stb_idict_init(e, size);
4248 e->alloced = 1;
4249 }
4250 return e;
4251 }
4252
stb_idict_remove_all(stb_idict * e)4253 void stb_idict_remove_all(stb_idict *e)
4254 {
4255 int n;
4256 for (n=0; n < e->limit; ++n)
4257 e->table[n].k = STB_IEMPTY;
4258 e->has_empty = e->has_del = 0;
4259 e->count = 0;
4260 e->deleted = 0;
4261 }
4262
4263 stb_define_hash_base(STB_noprefix, stb_uidict, STB_nofields, stb_uidict_,stb_uidict_,0.85f,
4264 stb_int32,0xffffffff,0xfffffffe,STB_nocopy,STB_nodelete,STB_nosafe,
4265 STB_equal,STB_equal,
4266 return stb_rehash_improved(k);,stb_uint32,STB_nonullvalue,0)
4267
stb_uidict_reset(stb_uidict * e)4268 void stb_uidict_reset(stb_uidict *e)
4269 {
4270 int n;
4271 for (n=0; n < e->limit; ++n)
4272 e->table[n].k = 0xffffffff;
4273 e->has_empty = e->has_del = 0;
4274 e->count = 0;
4275 e->deleted = 0;
4276 }
4277 #endif
4278
4279 //////////////////////////////////////////////////////////////////////////////
4280 //
4281 // stb_sparse_ptr_matrix
4282 //
4283 // An stb_ptrmap data structure is an O(1) hash table storing an arbitrary
4284 // block of data for a given pair of pointers.
4285 //
4286 // If create=0, returns
4287
4288 typedef struct stb__st_stb_spmatrix stb_spmatrix;
4289
4290 STB_EXTERN stb_spmatrix * stb_sparse_ptr_matrix_new(int val_size);
4291 STB_EXTERN void stb_sparse_ptr_matrix_free(stb_spmatrix *z);
4292 STB_EXTERN void * stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create);
4293
4294 #ifdef STB_DEFINE
4295 typedef struct
4296 {
4297 void *a;
4298 void *b;
4299 } stb__ptrpair;
4300
4301 static stb__ptrpair stb__ptrpair_empty = { (void *) 1, (void *) 1 };
4302 static stb__ptrpair stb__ptrpair_del = { (void *) 2, (void *) 2 };
4303
4304 #define STB__equal_ptrpair(x,y) ((x).a == (y).a && (x).b == (y).b)
4305
4306 stb_define_hash_base(STB_noprefix, stb_spmatrix, int val_size; void *arena;, stb__spmatrix_,stb__spmatrix_, 0.85,
4307 stb__ptrpair, stb__ptrpair_empty, stb__ptrpair_del,
4308 STB_nocopy, STB_nodelete, STB_nosafe,
4309 STB__equal_ptrpair, STB__equal_ptrpair, return stb_rehash(stb_hashptr(k.a))+stb_hashptr(k.b);,
4310 void *, STB_nullvalue, 0)
4311
stb_sparse_ptr_matrix_new(int val_size)4312 stb_spmatrix *stb_sparse_ptr_matrix_new(int val_size)
4313 {
4314 stb_spmatrix *m = stb__spmatrix_create();
4315 if (m) m->val_size = val_size;
4316 if (m) m->arena = stb_malloc_global(1);
4317 return m;
4318 }
4319
stb_sparse_ptr_matrix_free(stb_spmatrix * z)4320 void stb_sparse_ptr_matrix_free(stb_spmatrix *z)
4321 {
4322 if (z->arena) stb_free(z->arena);
4323 stb__spmatrix_destroy(z);
4324 }
4325
stb_sparse_ptr_matrix_get(stb_spmatrix * z,void * a,void * b,int create)4326 void *stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create)
4327 {
4328 stb__ptrpair t = { a,b };
4329 void *data = stb__spmatrix_get(z, t);
4330 if (!data && create) {
4331 data = stb_malloc_raw(z->arena, z->val_size);
4332 if (!data) return NULL;
4333 memset(data, 0, z->val_size);
4334 stb__spmatrix_add(z, t, data);
4335 }
4336 return data;
4337 }
4338 #endif
4339
4340
4341
4342 //////////////////////////////////////////////////////////////////////////////
4343 //
4344 // SDICT: Hash Table for Strings (symbol table)
4345 //
4346 // if "use_arena=1", then strings will be copied
4347 // into blocks and never freed until the sdict is freed;
4348 // otherwise they're malloc()ed and free()d on the fly.
4349 // (specify use_arena=1 if you never stb_sdict_remove)
4350
4351 stb_declare_hash(STB_EXTERN, stb_sdict, stb_sdict_, char *, void *)
4352
4353 STB_EXTERN stb_sdict * stb_sdict_new(int use_arena);
4354 STB_EXTERN stb_sdict * stb_sdict_copy(stb_sdict*);
4355 STB_EXTERN void stb_sdict_delete(stb_sdict *);
4356 STB_EXTERN void * stb_sdict_change(stb_sdict *, char *str, void *p);
4357 STB_EXTERN int stb_sdict_count(stb_sdict *d);
4358
4359 STB_EXTERN int stb_sdict_internal_limit(stb_sdict *d);
4360 STB_EXTERN char * stb_sdict_internal_key(stb_sdict *d, int n);
4361 STB_EXTERN void * stb_sdict_internal_value(stb_sdict *d, int n);
4362
4363 #define stb_sdict_for(d,i,q,z) \
4364 for(i=0; i < stb_sdict_internal_limit(d) ? (q=stb_sdict_internal_key(d,i),z=stb_sdict_internal_value(d,i),1) : 0; ++i) \
4365 if (q==NULL||q==(void *) 1);else // reversed makes macro friendly
4366
4367 #ifdef STB_DEFINE
4368
4369 // if in same translation unit, for speed, don't call accessors
4370 #undef stb_sdict_for
4371 #define stb_sdict_for(d,i,q,z) \
4372 for(i=0; i < (d)->limit ? (q=(d)->table[i].k,z=(d)->table[i].v,1) : 0; ++i) \
4373 if (q==NULL||q==(void *) 1);else // reversed makes macro friendly
4374
4375 #define STB_DEL ((void *) 1)
4376 #define STB_SDEL ((char *) 1)
4377
4378 #define stb_sdict__copy(x) \
4379 stb_p_strcpy_s(a->arena ? stb_malloc_string(a->arena, strlen(x)+1) \
4380 : (char *) malloc(strlen(x)+1), strlen(x)+1, x)
4381
4382 #define stb_sdict__dispose(x) if (!a->arena) free(x)
4383
4384 stb_define_hash_base(STB_noprefix, stb_sdict, void*arena;, stb_sdict_,stb_sdictinternal_, 0.85f,
4385 char *, NULL, STB_SDEL, stb_sdict__copy, stb_sdict__dispose,
4386 STB_safecompare, !strcmp, STB_equal, return stb_hash(k);,
4387 void *, STB_nullvalue, NULL)
4388
stb_sdict_count(stb_sdict * a)4389 int stb_sdict_count(stb_sdict *a)
4390 {
4391 return a->count;
4392 }
4393
stb_sdict_internal_limit(stb_sdict * a)4394 int stb_sdict_internal_limit(stb_sdict *a)
4395 {
4396 return a->limit;
4397 }
stb_sdict_internal_key(stb_sdict * a,int n)4398 char* stb_sdict_internal_key(stb_sdict *a, int n)
4399 {
4400 return a->table[n].k;
4401 }
stb_sdict_internal_value(stb_sdict * a,int n)4402 void* stb_sdict_internal_value(stb_sdict *a, int n)
4403 {
4404 return a->table[n].v;
4405 }
4406
stb_sdict_new(int use_arena)4407 stb_sdict * stb_sdict_new(int use_arena)
4408 {
4409 stb_sdict *d = stb_sdict_create();
4410 if (d == NULL) return NULL;
4411 d->arena = use_arena ? stb_malloc_global(1) : NULL;
4412 return d;
4413 }
4414
stb_sdict_copy(stb_sdict * old)4415 stb_sdict* stb_sdict_copy(stb_sdict *old)
4416 {
4417 stb_sdict *n;
4418 void *old_arena = old->arena;
4419 void *new_arena = old_arena ? stb_malloc_global(1) : NULL;
4420 old->arena = new_arena;
4421 n = stb_sdictinternal_copy(old);
4422 old->arena = old_arena;
4423 if (n)
4424 n->arena = new_arena;
4425 else if (new_arena)
4426 stb_free(new_arena);
4427 return n;
4428 }
4429
4430
stb_sdict_delete(stb_sdict * d)4431 void stb_sdict_delete(stb_sdict *d)
4432 {
4433 if (d->arena)
4434 stb_free(d->arena);
4435 stb_sdict_destroy(d);
4436 }
4437
stb_sdict_change(stb_sdict * d,char * str,void * p)4438 void * stb_sdict_change(stb_sdict *d, char *str, void *p)
4439 {
4440 void *q = stb_sdict_get(d, str);
4441 stb_sdict_set(d, str, p);
4442 return q;
4443 }
4444 #endif
4445
4446 //////////////////////////////////////////////////////////////////////////////
4447 //
4448 // Instantiated data structures
4449 //
4450 // This is an attempt to implement a templated data structure.
4451 // What you do is define a struct foo, and then include several
4452 // pointer fields to struct foo in your struct. Then you call
4453 // the instantiator, which creates the functions that implement
4454 // the data structure. This requires massive undebuggable #defines,
4455 // so we limit the cases where we do this.
4456 //
4457 // AA tree is an encoding of a 2-3 tree whereas RB trees encode a 2-3-4 tree;
4458 // much simpler code due to fewer cases.
4459
4460 #define stb__bst_parent(x) x
4461 #define stb__bst_noparent(x)
4462
4463 #define stb_bst_fields(N) \
4464 *STB_(N,left), *STB_(N,right); \
4465 unsigned char STB_(N,level)
4466
4467 #define stb_bst_fields_parent(N) \
4468 *STB_(N,left), *STB_(N,right), *STB_(N,parent); \
4469 unsigned char STB_(N,level)
4470
4471 #define STB__level(N,x) ((x) ? (x)->STB_(N,level) : 0)
4472
4473 #define stb_bst_base(TYPE, N, TREE, M, compare, PAR) \
4474 \
4475 static int STB_(N,_compare)(TYPE *p, TYPE *q) \
4476 { \
4477 compare \
4478 } \
4479 \
4480 static void STB_(N,setleft)(TYPE *q, TYPE *v) \
4481 { \
4482 q->STB_(N,left) = v; \
4483 PAR(if (v) v->STB_(N,parent) = q;) \
4484 } \
4485 \
4486 static void STB_(N,setright)(TYPE *q, TYPE *v) \
4487 { \
4488 q->STB_(N,right) = v; \
4489 PAR(if (v) v->STB_(N,parent) = q;) \
4490 } \
4491 \
4492 static TYPE *STB_(N,skew)(TYPE *q) \
4493 { \
4494 if (q == NULL) return q; \
4495 if (q->STB_(N,left) \
4496 && q->STB_(N,left)->STB_(N,level) == q->STB_(N,level)) { \
4497 TYPE *p = q->STB_(N,left); \
4498 STB_(N,setleft)(q, p->STB_(N,right)); \
4499 STB_(N,setright)(p, q); \
4500 return p; \
4501 } \
4502 return q; \
4503 } \
4504 \
4505 static TYPE *STB_(N,split)(TYPE *p) \
4506 { \
4507 TYPE *q = p->STB_(N,right); \
4508 if (q && q->STB_(N,right) \
4509 && q->STB_(N,right)->STB_(N,level) == p->STB_(N,level)) { \
4510 STB_(N,setright)(p, q->STB_(N,left)); \
4511 STB_(N,setleft)(q,p); \
4512 ++q->STB_(N,level); \
4513 return q; \
4514 } \
4515 return p; \
4516 } \
4517 \
4518 TYPE *STB__(N,insert)(TYPE *tree, TYPE *item) \
4519 { \
4520 int c; \
4521 if (tree == NULL) { \
4522 item->STB_(N,left) = NULL; \
4523 item->STB_(N,right) = NULL; \
4524 item->STB_(N,level) = 1; \
4525 PAR(item->STB_(N,parent) = NULL;) \
4526 return item; \
4527 } \
4528 c = STB_(N,_compare)(item,tree); \
4529 if (c == 0) { \
4530 if (item != tree) { \
4531 STB_(N,setleft)(item, tree->STB_(N,left)); \
4532 STB_(N,setright)(item, tree->STB_(N,right)); \
4533 item->STB_(N,level) = tree->STB_(N,level); \
4534 PAR(item->STB_(N,parent) = NULL;) \
4535 } \
4536 return item; \
4537 } \
4538 if (c < 0) \
4539 STB_(N,setleft )(tree, STB__(N,insert)(tree->STB_(N,left), item)); \
4540 else \
4541 STB_(N,setright)(tree, STB__(N,insert)(tree->STB_(N,right), item)); \
4542 tree = STB_(N,skew)(tree); \
4543 tree = STB_(N,split)(tree); \
4544 PAR(tree->STB_(N,parent) = NULL;) \
4545 return tree; \
4546 } \
4547 \
4548 TYPE *STB__(N,remove)(TYPE *tree, TYPE *item) \
4549 { \
4550 static TYPE *delnode, *leaf, *restore; \
4551 if (tree == NULL) return NULL; \
4552 leaf = tree; \
4553 if (STB_(N,_compare)(item, tree) < 0) { \
4554 STB_(N,setleft)(tree, STB__(N,remove)(tree->STB_(N,left), item)); \
4555 } else { \
4556 TYPE *r; \
4557 delnode = tree; \
4558 r = STB__(N,remove)(tree->STB_(N,right), item); \
4559 /* maybe move 'leaf' up to this location */ \
4560 if (restore == tree) { tree = leaf; leaf = restore = NULL; } \
4561 STB_(N,setright)(tree,r); \
4562 assert(tree->STB_(N,right) != tree); \
4563 } \
4564 if (tree == leaf) { \
4565 if (delnode == item) { \
4566 tree = tree->STB_(N,right); \
4567 assert(leaf->STB_(N,left) == NULL); \
4568 /* move leaf (the right sibling) up to delnode */ \
4569 STB_(N,setleft )(leaf, item->STB_(N,left )); \
4570 STB_(N,setright)(leaf, item->STB_(N,right)); \
4571 leaf->STB_(N,level) = item->STB_(N,level); \
4572 if (leaf != item) \
4573 restore = delnode; \
4574 } \
4575 delnode = NULL; \
4576 } else { \
4577 if (STB__level(N,tree->STB_(N,left) ) < tree->STB_(N,level)-1 || \
4578 STB__level(N,tree->STB_(N,right)) < tree->STB_(N,level)-1) { \
4579 --tree->STB_(N,level); \
4580 if (STB__level(N,tree->STB_(N,right)) > tree->STB_(N,level)) \
4581 tree->STB_(N,right)->STB_(N,level) = tree->STB_(N,level); \
4582 tree = STB_(N,skew)(tree); \
4583 STB_(N,setright)(tree, STB_(N,skew)(tree->STB_(N,right))); \
4584 if (tree->STB_(N,right)) \
4585 STB_(N,setright)(tree->STB_(N,right), \
4586 STB_(N,skew)(tree->STB_(N,right)->STB_(N,right))); \
4587 tree = STB_(N,split)(tree); \
4588 if (tree->STB_(N,right)) \
4589 STB_(N,setright)(tree, STB_(N,split)(tree->STB_(N,right))); \
4590 } \
4591 } \
4592 PAR(if (tree) tree->STB_(N,parent) = NULL;) \
4593 return tree; \
4594 } \
4595 \
4596 TYPE *STB__(N,last)(TYPE *tree) \
4597 { \
4598 if (tree) \
4599 while (tree->STB_(N,right)) tree = tree->STB_(N,right); \
4600 return tree; \
4601 } \
4602 \
4603 TYPE *STB__(N,first)(TYPE *tree) \
4604 { \
4605 if (tree) \
4606 while (tree->STB_(N,left)) tree = tree->STB_(N,left); \
4607 return tree; \
4608 } \
4609 \
4610 TYPE *STB__(N,next)(TYPE *tree, TYPE *item) \
4611 { \
4612 TYPE *next = NULL; \
4613 if (item->STB_(N,right)) \
4614 return STB__(N,first)(item->STB_(N,right)); \
4615 PAR( \
4616 while(item->STB_(N,parent)) { \
4617 TYPE *up = item->STB_(N,parent); \
4618 if (up->STB_(N,left) == item) return up; \
4619 item = up; \
4620 } \
4621 return NULL; \
4622 ) \
4623 while (tree != item) { \
4624 if (STB_(N,_compare)(item, tree) < 0) { \
4625 next = tree; \
4626 tree = tree->STB_(N,left); \
4627 } else { \
4628 tree = tree->STB_(N,right); \
4629 } \
4630 } \
4631 return next; \
4632 } \
4633 \
4634 TYPE *STB__(N,prev)(TYPE *tree, TYPE *item) \
4635 { \
4636 TYPE *next = NULL; \
4637 if (item->STB_(N,left)) \
4638 return STB__(N,last)(item->STB_(N,left)); \
4639 PAR( \
4640 while(item->STB_(N,parent)) { \
4641 TYPE *up = item->STB_(N,parent); \
4642 if (up->STB_(N,right) == item) return up; \
4643 item = up; \
4644 } \
4645 return NULL; \
4646 ) \
4647 while (tree != item) { \
4648 if (STB_(N,_compare)(item, tree) < 0) { \
4649 tree = tree->STB_(N,left); \
4650 } else { \
4651 next = tree; \
4652 tree = tree->STB_(N,right); \
4653 } \
4654 } \
4655 return next; \
4656 } \
4657 \
4658 STB__DEBUG( \
4659 void STB__(N,_validate)(TYPE *tree, int root) \
4660 { \
4661 if (tree == NULL) return; \
4662 PAR(if(root) assert(tree->STB_(N,parent) == NULL);) \
4663 assert(STB__level(N,tree->STB_(N,left) ) == tree->STB_(N,level)-1); \
4664 assert(STB__level(N,tree->STB_(N,right)) <= tree->STB_(N,level)); \
4665 assert(STB__level(N,tree->STB_(N,right)) >= tree->STB_(N,level)-1); \
4666 if (tree->STB_(N,right)) { \
4667 assert(STB__level(N,tree->STB_(N,right)->STB_(N,right)) \
4668 != tree->STB_(N,level)); \
4669 PAR(assert(tree->STB_(N,right)->STB_(N,parent) == tree);) \
4670 } \
4671 PAR(if(tree->STB_(N,left)) assert(tree->STB_(N,left)->STB_(N,parent) == tree);) \
4672 STB__(N,_validate)(tree->STB_(N,left) ,0); \
4673 STB__(N,_validate)(tree->STB_(N,right),0); \
4674 } \
4675 ) \
4676 \
4677 typedef struct \
4678 { \
4679 TYPE *root; \
4680 } TREE; \
4681 \
4682 void STB__(M,Insert)(TREE *tree, TYPE *item) \
4683 { tree->root = STB__(N,insert)(tree->root, item); } \
4684 void STB__(M,Remove)(TREE *tree, TYPE *item) \
4685 { tree->root = STB__(N,remove)(tree->root, item); } \
4686 TYPE *STB__(M,Next)(TREE *tree, TYPE *item) \
4687 { return STB__(N,next)(tree->root, item); } \
4688 TYPE *STB__(M,Prev)(TREE *tree, TYPE *item) \
4689 { return STB__(N,prev)(tree->root, item); } \
4690 TYPE *STB__(M,First)(TREE *tree) { return STB__(N,first)(tree->root); } \
4691 TYPE *STB__(M,Last) (TREE *tree) { return STB__(N,last) (tree->root); } \
4692 void STB__(M,Init)(TREE *tree) { tree->root = NULL; }
4693
4694
4695 #define stb_bst_find(N,tree,fcompare) \
4696 { \
4697 int c; \
4698 while (tree != NULL) { \
4699 fcompare \
4700 if (c == 0) return tree; \
4701 if (c < 0) tree = tree->STB_(N,left); \
4702 else tree = tree->STB_(N,right); \
4703 } \
4704 return NULL; \
4705 }
4706
4707 #define stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,PAR) \
4708 stb_bst_base(TYPE,N,TREE,M, \
4709 VTYPE a = p->vfield; VTYPE b = q->vfield; return (compare);, PAR ) \
4710 \
4711 TYPE *STB__(N,find)(TYPE *tree, VTYPE a) \
4712 stb_bst_find(N,tree,VTYPE b = tree->vfield; c = (compare);) \
4713 TYPE *STB__(M,Find)(TREE *tree, VTYPE a) \
4714 { return STB__(N,find)(tree->root, a); }
4715
4716 #define stb_bst(TYPE,N,TREE,M,vfield,VTYPE,compare) \
4717 stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_noparent)
4718 #define stb_bst_parent(TYPE,N,TREE,M,vfield,VTYPE,compare) \
4719 stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_parent)
4720
4721
4722
4723 //////////////////////////////////////////////////////////////////////////////
4724 //
4725 // Pointer Nulling
4726 //
4727 // This lets you automatically NULL dangling pointers to "registered"
4728 // objects. Note that you have to make sure you call the appropriate
4729 // functions when you free or realloc blocks of memory that contain
4730 // pointers or pointer targets. stb.h can automatically do this for
4731 // stb_arr, or for all frees/reallocs if it's wrapping them.
4732 //
4733
4734 #ifdef STB_NPTR
4735
4736 STB_EXTERN void stb_nptr_set(void *address_of_pointer, void *value_to_write);
4737 STB_EXTERN void stb_nptr_didset(void *address_of_pointer);
4738
4739 STB_EXTERN void stb_nptr_didfree(void *address_being_freed, int len);
4740 STB_EXTERN void stb_nptr_free(void *address_being_freed, int len);
4741
4742 STB_EXTERN void stb_nptr_didrealloc(void *new_address, void *old_address, int len);
4743 STB_EXTERN void stb_nptr_recache(void); // recache all known pointers
4744 // do this after pointer sets outside your control, slow
4745
4746 #ifdef STB_DEFINE
4747 // for fast updating on free/realloc, we need to be able to find
4748 // all the objects (pointers and targets) within a given block;
4749 // this precludes hashing
4750
4751 // we use a three-level hierarchy of memory to minimize storage:
4752 // level 1: 65536 pointers to stb__memory_node (always uses 256 KB)
4753 // level 2: each stb__memory_node represents a 64K block of memory
4754 // with 256 stb__memory_leafs (worst case 64MB)
4755 // level 3: each stb__memory_leaf represents 256 bytes of memory
4756 // using a list of target locations and a list of pointers
4757 // (which are hopefully fairly short normally!)
4758
4759 // this approach won't work in 64-bit, which has a much larger address
4760 // space. need to redesign
4761
4762 #define STB__NPTR_ROOT_LOG2 16
4763 #define STB__NPTR_ROOT_NUM (1 << STB__NPTR_ROOT_LOG2)
4764 #define STB__NPTR_ROOT_SHIFT (32 - STB__NPTR_ROOT_LOG2)
4765
4766 #define STB__NPTR_NODE_LOG2 5
4767 #define STB__NPTR_NODE_NUM (1 << STB__NPTR_NODE_LOG2)
4768 #define STB__NPTR_NODE_MASK (STB__NPTR_NODE_NUM-1)
4769 #define STB__NPTR_NODE_SHIFT (STB__NPTR_ROOT_SHIFT - STB__NPTR_NODE_LOG2)
4770 #define STB__NPTR_NODE_OFFSET(x) (((x) >> STB__NPTR_NODE_SHIFT) & STB__NPTR_NODE_MASK)
4771
4772 typedef struct stb__st_nptr
4773 {
4774 void *ptr; // address of actual pointer
4775 struct stb__st_nptr *next; // next pointer with same target
4776 struct stb__st_nptr **prev; // prev pointer with same target, address of 'next' field (or first)
4777 struct stb__st_nptr *next_in_block;
4778 } stb__nptr;
4779
4780 typedef struct stb__st_nptr_target
4781 {
4782 void *ptr; // address of target
4783 stb__nptr *first; // address of first nptr pointing to this
4784 struct stb__st_nptr_target *next_in_block;
4785 } stb__nptr_target;
4786
4787 typedef struct
4788 {
4789 stb__nptr *pointers;
4790 stb__nptr_target *targets;
4791 } stb__memory_leaf;
4792
4793 typedef struct
4794 {
4795 stb__memory_leaf *children[STB__NPTR_NODE_NUM];
4796 } stb__memory_node;
4797
4798 stb__memory_node *stb__memtab_root[STB__NPTR_ROOT_NUM];
4799
stb__nptr_find_leaf(void * mem)4800 static stb__memory_leaf *stb__nptr_find_leaf(void *mem)
4801 {
4802 stb_uint32 address = (stb_uint32) mem;
4803 stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
4804 if (z)
4805 return z->children[STB__NPTR_NODE_OFFSET(address)];
4806 else
4807 return NULL;
4808 }
4809
stb__nptr_alloc(int size)4810 static void * stb__nptr_alloc(int size)
4811 {
4812 return stb__realloc_raw(0,size);
4813 }
4814
stb__nptr_free(void * p)4815 static void stb__nptr_free(void *p)
4816 {
4817 stb__realloc_raw(p,0);
4818 }
4819
stb__nptr_make_leaf(void * mem)4820 static stb__memory_leaf *stb__nptr_make_leaf(void *mem)
4821 {
4822 stb_uint32 address = (stb_uint32) mem;
4823 stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
4824 stb__memory_leaf *f;
4825 if (!z) {
4826 int i;
4827 z = (stb__memory_node *) stb__nptr_alloc(sizeof(*stb__memtab_root[0]));
4828 stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT] = z;
4829 for (i=0; i < 256; ++i)
4830 z->children[i] = 0;
4831 }
4832 f = (stb__memory_leaf *) stb__nptr_alloc(sizeof(*f));
4833 z->children[STB__NPTR_NODE_OFFSET(address)] = f;
4834 f->pointers = NULL;
4835 f->targets = NULL;
4836 return f;
4837 }
4838
stb__nptr_find_target(void * target,int force)4839 static stb__nptr_target *stb__nptr_find_target(void *target, int force)
4840 {
4841 stb__memory_leaf *p = stb__nptr_find_leaf(target);
4842 if (p) {
4843 stb__nptr_target *t = p->targets;
4844 while (t) {
4845 if (t->ptr == target)
4846 return t;
4847 t = t->next_in_block;
4848 }
4849 }
4850 if (force) {
4851 stb__nptr_target *t = (stb__nptr_target*) stb__nptr_alloc(sizeof(*t));
4852 if (!p) p = stb__nptr_make_leaf(target);
4853 t->ptr = target;
4854 t->first = NULL;
4855 t->next_in_block = p->targets;
4856 p->targets = t;
4857 return t;
4858 } else
4859 return NULL;
4860 }
4861
stb__nptr_find_pointer(void * ptr,int force)4862 static stb__nptr *stb__nptr_find_pointer(void *ptr, int force)
4863 {
4864 stb__memory_leaf *p = stb__nptr_find_leaf(ptr);
4865 if (p) {
4866 stb__nptr *t = p->pointers;
4867 while (t) {
4868 if (t->ptr == ptr)
4869 return t;
4870 t = t->next_in_block;
4871 }
4872 }
4873 if (force) {
4874 stb__nptr *t = (stb__nptr *) stb__nptr_alloc(sizeof(*t));
4875 if (!p) p = stb__nptr_make_leaf(ptr);
4876 t->ptr = ptr;
4877 t->next = NULL;
4878 t->prev = NULL;
4879 t->next_in_block = p->pointers;
4880 p->pointers = t;
4881 return t;
4882 } else
4883 return NULL;
4884 }
4885
stb_nptr_set(void * address_of_pointer,void * value_to_write)4886 void stb_nptr_set(void *address_of_pointer, void *value_to_write)
4887 {
4888 if (*(void **)address_of_pointer != value_to_write) {
4889 *(void **) address_of_pointer = value_to_write;
4890 stb_nptr_didset(address_of_pointer);
4891 }
4892 }
4893
stb_nptr_didset(void * address_of_pointer)4894 void stb_nptr_didset(void *address_of_pointer)
4895 {
4896 // first unlink from old chain
4897 void *new_address;
4898 stb__nptr *p = stb__nptr_find_pointer(address_of_pointer, 1); // force building if doesn't exist
4899 if (p->prev) { // if p->prev is NULL, we just built it, or it was NULL
4900 *(p->prev) = p->next;
4901 if (p->next) p->next->prev = p->prev;
4902 }
4903 // now add to new chain
4904 new_address = *(void **)address_of_pointer;
4905 if (new_address != NULL) {
4906 stb__nptr_target *t = stb__nptr_find_target(new_address, 1);
4907 p->next = t->first;
4908 if (p->next) p->next->prev = &p->next;
4909 p->prev = &t->first;
4910 t->first = p;
4911 } else {
4912 p->prev = NULL;
4913 p->next = NULL;
4914 }
4915 }
4916
stb__nptr_block(void * address,int len,void (* function)(stb__memory_leaf * f,int datum,void * start,void * end),int datum)4917 void stb__nptr_block(void *address, int len, void (*function)(stb__memory_leaf *f, int datum, void *start, void *end), int datum)
4918 {
4919 void *end_address = (void *) ((char *) address + len - 1);
4920 stb__memory_node *n;
4921 stb_uint32 start = (stb_uint32) address;
4922 stb_uint32 end = start + len - 1;
4923
4924 int b0 = start >> STB__NPTR_ROOT_SHIFT;
4925 int b1 = end >> STB__NPTR_ROOT_SHIFT;
4926 int b=b0,i,e0,e1;
4927
4928 e0 = STB__NPTR_NODE_OFFSET(start);
4929
4930 if (datum <= 0) {
4931 // first block
4932 n = stb__memtab_root[b0];
4933 if (n) {
4934 if (b0 != b1)
4935 e1 = STB__NPTR_NODE_NUM-1;
4936 else
4937 e1 = STB__NPTR_NODE_OFFSET(end);
4938 for (i=e0; i <= e1; ++i)
4939 if (n->children[i])
4940 function(n->children[i], datum, address, end_address);
4941 }
4942 if (b1 > b0) {
4943 // blocks other than the first and last block
4944 for (b=b0+1; b < b1; ++b) {
4945 n = stb__memtab_root[b];
4946 if (n)
4947 for (i=0; i <= STB__NPTR_NODE_NUM-1; ++i)
4948 if (n->children[i])
4949 function(n->children[i], datum, address, end_address);
4950 }
4951 // last block
4952 n = stb__memtab_root[b1];
4953 if (n) {
4954 e1 = STB__NPTR_NODE_OFFSET(end);
4955 for (i=0; i <= e1; ++i)
4956 if (n->children[i])
4957 function(n->children[i], datum, address, end_address);
4958 }
4959 }
4960 } else {
4961 if (b1 > b0) {
4962 // last block
4963 n = stb__memtab_root[b1];
4964 if (n) {
4965 e1 = STB__NPTR_NODE_OFFSET(end);
4966 for (i=e1; i >= 0; --i)
4967 if (n->children[i])
4968 function(n->children[i], datum, address, end_address);
4969 }
4970 // blocks other than the first and last block
4971 for (b=b1-1; b > b0; --b) {
4972 n = stb__memtab_root[b];
4973 if (n)
4974 for (i=STB__NPTR_NODE_NUM-1; i >= 0; --i)
4975 if (n->children[i])
4976 function(n->children[i], datum, address, end_address);
4977 }
4978 }
4979 // first block
4980 n = stb__memtab_root[b0];
4981 if (n) {
4982 if (b0 != b1)
4983 e1 = STB__NPTR_NODE_NUM-1;
4984 else
4985 e1 = STB__NPTR_NODE_OFFSET(end);
4986 for (i=e1; i >= e0; --i)
4987 if (n->children[i])
4988 function(n->children[i], datum, address, end_address);
4989 }
4990 }
4991 }
4992
stb__nptr_delete_pointers(stb__memory_leaf * f,int offset,void * start,void * end)4993 static void stb__nptr_delete_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
4994 {
4995 stb__nptr **p = &f->pointers;
4996 while (*p) {
4997 stb__nptr *n = *p;
4998 if (n->ptr >= start && n->ptr <= end) {
4999 // unlink
5000 if (n->prev) {
5001 *(n->prev) = n->next;
5002 if (n->next) n->next->prev = n->prev;
5003 }
5004 *p = n->next_in_block;
5005 stb__nptr_free(n);
5006 } else
5007 p = &(n->next_in_block);
5008 }
5009 }
5010
stb__nptr_delete_targets(stb__memory_leaf * f,int offset,void * start,void * end)5011 static void stb__nptr_delete_targets(stb__memory_leaf *f, int offset, void *start, void *end)
5012 {
5013 stb__nptr_target **p = &f->targets;
5014 while (*p) {
5015 stb__nptr_target *n = *p;
5016 if (n->ptr >= start && n->ptr <= end) {
5017 // null pointers
5018 stb__nptr *z = n->first;
5019 while (z) {
5020 stb__nptr *y = z->next;
5021 z->prev = NULL;
5022 z->next = NULL;
5023 *(void **) z->ptr = NULL;
5024 z = y;
5025 }
5026 // unlink this target
5027 *p = n->next_in_block;
5028 stb__nptr_free(n);
5029 } else
5030 p = &(n->next_in_block);
5031 }
5032 }
5033
stb_nptr_didfree(void * address_being_freed,int len)5034 void stb_nptr_didfree(void *address_being_freed, int len)
5035 {
5036 // step one: delete all pointers in this block
5037 stb__nptr_block(address_being_freed, len, stb__nptr_delete_pointers, 0);
5038 // step two: NULL all pointers to this block; do this second to avoid NULLing deleted pointers
5039 stb__nptr_block(address_being_freed, len, stb__nptr_delete_targets, 0);
5040 }
5041
stb_nptr_free(void * address_being_freed,int len)5042 void stb_nptr_free(void *address_being_freed, int len)
5043 {
5044 free(address_being_freed);
5045 stb_nptr_didfree(address_being_freed, len);
5046 }
5047
stb__nptr_move_targets(stb__memory_leaf * f,int offset,void * start,void * end)5048 static void stb__nptr_move_targets(stb__memory_leaf *f, int offset, void *start, void *end)
5049 {
5050 stb__nptr_target **t = &f->targets;
5051 while (*t) {
5052 stb__nptr_target *n = *t;
5053 if (n->ptr >= start && n->ptr <= end) {
5054 stb__nptr *z;
5055 stb__memory_leaf *f;
5056 // unlink n
5057 *t = n->next_in_block;
5058 // update n to new address
5059 n->ptr = (void *) ((char *) n->ptr + offset);
5060 f = stb__nptr_find_leaf(n->ptr);
5061 if (!f) f = stb__nptr_make_leaf(n->ptr);
5062 n->next_in_block = f->targets;
5063 f->targets = n;
5064 // now go through all pointers and make them point here
5065 z = n->first;
5066 while (z) {
5067 *(void**) z->ptr = n->ptr;
5068 z = z->next;
5069 }
5070 } else
5071 t = &(n->next_in_block);
5072 }
5073 }
5074
stb__nptr_move_pointers(stb__memory_leaf * f,int offset,void * start,void * end)5075 static void stb__nptr_move_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
5076 {
5077 stb__nptr **p = &f->pointers;
5078 while (*p) {
5079 stb__nptr *n = *p;
5080 if (n->ptr >= start && n->ptr <= end) {
5081 // unlink
5082 *p = n->next_in_block;
5083 n->ptr = (void *) ((int) n->ptr + offset);
5084 // move to new block
5085 f = stb__nptr_find_leaf(n->ptr);
5086 if (!f) f = stb__nptr_make_leaf(n->ptr);
5087 n->next_in_block = f->pointers;
5088 f->pointers = n;
5089 } else
5090 p = &(n->next_in_block);
5091 }
5092 }
5093
stb_nptr_realloc(void * new_address,void * old_address,int len)5094 void stb_nptr_realloc(void *new_address, void *old_address, int len)
5095 {
5096 if (new_address == old_address) return;
5097
5098 // have to move the pointers first, because moving the targets
5099 // requires writing to the pointers-to-the-targets, and if some of those moved too,
5100 // we need to make sure we don't write to the old memory
5101
5102 // step one: move all pointers within the block
5103 stb__nptr_block(old_address, len, stb__nptr_move_pointers, (char *) new_address - (char *) old_address);
5104 // step two: move all targets within the block
5105 stb__nptr_block(old_address, len, stb__nptr_move_targets, (char *) new_address - (char *) old_address);
5106 }
5107
stb_nptr_move(void * new_address,void * old_address)5108 void stb_nptr_move(void *new_address, void *old_address)
5109 {
5110 stb_nptr_realloc(new_address, old_address, 1);
5111 }
5112
stb_nptr_recache(void)5113 void stb_nptr_recache(void)
5114 {
5115 int i,j;
5116 for (i=0; i < STB__NPTR_ROOT_NUM; ++i)
5117 if (stb__memtab_root[i])
5118 for (j=0; j < STB__NPTR_NODE_NUM; ++j)
5119 if (stb__memtab_root[i]->children[j]) {
5120 stb__nptr *p = stb__memtab_root[i]->children[j]->pointers;
5121 while (p) {
5122 stb_nptr_didset(p->ptr);
5123 p = p->next_in_block;
5124 }
5125 }
5126 }
5127
5128 #endif // STB_DEFINE
5129 #endif // STB_NPTR
5130
5131
5132 //////////////////////////////////////////////////////////////////////////////
5133 //
5134 // File Processing
5135 //
5136
5137
5138 #ifdef _WIN32
5139 #define stb_rename(x,y) _wrename((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
5140 #else
5141 #define stb_rename rename
5142 #endif
5143
5144 STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
5145 STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
5146 STB_EXTERN int stb_size_varlen64(stb_uint64 v);
5147
5148
5149 #define stb_filec (char *) stb_file
5150 #define stb_fileu (unsigned char *) stb_file
5151 STB_EXTERN void * stb_file(char *filename, size_t *length);
5152 STB_EXTERN void * stb_file_max(char *filename, size_t *length);
5153 STB_EXTERN size_t stb_filelen(FILE *f);
5154 STB_EXTERN int stb_filewrite(char *filename, void *data, size_t length);
5155 STB_EXTERN int stb_filewritestr(char *filename, char *data);
5156 STB_EXTERN char ** stb_stringfile(char *filename, int *len);
5157 STB_EXTERN char ** stb_stringfile_trimmed(char *name, int *len, char comm);
5158 STB_EXTERN char * stb_fgets(char *buffer, int buflen, FILE *f);
5159 STB_EXTERN char * stb_fgets_malloc(FILE *f);
5160 STB_EXTERN int stb_fexists(char *filename);
5161 STB_EXTERN int stb_fcmp(char *s1, char *s2);
5162 STB_EXTERN int stb_feq(char *s1, char *s2);
5163 STB_EXTERN time_t stb_ftimestamp(char *filename);
5164
5165 STB_EXTERN int stb_fullpath(char *abs, int abs_size, char *rel);
5166 STB_EXTERN FILE * stb_fopen(char *filename, const char *mode);
5167 STB_EXTERN int stb_fclose(FILE *f, int keep);
5168
5169 enum
5170 {
5171 stb_keep_no = 0,
5172 stb_keep_yes = 1,
5173 stb_keep_if_different = 2,
5174 };
5175
5176 STB_EXTERN int stb_copyfile(char *src, char *dest);
5177
5178 STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
5179 STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
5180 STB_EXTERN int stb_size_varlen64(stb_uint64 v);
5181
5182 STB_EXTERN void stb_fwrite32(FILE *f, stb_uint32 datum);
5183 STB_EXTERN void stb_fput_varlen (FILE *f, int v);
5184 STB_EXTERN void stb_fput_varlenu(FILE *f, unsigned int v);
5185 STB_EXTERN int stb_fget_varlen (FILE *f);
5186 STB_EXTERN stb_uint stb_fget_varlenu(FILE *f);
5187 STB_EXTERN void stb_fput_ranged (FILE *f, int v, int b, stb_uint n);
5188 STB_EXTERN int stb_fget_ranged (FILE *f, int b, stb_uint n);
5189 STB_EXTERN int stb_size_varlen (int v);
5190 STB_EXTERN int stb_size_varlenu(unsigned int v);
5191 STB_EXTERN int stb_size_ranged (int b, stb_uint n);
5192
5193 STB_EXTERN int stb_fread(void *data, size_t len, size_t count, void *f);
5194 STB_EXTERN int stb_fwrite(void *data, size_t len, size_t count, void *f);
5195
5196 #if 0
5197 typedef struct
5198 {
5199 FILE *base_file;
5200 char *buffer;
5201 int buffer_size;
5202 int buffer_off;
5203 int buffer_left;
5204 } STBF;
5205
5206 STB_EXTERN STBF *stb_tfopen(char *filename, char *mode);
5207 STB_EXTERN int stb_tfread(void *data, size_t len, size_t count, STBF *f);
5208 STB_EXTERN int stb_tfwrite(void *data, size_t len, size_t count, STBF *f);
5209 #endif
5210
5211 #ifdef STB_DEFINE
5212
5213 #if 0
stb_tfopen(char * filename,char * mode)5214 STBF *stb_tfopen(char *filename, char *mode)
5215 {
5216 STBF *z;
5217 FILE *f = stb_p_fopen(filename, mode);
5218 if (!f) return NULL;
5219 z = (STBF *) malloc(sizeof(*z));
5220 if (!z) { fclose(f); return NULL; }
5221 z->base_file = f;
5222 if (!strcmp(mode, "rb") || !strcmp(mode, "wb")) {
5223 z->buffer_size = 4096;
5224 z->buffer_off = z->buffer_size;
5225 z->buffer_left = 0;
5226 z->buffer = malloc(z->buffer_size);
5227 if (!z->buffer) { free(z); fclose(f); return NULL; }
5228 } else {
5229 z->buffer = 0;
5230 z->buffer_size = 0;
5231 z->buffer_left = 0;
5232 }
5233 return z;
5234 }
5235
stb_tfread(void * data,size_t len,size_t count,STBF * f)5236 int stb_tfread(void *data, size_t len, size_t count, STBF *f)
5237 {
5238 int total = len*count, done=0;
5239 if (!total) return 0;
5240 if (total <= z->buffer_left) {
5241 memcpy(data, z->buffer + z->buffer_off, total);
5242 z->buffer_off += total;
5243 z->buffer_left -= total;
5244 return count;
5245 } else {
5246 char *out = (char *) data;
5247
5248 // consume all buffered data
5249 memcpy(data, z->buffer + z->buffer_off, z->buffer_left);
5250 done = z->buffer_left;
5251 out += z->buffer_left;
5252 z->buffer_left=0;
5253
5254 if (total-done > (z->buffer_size >> 1)) {
5255 done += fread(out
5256 }
5257 }
5258 }
5259 #endif
5260
5261 void stb_fwrite32(FILE *f, stb_uint32 x)
5262 {
5263 fwrite(&x, 4, 1, f);
5264 }
5265
5266 #if defined(_WIN32)
5267 #define stb__stat _stat
5268 #else
5269 #define stb__stat stat
5270 #endif
5271
5272 int stb_fexists(char *filename)
5273 {
5274 struct stb__stat buf;
5275 return stb__windows(
5276 _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
5277 stat(filename,&buf)
5278 ) == 0;
5279 }
5280
5281 time_t stb_ftimestamp(char *filename)
5282 {
5283 struct stb__stat buf;
5284 if (stb__windows(
5285 _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
5286 stat(filename,&buf)
5287 ) == 0)
5288 {
5289 return buf.st_mtime;
5290 } else {
5291 return 0;
5292 }
5293 }
5294
5295 size_t stb_filelen(FILE *f)
5296 {
5297 long len, pos;
5298 pos = ftell(f);
5299 fseek(f, 0, SEEK_END);
5300 len = ftell(f);
5301 fseek(f, pos, SEEK_SET);
5302 return (size_t) len;
5303 }
5304
5305 void *stb_file(char *filename, size_t *length)
5306 {
5307 FILE *f = stb__fopen(filename, "rb");
5308 char *buffer;
5309 size_t len, len2;
5310 if (!f) return NULL;
5311 len = stb_filelen(f);
5312 buffer = (char *) malloc(len+2); // nul + extra
5313 len2 = fread(buffer, 1, len, f);
5314 if (len2 == len) {
5315 if (length) *length = len;
5316 buffer[len] = 0;
5317 } else {
5318 free(buffer);
5319 buffer = NULL;
5320 }
5321 fclose(f);
5322 return buffer;
5323 }
5324
5325 int stb_filewrite(char *filename, void *data, size_t length)
5326 {
5327 FILE *f = stb_fopen(filename, "wb");
5328 if (f) {
5329 unsigned char *data_ptr = (unsigned char *) data;
5330 size_t remaining = length;
5331 while (remaining > 0) {
5332 size_t len2 = remaining > 65536 ? 65536 : remaining;
5333 size_t len3 = fwrite(data_ptr, 1, len2, f);
5334 if (len2 != len3) {
5335 fprintf(stderr, "Failed while writing %s\n", filename);
5336 break;
5337 }
5338 remaining -= len2;
5339 data_ptr += len2;
5340 }
5341 stb_fclose(f, stb_keep_if_different);
5342 }
5343 return f != NULL;
5344 }
5345
5346 int stb_filewritestr(char *filename, char *data)
5347 {
5348 return stb_filewrite(filename, data, strlen(data));
5349 }
5350
5351 void * stb_file_max(char *filename, size_t *length)
5352 {
5353 FILE *f = stb__fopen(filename, "rb");
5354 char *buffer;
5355 size_t len, maxlen;
5356 if (!f) return NULL;
5357 maxlen = *length;
5358 buffer = (char *) malloc(maxlen+1);
5359 len = fread(buffer, 1, maxlen, f);
5360 buffer[len] = 0;
5361 fclose(f);
5362 *length = len;
5363 return buffer;
5364 }
5365
5366 char ** stb_stringfile(char *filename, int *plen)
5367 {
5368 FILE *f = stb__fopen(filename, "rb");
5369 char *buffer, **list=NULL, *s;
5370 size_t len, count, i;
5371
5372 if (!f) return NULL;
5373 len = stb_filelen(f);
5374 buffer = (char *) malloc(len+1);
5375 len = fread(buffer, 1, len, f);
5376 buffer[len] = 0;
5377 fclose(f);
5378
5379 // two passes through: first time count lines, second time set them
5380 for (i=0; i < 2; ++i) {
5381 s = buffer;
5382 if (i == 1)
5383 list[0] = s;
5384 count = 1;
5385 while (*s) {
5386 if (*s == '\n' || *s == '\r') {
5387 // detect if both cr & lf are together
5388 int crlf = (s[0] + s[1]) == ('\n' + '\r');
5389 if (i == 1) *s = 0;
5390 if (crlf) ++s;
5391 if (s[1]) { // it's not over yet
5392 if (i == 1) list[count] = s+1;
5393 ++count;
5394 }
5395 }
5396 ++s;
5397 }
5398 if (i == 0) {
5399 list = (char **) malloc(sizeof(*list) * (count+1) + len+1);
5400 if (!list) return NULL;
5401 list[count] = 0;
5402 // recopy the file so there's just a single allocation to free
5403 memcpy(&list[count+1], buffer, len+1);
5404 free(buffer);
5405 buffer = (char *) &list[count+1];
5406 if (plen) *plen = (int) count;
5407 }
5408 }
5409 return list;
5410 }
5411
5412 char ** stb_stringfile_trimmed(char *name, int *len, char comment)
5413 {
5414 int i,n,o=0;
5415 char **s = stb_stringfile(name, &n);
5416 if (s == NULL) return NULL;
5417 for (i=0; i < n; ++i) {
5418 char *p = stb_skipwhite(s[i]);
5419 if (*p && *p != comment)
5420 s[o++] = p;
5421 }
5422 s[o] = NULL;
5423 if (len) *len = o;
5424 return s;
5425 }
5426
5427 char * stb_fgets(char *buffer, int buflen, FILE *f)
5428 {
5429 char *p;
5430 buffer[0] = 0;
5431 p = fgets(buffer, buflen, f);
5432 if (p) {
5433 int n = (int) (strlen(p)-1);
5434 if (n >= 0)
5435 if (p[n] == '\n')
5436 p[n] = 0;
5437 }
5438 return p;
5439 }
5440
5441 char * stb_fgets_malloc(FILE *f)
5442 {
5443 // avoid reallocing for small strings
5444 char quick_buffer[800];
5445 quick_buffer[sizeof(quick_buffer)-2] = 0;
5446 if (!fgets(quick_buffer, sizeof(quick_buffer), f))
5447 return NULL;
5448
5449 if (quick_buffer[sizeof(quick_buffer)-2] == 0) {
5450 size_t n = strlen(quick_buffer);
5451 if (n > 0 && quick_buffer[n-1] == '\n')
5452 quick_buffer[n-1] = 0;
5453 return stb_p_strdup(quick_buffer);
5454 } else {
5455 char *p;
5456 char *a = stb_p_strdup(quick_buffer);
5457 size_t len = sizeof(quick_buffer)-1;
5458
5459 while (!feof(f)) {
5460 if (a[len-1] == '\n') break;
5461 a = (char *) realloc(a, len*2);
5462 p = &a[len];
5463 p[len-2] = 0;
5464 if (!fgets(p, (int) len, f))
5465 break;
5466 if (p[len-2] == 0) {
5467 len += strlen(p);
5468 break;
5469 }
5470 len = len + (len-1);
5471 }
5472 if (a[len-1] == '\n')
5473 a[len-1] = 0;
5474 return a;
5475 }
5476 }
5477
5478 int stb_fullpath(char *abs, int abs_size, char *rel)
5479 {
5480 #ifdef _WIN32
5481 return _fullpath(abs, rel, abs_size) != NULL;
5482 #else
5483 if (rel[0] == '/' || rel[0] == '~') {
5484 if ((int) strlen(rel) >= abs_size)
5485 return 0;
5486 stb_p_strcpy_s(abs,65536,rel);
5487 return STB_TRUE;
5488 } else {
5489 int n;
5490 getcwd(abs, abs_size);
5491 n = strlen(abs);
5492 if (n+(int) strlen(rel)+2 <= abs_size) {
5493 abs[n] = '/';
5494 stb_p_strcpy_s(abs+n+1, 65536,rel);
5495 return STB_TRUE;
5496 } else {
5497 return STB_FALSE;
5498 }
5499 }
5500 #endif
5501 }
5502
5503 static int stb_fcmp_core(FILE *f, FILE *g)
5504 {
5505 char buf1[1024],buf2[1024];
5506 int n1,n2, res=0;
5507
5508 while (1) {
5509 n1 = (int) fread(buf1, 1, sizeof(buf1), f);
5510 n2 = (int) fread(buf2, 1, sizeof(buf2), g);
5511 res = memcmp(buf1,buf2,stb_min(n1,n2));
5512 if (res)
5513 break;
5514 if (n1 != n2) {
5515 res = n1 < n2 ? -1 : 1;
5516 break;
5517 }
5518 if (n1 == 0)
5519 break;
5520 }
5521
5522 fclose(f);
5523 fclose(g);
5524 return res;
5525 }
5526
5527 int stb_fcmp(char *s1, char *s2)
5528 {
5529 FILE *f = stb__fopen(s1, "rb");
5530 FILE *g = stb__fopen(s2, "rb");
5531
5532 if (f == NULL || g == NULL) {
5533 if (f) fclose(f);
5534 if (g) {
5535 fclose(g);
5536 return STB_TRUE;
5537 }
5538 return f != NULL;
5539 }
5540
5541 return stb_fcmp_core(f,g);
5542 }
5543
5544 int stb_feq(char *s1, char *s2)
5545 {
5546 FILE *f = stb__fopen(s1, "rb");
5547 FILE *g = stb__fopen(s2, "rb");
5548
5549 if (f == NULL || g == NULL) {
5550 if (f) fclose(f);
5551 if (g) fclose(g);
5552 return f == g;
5553 }
5554
5555 // feq is faster because it shortcuts if they're different length
5556 if (stb_filelen(f) != stb_filelen(g)) {
5557 fclose(f);
5558 fclose(g);
5559 return 0;
5560 }
5561
5562 return !stb_fcmp_core(f,g);
5563 }
5564
5565 static stb_ptrmap *stb__files;
5566
5567 typedef struct
5568 {
5569 char *temp_name;
5570 char *name;
5571 int errors;
5572 } stb__file_data;
5573
5574 static FILE *stb__open_temp_file(char *temp_name, char *src_name, const char *mode)
5575 {
5576 size_t p;
5577 #ifdef _MSC_VER
5578 int j;
5579 #endif
5580 FILE *f;
5581 // try to generate a temporary file in the same directory
5582 p = strlen(src_name)-1;
5583 while (p > 0 && src_name[p] != '/' && src_name[p] != '\\'
5584 && src_name[p] != ':' && src_name[p] != '~')
5585 --p;
5586 ++p;
5587
5588 memcpy(temp_name, src_name, p);
5589
5590 #ifdef _MSC_VER
5591 // try multiple times to make a temp file... just in
5592 // case some other process makes the name first
5593 for (j=0; j < 32; ++j) {
5594 stb_p_strcpy_s(temp_name+p, 65536, "stmpXXXXXX");
5595 if (!stb_p_mktemp(temp_name))
5596 return 0;
5597
5598 f = stb_p_fopen(temp_name, mode);
5599 if (f != NULL)
5600 break;
5601 }
5602 #else
5603 {
5604 stb_p_strcpy_s(temp_name+p, 65536, "stmpXXXXXX");
5605 #ifdef __MINGW32__
5606 int fd = open(stb_p_mktemp(temp_name), O_RDWR);
5607 #else
5608 int fd = mkstemp(temp_name);
5609 #endif
5610 if (fd == -1) return NULL;
5611 f = fdopen(fd, mode);
5612 if (f == NULL) {
5613 unlink(temp_name);
5614 close(fd);
5615 return NULL;
5616 }
5617 }
5618 #endif
5619 return f;
5620 }
5621
5622
5623 FILE * stb_fopen(char *filename, const char *mode)
5624 {
5625 FILE *f;
5626 char name_full[4096];
5627 char temp_full[sizeof(name_full) + 12];
5628
5629 // @TODO: if the file doesn't exist, we can also use the fastpath here
5630 if (mode[0] != 'w' && !strchr(mode, '+'))
5631 return stb__fopen(filename, mode);
5632
5633 // save away the full path to the file so if the program
5634 // changes the cwd everything still works right! unix has
5635 // better ways to do this, but we have to work in windows
5636 name_full[0] = '\0'; // stb_fullpath reads name_full[0]
5637 if (stb_fullpath(name_full, sizeof(name_full), filename)==0)
5638 return 0;
5639
5640 f = stb__open_temp_file(temp_full, name_full, mode);
5641 if (f != NULL) {
5642 stb__file_data *d = (stb__file_data *) malloc(sizeof(*d));
5643 if (!d) { assert(0); /* NOTREACHED */fclose(f); return NULL; }
5644 if (stb__files == NULL) stb__files = stb_ptrmap_create();
5645 d->temp_name = stb_p_strdup(temp_full);
5646 d->name = stb_p_strdup(name_full);
5647 d->errors = 0;
5648 stb_ptrmap_add(stb__files, f, d);
5649 return f;
5650 }
5651
5652 return NULL;
5653 }
5654
5655 int stb_fclose(FILE *f, int keep)
5656 {
5657 stb__file_data *d;
5658
5659 int ok = STB_FALSE;
5660 if (f == NULL) return 0;
5661
5662 if (ferror(f))
5663 keep = stb_keep_no;
5664
5665 fclose(f);
5666
5667 if (stb__files && stb_ptrmap_remove(stb__files, f, (void **) &d)) {
5668 if (stb__files->count == 0) {
5669 stb_ptrmap_destroy(stb__files);
5670 stb__files = NULL;
5671 }
5672 } else
5673 return STB_TRUE; // not special
5674
5675 if (keep == stb_keep_if_different) {
5676 // check if the files are identical
5677 if (stb_feq(d->name, d->temp_name)) {
5678 keep = stb_keep_no;
5679 ok = STB_TRUE; // report success if no change
5680 }
5681 }
5682
5683 if (keep == stb_keep_no) {
5684 remove(d->temp_name);
5685 } else {
5686 if (!stb_fexists(d->name)) {
5687 // old file doesn't exist, so just move the new file over it
5688 stb_rename(d->temp_name, d->name);
5689 } else {
5690 // don't delete the old file yet in case there are troubles! First rename it!
5691 char preserved_old_file[4096];
5692
5693 // generate a temp filename in the same directory (also creates it, which we don't need)
5694 FILE *dummy = stb__open_temp_file(preserved_old_file, d->name, "wb");
5695 if (dummy != NULL) {
5696 // we don't actually want the open file
5697 fclose(dummy);
5698
5699 // discard what we just created
5700 remove(preserved_old_file); // if this fails, there's nothing we can do, and following logic handles it as best as possible anyway
5701
5702 // move the existing file to the preserved name
5703 if (0 != stb_rename(d->name, preserved_old_file)) { // 0 on success
5704 // failed, state is:
5705 // filename -> old file
5706 // tempname -> new file
5707 // keep tempname around so we don't lose data
5708 } else {
5709 // state is:
5710 // preserved -> old file
5711 // tempname -> new file
5712 // move the new file to the old name
5713 if (0 == stb_rename(d->temp_name, d->name)) {
5714 // state is:
5715 // preserved -> old file
5716 // filename -> new file
5717 ok = STB_TRUE;
5718
5719 // 'filename -> new file' has always been the goal, so clean up
5720 remove(preserved_old_file); // nothing to be done if it fails
5721 } else {
5722 // couldn't rename, so try renaming preserved file back
5723
5724 // state is:
5725 // preserved -> old file
5726 // tempname -> new file
5727 stb_rename(preserved_old_file, d->name);
5728 // if the rename failed, there's nothing more we can do
5729 }
5730 }
5731 } else {
5732 // we couldn't get a temp filename. do this the naive way; the worst case failure here
5733 // leaves the filename pointing to nothing and the new file as a tempfile
5734 remove(d->name);
5735 stb_rename(d->temp_name, d->name);
5736 }
5737 }
5738 }
5739
5740 free(d->temp_name);
5741 free(d->name);
5742 free(d);
5743
5744 return ok;
5745 }
5746
5747 int stb_copyfile(char *src, char *dest)
5748 {
5749 char raw_buffer[1024];
5750 char *buffer;
5751 int buf_size = 65536;
5752
5753 FILE *f, *g;
5754
5755 // if file already exists at destination, do nothing
5756 if (stb_feq(src, dest)) return STB_TRUE;
5757
5758 // open file
5759 f = stb__fopen(src, "rb");
5760 if (f == NULL) return STB_FALSE;
5761
5762 // open file for writing
5763 g = stb__fopen(dest, "wb");
5764 if (g == NULL) {
5765 fclose(f);
5766 return STB_FALSE;
5767 }
5768
5769 buffer = (char *) malloc(buf_size);
5770 if (buffer == NULL) {
5771 buffer = raw_buffer;
5772 buf_size = sizeof(raw_buffer);
5773 }
5774
5775 while (!feof(f)) {
5776 size_t n = fread(buffer, 1, buf_size, f);
5777 if (n != 0)
5778 fwrite(buffer, 1, n, g);
5779 }
5780
5781 fclose(f);
5782 if (buffer != raw_buffer)
5783 free(buffer);
5784
5785 fclose(g);
5786 return STB_TRUE;
5787 }
5788
5789 // varlen:
5790 // v' = (v >> 31) + (v < 0 ? ~v : v)<<1; // small abs(v) => small v'
5791 // output v as big endian v'+k for v' <= k:
5792 // 1 byte : v' <= 0x00000080 ( -64 <= v < 64) 7 bits
5793 // 2 bytes: v' <= 0x00004000 (-8192 <= v < 8192) 14 bits
5794 // 3 bytes: v' <= 0x00200000 21 bits
5795 // 4 bytes: v' <= 0x10000000 28 bits
5796 // the number of most significant 1-bits in the first byte
5797 // equals the number of bytes after the first
5798
5799 #define stb__varlen_xform(v) (v<0 ? (~v << 1)+1 : (v << 1))
5800
5801 int stb_size_varlen(int v) { return stb_size_varlenu(stb__varlen_xform(v)); }
5802 int stb_size_varlenu(unsigned int v)
5803 {
5804 if (v < 0x00000080) return 1;
5805 if (v < 0x00004000) return 2;
5806 if (v < 0x00200000) return 3;
5807 if (v < 0x10000000) return 4;
5808 return 5;
5809 }
5810
5811 void stb_fput_varlen(FILE *f, int v) { stb_fput_varlenu(f, stb__varlen_xform(v)); }
5812
5813 void stb_fput_varlenu(FILE *f, unsigned int z)
5814 {
5815 if (z >= 0x10000000) fputc(0xF0,f);
5816 if (z >= 0x00200000) fputc((z < 0x10000000 ? 0xE0 : 0)+(z>>24),f);
5817 if (z >= 0x00004000) fputc((z < 0x00200000 ? 0xC0 : 0)+(z>>16),f);
5818 if (z >= 0x00000080) fputc((z < 0x00004000 ? 0x80 : 0)+(z>> 8),f);
5819 fputc(z,f);
5820 }
5821
5822 #define stb_fgetc(f) ((unsigned char) fgetc(f))
5823
5824 int stb_fget_varlen(FILE *f)
5825 {
5826 unsigned int z = stb_fget_varlenu(f);
5827 return (z & 1) ? ~(z>>1) : (z>>1);
5828 }
5829
5830 unsigned int stb_fget_varlenu(FILE *f)
5831 {
5832 unsigned int z;
5833 unsigned char d;
5834 d = stb_fgetc(f);
5835
5836 if (d >= 0x80) {
5837 if (d >= 0xc0) {
5838 if (d >= 0xe0) {
5839 if (d == 0xf0) z = stb_fgetc(f) << 24;
5840 else z = (d - 0xe0) << 24;
5841 z += stb_fgetc(f) << 16;
5842 }
5843 else
5844 z = (d - 0xc0) << 16;
5845 z += stb_fgetc(f) << 8;
5846 } else
5847 z = (d - 0x80) << 8;
5848 z += stb_fgetc(f);
5849 } else
5850 z = d;
5851 return z;
5852 }
5853
5854 stb_uint64 stb_fget_varlen64(FILE *f)
5855 {
5856 stb_uint64 z;
5857 unsigned char d;
5858 d = stb_fgetc(f);
5859
5860 if (d >= 0x80) {
5861 if (d >= 0xc0) {
5862 if (d >= 0xe0) {
5863 if (d >= 0xf0) {
5864 if (d >= 0xf8) {
5865 if (d >= 0xfc) {
5866 if (d >= 0xfe) {
5867 if (d >= 0xff)
5868 z = (stb_uint64) stb_fgetc(f) << 56;
5869 else
5870 z = (stb_uint64) (d - 0xfe) << 56;
5871 z |= (stb_uint64) stb_fgetc(f) << 48;
5872 } else z = (stb_uint64) (d - 0xfc) << 48;
5873 z |= (stb_uint64) stb_fgetc(f) << 40;
5874 } else z = (stb_uint64) (d - 0xf8) << 40;
5875 z |= (stb_uint64) stb_fgetc(f) << 32;
5876 } else z = (stb_uint64) (d - 0xf0) << 32;
5877 z |= (stb_uint) stb_fgetc(f) << 24;
5878 } else z = (stb_uint) (d - 0xe0) << 24;
5879 z |= (stb_uint) stb_fgetc(f) << 16;
5880 } else z = (stb_uint) (d - 0xc0) << 16;
5881 z |= (stb_uint) stb_fgetc(f) << 8;
5882 } else z = (stb_uint) (d - 0x80) << 8;
5883 z |= stb_fgetc(f);
5884 } else
5885 z = d;
5886
5887 return (z & 1) ? ~(z >> 1) : (z >> 1);
5888 }
5889
5890 int stb_size_varlen64(stb_uint64 v)
5891 {
5892 if (v < 0x00000080) return 1;
5893 if (v < 0x00004000) return 2;
5894 if (v < 0x00200000) return 3;
5895 if (v < 0x10000000) return 4;
5896 if (v < STB_IMM_UINT64(0x0000000800000000)) return 5;
5897 if (v < STB_IMM_UINT64(0x0000040000000000)) return 6;
5898 if (v < STB_IMM_UINT64(0x0002000000000000)) return 7;
5899 if (v < STB_IMM_UINT64(0x0100000000000000)) return 8;
5900 return 9;
5901 }
5902
5903 void stb_fput_varlen64(FILE *f, stb_uint64 v)
5904 {
5905 stb_uint64 z = stb__varlen_xform(v);
5906 int first=1;
5907 if (z >= STB_IMM_UINT64(0x100000000000000)) {
5908 fputc(0xff,f);
5909 first=0;
5910 }
5911 if (z >= STB_IMM_UINT64(0x02000000000000)) fputc((first ? 0xFE : 0)+(char)(z>>56),f), first=0;
5912 if (z >= STB_IMM_UINT64(0x00040000000000)) fputc((first ? 0xFC : 0)+(char)(z>>48),f), first=0;
5913 if (z >= STB_IMM_UINT64(0x00000800000000)) fputc((first ? 0xF8 : 0)+(char)(z>>40),f), first=0;
5914 if (z >= STB_IMM_UINT64(0x00000010000000)) fputc((first ? 0xF0 : 0)+(char)(z>>32),f), first=0;
5915 if (z >= STB_IMM_UINT64(0x00000000200000)) fputc((first ? 0xE0 : 0)+(char)(z>>24),f), first=0;
5916 if (z >= STB_IMM_UINT64(0x00000000004000)) fputc((first ? 0xC0 : 0)+(char)(z>>16),f), first=0;
5917 if (z >= STB_IMM_UINT64(0x00000000000080)) fputc((first ? 0x80 : 0)+(char)(z>> 8),f), first=0;
5918 fputc((char)z,f);
5919 }
5920
5921 void stb_fput_ranged(FILE *f, int v, int b, stb_uint n)
5922 {
5923 v -= b;
5924 if (n <= (1 << 31))
5925 assert((stb_uint) v < n);
5926 if (n > (1 << 24)) fputc(v >> 24, f);
5927 if (n > (1 << 16)) fputc(v >> 16, f);
5928 if (n > (1 << 8)) fputc(v >> 8, f);
5929 fputc(v,f);
5930 }
5931
5932 int stb_fget_ranged(FILE *f, int b, stb_uint n)
5933 {
5934 unsigned int v=0;
5935 if (n > (1 << 24)) v += stb_fgetc(f) << 24;
5936 if (n > (1 << 16)) v += stb_fgetc(f) << 16;
5937 if (n > (1 << 8)) v += stb_fgetc(f) << 8;
5938 v += stb_fgetc(f);
5939 return b+v;
5940 }
5941
5942 int stb_size_ranged(int b, stb_uint n)
5943 {
5944 if (n > (1 << 24)) return 4;
5945 if (n > (1 << 16)) return 3;
5946 if (n > (1 << 8)) return 2;
5947 return 1;
5948 }
5949
5950 void stb_fput_string(FILE *f, char *s)
5951 {
5952 size_t len = strlen(s);
5953 stb_fput_varlenu(f, (unsigned int) len);
5954 fwrite(s, 1, len, f);
5955 }
5956
5957 // inverse of the above algorithm
5958 char *stb_fget_string(FILE *f, void *p)
5959 {
5960 char *s;
5961 int len = stb_fget_varlenu(f);
5962 if (len > 4096) return NULL;
5963 s = p ? stb_malloc_string(p, len+1) : (char *) malloc(len+1);
5964 fread(s, 1, len, f);
5965 s[len] = 0;
5966 return s;
5967 }
5968
5969 char *stb_strdup(char *str, void *pool)
5970 {
5971 size_t len = strlen(str);
5972 char *p = stb_malloc_string(pool, len+1);
5973 stb_p_strcpy_s(p, len+1, str);
5974 return p;
5975 }
5976
5977 // strip the trailing '/' or '\\' from a directory so we can refer to it
5978 // as a file for _stat()
5979 char *stb_strip_final_slash(char *t)
5980 {
5981 if (t[0]) {
5982 char *z = t + strlen(t) - 1;
5983 // *z is the last character
5984 if (*z == '\\' || *z == '/')
5985 if (z != t+2 || t[1] != ':') // but don't strip it if it's e.g. "c:/"
5986 *z = 0;
5987 if (*z == '\\')
5988 *z = '/'; // canonicalize to make sure it matches db
5989 }
5990 return t;
5991 }
5992
5993 char *stb_strip_final_slash_regardless(char *t)
5994 {
5995 if (t[0]) {
5996 char *z = t + strlen(t) - 1;
5997 // *z is the last character
5998 if (*z == '\\' || *z == '/')
5999 *z = 0;
6000 if (*z == '\\')
6001 *z = '/'; // canonicalize to make sure it matches db
6002 }
6003 return t;
6004 }
6005 #endif
6006
6007 //////////////////////////////////////////////////////////////////////////////
6008 //
6009 // Options parsing
6010 //
6011
6012 STB_EXTERN char **stb_getopt_param(int *argc, char **argv, char *param);
6013 STB_EXTERN char **stb_getopt(int *argc, char **argv);
6014 STB_EXTERN void stb_getopt_free(char **opts);
6015
6016 #ifdef STB_DEFINE
6017
6018 void stb_getopt_free(char **opts)
6019 {
6020 int i;
6021 char ** o2 = opts;
6022 for (i=0; i < stb_arr_len(o2); ++i)
6023 free(o2[i]);
6024 stb_arr_free(o2);
6025 }
6026
6027 char **stb_getopt(int *argc, char **argv)
6028 {
6029 return stb_getopt_param(argc, argv, (char*) "");
6030 }
6031
6032 char **stb_getopt_param(int *argc, char **argv, char *param)
6033 {
6034 char ** opts=NULL;
6035 int i,j=1;
6036 for (i=1; i < *argc; ++i) {
6037 if (argv[i][0] != '-') {
6038 argv[j++] = argv[i];
6039 } else {
6040 if (argv[i][1] == 0) { // plain - == don't parse further options
6041 ++i;
6042 while (i < *argc)
6043 argv[j++] = argv[i++];
6044 break;
6045 } else if (argv[i][1] == '-') {
6046 // copy argument through including initial '-' for clarity
6047 stb_arr_push(opts, stb_p_strdup(argv[i]));
6048 } else {
6049 int k;
6050 char *q = argv[i]; // traverse options list
6051 for (k=1; q[k]; ++k) {
6052 char *s;
6053 if (strchr(param, q[k])) { // does it take a parameter?
6054 char *t = &q[k+1], z = q[k];
6055 size_t len=0;
6056 if (*t == 0) {
6057 if (i == *argc-1) { // takes a parameter, but none found
6058 *argc = 0;
6059 stb_getopt_free(opts);
6060 return NULL;
6061 }
6062 t = argv[++i];
6063 } else
6064 k += (int) strlen(t);
6065 len = strlen(t);
6066 s = (char *) malloc(len+2);
6067 if (!s) return NULL;
6068 s[0] = z;
6069 stb_p_strcpy_s(s+1, len+2, t);
6070 } else {
6071 // no parameter
6072 s = (char *) malloc(2);
6073 if (!s) return NULL;
6074 s[0] = q[k];
6075 s[1] = 0;
6076 }
6077 stb_arr_push(opts, s);
6078 }
6079 }
6080 }
6081 }
6082 stb_arr_push(opts, NULL);
6083 *argc = j;
6084 return opts;
6085 }
6086 #endif
6087
6088
6089 //////////////////////////////////////////////////////////////////////////////
6090 //
6091 // Portable directory reading
6092 //
6093
6094 STB_EXTERN char **stb_readdir_files (char *dir);
6095 STB_EXTERN char **stb_readdir_files_mask(char *dir, char *wild);
6096 STB_EXTERN char **stb_readdir_subdirs(char *dir);
6097 STB_EXTERN char **stb_readdir_subdirs_mask(char *dir, char *wild);
6098 STB_EXTERN void stb_readdir_free (char **files);
6099 STB_EXTERN char **stb_readdir_recursive(char *dir, char *filespec);
6100 STB_EXTERN void stb_delete_directory_recursive(char *dir);
6101
6102 #ifdef STB_DEFINE
6103
6104 #ifdef _MSC_VER
6105 #include <io.h>
6106 #else
6107 #include <unistd.h>
6108 #include <dirent.h>
6109 #endif
6110
6111 void stb_readdir_free(char **files)
6112 {
6113 char **f2 = files;
6114 int i;
6115 for (i=0; i < stb_arr_len(f2); ++i)
6116 free(f2[i]);
6117 stb_arr_free(f2);
6118 }
6119
6120 static int isdotdirname(char *name)
6121 {
6122 if (name[0] == '.')
6123 return (name[1] == '.') ? !name[2] : !name[1];
6124 return 0;
6125 }
6126
6127 STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
6128 static char **readdir_raw(char *dir, int return_subdirs, char *mask)
6129 {
6130 char **results = NULL;
6131 char buffer[4096], with_slash[4096];
6132 size_t n;
6133
6134 #ifdef _MSC_VER
6135 stb__wchar *ws;
6136 struct _wfinddata_t data;
6137 #ifdef _WIN64
6138 const intptr_t none = -1;
6139 intptr_t z;
6140 #else
6141 const long none = -1;
6142 long z;
6143 #endif
6144 #else // !_MSC_VER
6145 const DIR *none = NULL;
6146 DIR *z;
6147 #endif
6148
6149 n = stb_strscpy(buffer,dir,sizeof(buffer));
6150 if (!n || n >= sizeof(buffer))
6151 return NULL;
6152 stb_fixpath(buffer);
6153 n--;
6154
6155 if (n > 0 && (buffer[n-1] != '/')) {
6156 buffer[n++] = '/';
6157 }
6158 buffer[n] = 0;
6159 if (!stb_strscpy(with_slash,buffer,sizeof(with_slash)))
6160 return NULL;
6161
6162 #ifdef _MSC_VER
6163 if (!stb_strscpy(buffer+n,"*.*",sizeof(buffer)-n))
6164 return NULL;
6165 ws = stb__from_utf8(buffer);
6166 z = _wfindfirst((const wchar_t *)ws, &data);
6167 #else
6168 z = opendir(dir);
6169 #endif
6170
6171 if (z != none) {
6172 int nonempty = STB_TRUE;
6173 #ifndef _MSC_VER
6174 struct dirent *data = readdir(z);
6175 nonempty = (data != NULL);
6176 #endif
6177
6178 if (nonempty) {
6179
6180 do {
6181 int is_subdir;
6182 #ifdef _MSC_VER
6183 char *name = stb__to_utf8((stb__wchar *)data.name);
6184 if (name == NULL) {
6185 fprintf(stderr, "%s to convert '%S' to %s!\n", "Unable", data.name, "utf8");
6186 continue;
6187 }
6188 is_subdir = !!(data.attrib & _A_SUBDIR);
6189 #else
6190 char *name = data->d_name;
6191 if (!stb_strscpy(buffer+n,name,sizeof(buffer)-n))
6192 break;
6193 // Could follow DT_LNK, but would need to check for recursive links.
6194 is_subdir = !!(data->d_type & DT_DIR);
6195 #endif
6196
6197 if (is_subdir == return_subdirs) {
6198 if (!is_subdir || !isdotdirname(name)) {
6199 if (!mask || stb_wildmatchi(mask, name)) {
6200 char buffer[4096],*p=buffer;
6201 if ( stb_snprintf(buffer, sizeof(buffer), "%s%s", with_slash, name) < 0 )
6202 break;
6203 if (buffer[0] == '.' && buffer[1] == '/')
6204 p = buffer+2;
6205 stb_arr_push(results, stb_p_strdup(p));
6206 }
6207 }
6208 }
6209 }
6210 #ifdef _MSC_VER
6211 while (0 == _wfindnext(z, &data));
6212 #else
6213 while ((data = readdir(z)) != NULL);
6214 #endif
6215 }
6216 #ifdef _MSC_VER
6217 _findclose(z);
6218 #else
6219 closedir(z);
6220 #endif
6221 }
6222 return results;
6223 }
6224
6225 char **stb_readdir_files (char *dir) { return readdir_raw(dir, 0, NULL); }
6226 char **stb_readdir_subdirs(char *dir) { return readdir_raw(dir, 1, NULL); }
6227 char **stb_readdir_files_mask(char *dir, char *wild) { return readdir_raw(dir, 0, wild); }
6228 char **stb_readdir_subdirs_mask(char *dir, char *wild) { return readdir_raw(dir, 1, wild); }
6229
6230 int stb__rec_max=0x7fffffff;
6231 static char **stb_readdir_rec(char **sofar, char *dir, char *filespec)
6232 {
6233 char **files;
6234 char ** dirs;
6235 char **p;
6236
6237 if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
6238
6239 files = stb_readdir_files_mask(dir, filespec);
6240 stb_arr_for(p, files) {
6241 stb_arr_push(sofar, stb_p_strdup(*p));
6242 if (stb_arr_len(sofar) >= stb__rec_max) break;
6243 }
6244 stb_readdir_free(files);
6245 if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
6246
6247 dirs = stb_readdir_subdirs(dir);
6248 stb_arr_for(p, dirs)
6249 sofar = stb_readdir_rec(sofar, *p, filespec);
6250 stb_readdir_free(dirs);
6251 return sofar;
6252 }
6253
6254 char **stb_readdir_recursive(char *dir, char *filespec)
6255 {
6256 return stb_readdir_rec(NULL, dir, filespec);
6257 }
6258
6259 void stb_delete_directory_recursive(char *dir)
6260 {
6261 char **list = stb_readdir_subdirs(dir);
6262 int i;
6263 for (i=0; i < stb_arr_len(list); ++i)
6264 stb_delete_directory_recursive(list[i]);
6265 stb_arr_free(list);
6266 list = stb_readdir_files(dir);
6267 for (i=0; i < stb_arr_len(list); ++i)
6268 if (!remove(list[i])) {
6269 // on windows, try again after making it writeable; don't ALWAYS
6270 // do this first since that would be slow in the normal case
6271 #ifdef _MSC_VER
6272 _chmod(list[i], _S_IWRITE);
6273 remove(list[i]);
6274 #endif
6275 }
6276 stb_arr_free(list);
6277 stb__windows(_rmdir,rmdir)(dir);
6278 }
6279
6280 #endif
6281
6282 //////////////////////////////////////////////////////////////////////////////
6283 //
6284 // construct trees from filenames; useful for cmirror summaries
6285
6286 typedef struct stb_dirtree2 stb_dirtree2;
6287
6288 struct stb_dirtree2
6289 {
6290 stb_dirtree2 **subdirs;
6291
6292 // make convenient for stb_summarize_tree
6293 int num_subdir;
6294 float weight;
6295
6296 // actual data
6297 char *fullpath;
6298 char *relpath;
6299 char **files;
6300 };
6301
6302 STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count);
6303 STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count);
6304 STB_EXTERN int stb_dir_is_prefix(char *dir, int dirlen, char *file);
6305
6306 #ifdef STB_DEFINE
6307
6308 int stb_dir_is_prefix(char *dir, int dirlen, char *file)
6309 {
6310 if (dirlen == 0) return STB_TRUE;
6311 if (stb_strnicmp(dir, file, dirlen)) return STB_FALSE;
6312 if (file[dirlen] == '/' || file[dirlen] == '\\') return STB_TRUE;
6313 return STB_FALSE;
6314 }
6315
6316 stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count)
6317 {
6318 char buffer1[1024];
6319 int i;
6320 int dlen = (int) strlen(src), elen;
6321 stb_dirtree2 *d;
6322 char ** descendents = NULL;
6323 char ** files = NULL;
6324 char *s;
6325 if (!count) return NULL;
6326 // first find all the ones that belong here... note this is will take O(NM) with N files and M subdirs
6327 for (i=0; i < count; ++i) {
6328 if (stb_dir_is_prefix(src, dlen, filelist[i])) {
6329 stb_arr_push(descendents, filelist[i]);
6330 }
6331 }
6332 if (descendents == NULL)
6333 return NULL;
6334 elen = dlen;
6335 // skip a leading slash
6336 if (elen == 0 && (descendents[0][0] == '/' || descendents[0][0] == '\\'))
6337 ++elen;
6338 else if (elen)
6339 ++elen;
6340 // now extract all the ones that have their root here
6341 for (i=0; i < stb_arr_len(descendents);) {
6342 if (!stb_strchr2(descendents[i]+elen, '/', '\\')) {
6343 stb_arr_push(files, descendents[i]);
6344 descendents[i] = descendents[stb_arr_len(descendents)-1];
6345 stb_arr_pop(descendents);
6346 } else
6347 ++i;
6348 }
6349 // now create a record
6350 d = (stb_dirtree2 *) malloc(sizeof(*d));
6351 d->files = files;
6352 d->subdirs = NULL;
6353 d->fullpath = stb_p_strdup(src);
6354 s = stb_strrchr2(d->fullpath, '/', '\\');
6355 if (s)
6356 ++s;
6357 else
6358 s = d->fullpath;
6359 d->relpath = s;
6360 // now create the children
6361 qsort(descendents, stb_arr_len(descendents), sizeof(char *), stb_qsort_stricmp(0));
6362 buffer1[0] = 0;
6363 for (i=0; i < stb_arr_len(descendents); ++i) {
6364 char buffer2[1024];
6365 char *s = descendents[i] + elen, *t;
6366 t = stb_strchr2(s, '/', '\\');
6367 assert(t);
6368 stb_strncpy(buffer2, descendents[i], (int) (t-descendents[i]+1));
6369 if (stb_stricmp(buffer1, buffer2)) {
6370 stb_dirtree2 *t = stb_dirtree2_from_files_relative(buffer2, descendents, stb_arr_len(descendents));
6371 assert(t != NULL);
6372 stb_p_strcpy_s(buffer1, sizeof(buffer1), buffer2);
6373 stb_arr_push(d->subdirs, t);
6374 }
6375 }
6376 d->num_subdir = stb_arr_len(d->subdirs);
6377 d->weight = 0;
6378 return d;
6379 }
6380
6381 stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count)
6382 {
6383 return stb_dirtree2_from_files_relative((char*) "", filelist, count);
6384 }
6385 #endif
6386
6387 //////////////////////////////////////////////////////////////////////////////
6388 //
6389 // Checksums: CRC-32, ADLER32, SHA-1
6390 //
6391 // CRC-32 and ADLER32 allow streaming blocks
6392 // SHA-1 requires either a complete buffer, max size 2^32 - 73
6393 // or it can checksum directly from a file, max 2^61
6394
6395 #define STB_ADLER32_SEED 1
6396 #define STB_CRC32_SEED 0 // note that we logical NOT this in the code
6397
6398 STB_EXTERN stb_uint
6399 stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen);
6400 STB_EXTERN stb_uint
6401 stb_crc32_block(stb_uint crc32, stb_uchar *buffer, stb_uint len);
6402 STB_EXTERN stb_uint stb_crc32(unsigned char *buffer, stb_uint len);
6403
6404 STB_EXTERN void stb_sha1(
6405 unsigned char output[20], unsigned char *buffer, unsigned int len);
6406 STB_EXTERN int stb_sha1_file(unsigned char output[20], char *file);
6407
6408 STB_EXTERN void stb_sha1_readable(char display[27], unsigned char sha[20]);
6409
6410 #ifdef STB_DEFINE
6411 stb_uint stb_crc32_block(stb_uint crc, unsigned char *buffer, stb_uint len)
6412 {
6413 static stb_uint crc_table[256];
6414 stb_uint i,j,s;
6415 crc = ~crc;
6416
6417 if (crc_table[1] == 0)
6418 for(i=0; i < 256; i++) {
6419 for (s=i, j=0; j < 8; ++j)
6420 s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0);
6421 crc_table[i] = s;
6422 }
6423 for (i=0; i < len; ++i)
6424 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
6425 return ~crc;
6426 }
6427
6428 stb_uint stb_crc32(unsigned char *buffer, stb_uint len)
6429 {
6430 return stb_crc32_block(0, buffer, len);
6431 }
6432
6433 stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
6434 {
6435 const unsigned long ADLER_MOD = 65521;
6436 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
6437 unsigned long blocklen, i;
6438
6439 blocklen = buflen % 5552;
6440 while (buflen) {
6441 for (i=0; i + 7 < blocklen; i += 8) {
6442 s1 += buffer[0], s2 += s1;
6443 s1 += buffer[1], s2 += s1;
6444 s1 += buffer[2], s2 += s1;
6445 s1 += buffer[3], s2 += s1;
6446 s1 += buffer[4], s2 += s1;
6447 s1 += buffer[5], s2 += s1;
6448 s1 += buffer[6], s2 += s1;
6449 s1 += buffer[7], s2 += s1;
6450
6451 buffer += 8;
6452 }
6453
6454 for (; i < blocklen; ++i)
6455 s1 += *buffer++, s2 += s1;
6456
6457 s1 %= ADLER_MOD, s2 %= ADLER_MOD;
6458 buflen -= blocklen;
6459 blocklen = 5552;
6460 }
6461 return (s2 << 16) + s1;
6462 }
6463
6464 static void stb__sha1(stb_uchar *chunk, stb_uint h[5])
6465 {
6466 int i;
6467 stb_uint a,b,c,d,e;
6468 stb_uint w[80];
6469
6470 for (i=0; i < 16; ++i)
6471 w[i] = stb_big32(&chunk[i*4]);
6472 for (i=16; i < 80; ++i) {
6473 stb_uint t;
6474 t = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
6475 w[i] = (t + t) | (t >> 31);
6476 }
6477
6478 a = h[0];
6479 b = h[1];
6480 c = h[2];
6481 d = h[3];
6482 e = h[4];
6483
6484 #define STB__SHA1(k,f) \
6485 { \
6486 stb_uint temp = (a << 5) + (a >> 27) + (f) + e + (k) + w[i]; \
6487 e = d; \
6488 d = c; \
6489 c = (b << 30) + (b >> 2); \
6490 b = a; \
6491 a = temp; \
6492 }
6493
6494 i=0;
6495 for (; i < 20; ++i) STB__SHA1(0x5a827999, d ^ (b & (c ^ d)) );
6496 for (; i < 40; ++i) STB__SHA1(0x6ed9eba1, b ^ c ^ d );
6497 for (; i < 60; ++i) STB__SHA1(0x8f1bbcdc, (b & c) + (d & (b ^ c)) );
6498 for (; i < 80; ++i) STB__SHA1(0xca62c1d6, b ^ c ^ d );
6499
6500 #undef STB__SHA1
6501
6502 h[0] += a;
6503 h[1] += b;
6504 h[2] += c;
6505 h[3] += d;
6506 h[4] += e;
6507 }
6508
6509 void stb_sha1(stb_uchar output[20], stb_uchar *buffer, stb_uint len)
6510 {
6511 unsigned char final_block[128];
6512 stb_uint end_start, final_len, j;
6513 int i;
6514
6515 stb_uint h[5];
6516
6517 h[0] = 0x67452301;
6518 h[1] = 0xefcdab89;
6519 h[2] = 0x98badcfe;
6520 h[3] = 0x10325476;
6521 h[4] = 0xc3d2e1f0;
6522
6523 // we need to write padding to the last one or two
6524 // blocks, so build those first into 'final_block'
6525
6526 // we have to write one special byte, plus the 8-byte length
6527
6528 // compute the block where the data runs out
6529 end_start = len & ~63;
6530
6531 // compute the earliest we can encode the length
6532 if (((len+9) & ~63) == end_start) {
6533 // it all fits in one block, so fill a second-to-last block
6534 end_start -= 64;
6535 }
6536
6537 final_len = end_start + 128;
6538
6539 // now we need to copy the data in
6540 assert(end_start + 128 >= len+9);
6541 assert(end_start < len || len < 64-9);
6542
6543 j = 0;
6544 if (end_start > len)
6545 j = (stb_uint) - (int) end_start;
6546
6547 for (; end_start + j < len; ++j)
6548 final_block[j] = buffer[end_start + j];
6549 final_block[j++] = 0x80;
6550 while (j < 128-5) // 5 byte length, so write 4 extra padding bytes
6551 final_block[j++] = 0;
6552 // big-endian size
6553 final_block[j++] = len >> 29;
6554 final_block[j++] = len >> 21;
6555 final_block[j++] = len >> 13;
6556 final_block[j++] = len >> 5;
6557 final_block[j++] = len << 3;
6558 assert(j == 128 && end_start + j == final_len);
6559
6560 for (j=0; j < final_len; j += 64) { // 512-bit chunks
6561 if (j+64 >= end_start+64)
6562 stb__sha1(&final_block[j - end_start], h);
6563 else
6564 stb__sha1(&buffer[j], h);
6565 }
6566
6567 for (i=0; i < 5; ++i) {
6568 output[i*4 + 0] = h[i] >> 24;
6569 output[i*4 + 1] = h[i] >> 16;
6570 output[i*4 + 2] = h[i] >> 8;
6571 output[i*4 + 3] = h[i] >> 0;
6572 }
6573 }
6574
6575 #ifdef _MSC_VER
6576 int stb_sha1_file(stb_uchar output[20], char *file)
6577 {
6578 int i;
6579 stb_uint64 length=0;
6580 unsigned char buffer[128];
6581
6582 FILE *f = stb__fopen(file, "rb");
6583 stb_uint h[5];
6584
6585 if (f == NULL) return 0; // file not found
6586
6587 h[0] = 0x67452301;
6588 h[1] = 0xefcdab89;
6589 h[2] = 0x98badcfe;
6590 h[3] = 0x10325476;
6591 h[4] = 0xc3d2e1f0;
6592
6593 for(;;) {
6594 size_t n = fread(buffer, 1, 64, f);
6595 if (n == 64) {
6596 stb__sha1(buffer, h);
6597 length += n;
6598 } else {
6599 int block = 64;
6600
6601 length += n;
6602
6603 buffer[n++] = 0x80;
6604
6605 // if there isn't enough room for the length, double the block
6606 if (n + 8 > 64)
6607 block = 128;
6608
6609 // pad to end
6610 memset(buffer+n, 0, block-8-n);
6611
6612 i = block - 8;
6613 buffer[i++] = (stb_uchar) (length >> 53);
6614 buffer[i++] = (stb_uchar) (length >> 45);
6615 buffer[i++] = (stb_uchar) (length >> 37);
6616 buffer[i++] = (stb_uchar) (length >> 29);
6617 buffer[i++] = (stb_uchar) (length >> 21);
6618 buffer[i++] = (stb_uchar) (length >> 13);
6619 buffer[i++] = (stb_uchar) (length >> 5);
6620 buffer[i++] = (stb_uchar) (length << 3);
6621 assert(i == block);
6622 stb__sha1(buffer, h);
6623 if (block == 128)
6624 stb__sha1(buffer+64, h);
6625 else
6626 assert(block == 64);
6627 break;
6628 }
6629 }
6630 fclose(f);
6631
6632 for (i=0; i < 5; ++i) {
6633 output[i*4 + 0] = h[i] >> 24;
6634 output[i*4 + 1] = h[i] >> 16;
6635 output[i*4 + 2] = h[i] >> 8;
6636 output[i*4 + 3] = h[i] >> 0;
6637 }
6638
6639 return 1;
6640 }
6641 #endif // _MSC_VER
6642
6643 // client can truncate this wherever they like
6644 void stb_sha1_readable(char display[27], unsigned char sha[20])
6645 {
6646 char encoding[65] = "0123456789abcdefghijklmnopqrstuv"
6647 "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%$";
6648 int num_bits = 0, acc=0;
6649 int i=0,o=0;
6650 while (o < 26) {
6651 int v;
6652 // expand the accumulator
6653 if (num_bits < 6) {
6654 assert(i != 20);
6655 acc += sha[i++] << num_bits;
6656 num_bits += 8;
6657 }
6658 v = acc & ((1 << 6) - 1);
6659 display[o++] = encoding[v];
6660 acc >>= 6;
6661 num_bits -= 6;
6662 }
6663 assert(num_bits == 20*8 - 26*6);
6664 display[o++] = encoding[acc];
6665 }
6666
6667 #endif // STB_DEFINE
6668
6669 ///////////////////////////////////////////////////////////
6670 //
6671 // simplified WINDOWS registry interface... hopefully
6672 // we'll never actually use this?
6673
6674 #if defined(_WIN32)
6675
6676 STB_EXTERN void * stb_reg_open(const char *mode, const char *where); // mode: "rHKLM" or "rHKCU" or "w.."
6677 STB_EXTERN void stb_reg_close(void *reg);
6678 STB_EXTERN int stb_reg_read(void *zreg, const char *str, void *data, unsigned long len);
6679 STB_EXTERN int stb_reg_read_string(void *zreg, const char *str, char *data, int len);
6680 STB_EXTERN void stb_reg_write(void *zreg, const char *str, const void *data, unsigned long len);
6681 STB_EXTERN void stb_reg_write_string(void *zreg, const char *str, const char *data);
6682
6683 #if defined(STB_DEFINE) && !defined(STB_NO_REGISTRY)
6684
6685 #define STB_HAS_REGISTRY
6686
6687 #ifndef _WINDOWS_
6688
6689 #define HKEY void *
6690
6691 STB_EXTERN __declspec(dllimport) long __stdcall RegCloseKey ( HKEY hKey );
6692 STB_EXTERN __declspec(dllimport) long __stdcall RegCreateKeyExA ( HKEY hKey, const char * lpSubKey,
6693 int Reserved, char * lpClass, int dwOptions,
6694 int samDesired, void *lpSecurityAttributes, HKEY * phkResult, int * lpdwDisposition );
6695 STB_EXTERN __declspec(dllimport) long __stdcall RegDeleteKeyA ( HKEY hKey, const char * lpSubKey );
6696 STB_EXTERN __declspec(dllimport) long __stdcall RegQueryValueExA ( HKEY hKey, const char * lpValueName,
6697 int * lpReserved, unsigned long * lpType, unsigned char * lpData, unsigned long * lpcbData );
6698 STB_EXTERN __declspec(dllimport) long __stdcall RegSetValueExA ( HKEY hKey, const char * lpValueName,
6699 int Reserved, int dwType, const unsigned char* lpData, int cbData );
6700 STB_EXTERN __declspec(dllimport) long __stdcall RegOpenKeyExA ( HKEY hKey, const char * lpSubKey,
6701 int ulOptions, int samDesired, HKEY * phkResult );
6702
6703 #endif // _WINDOWS_
6704
6705 #define STB__REG_OPTION_NON_VOLATILE 0
6706 #define STB__REG_KEY_ALL_ACCESS 0x000f003f
6707 #define STB__REG_KEY_READ 0x00020019
6708
6709 #ifdef _M_AMD64
6710 #define STB__HKEY_CURRENT_USER 0x80000001ull
6711 #define STB__HKEY_LOCAL_MACHINE 0x80000002ull
6712 #else
6713 #define STB__HKEY_CURRENT_USER 0x80000001
6714 #define STB__HKEY_LOCAL_MACHINE 0x80000002
6715 #endif
6716
6717 void *stb_reg_open(const char *mode, const char *where)
6718 {
6719 long res;
6720 HKEY base;
6721 HKEY zreg;
6722 if (!stb_stricmp(mode+1, "cu") || !stb_stricmp(mode+1, "hkcu"))
6723 base = (HKEY) STB__HKEY_CURRENT_USER;
6724 else if (!stb_stricmp(mode+1, "lm") || !stb_stricmp(mode+1, "hklm"))
6725 base = (HKEY) STB__HKEY_LOCAL_MACHINE;
6726 else
6727 return NULL;
6728
6729 if (mode[0] == 'r')
6730 res = RegOpenKeyExA(base, where, 0, STB__REG_KEY_READ, &zreg);
6731 else if (mode[0] == 'w')
6732 res = RegCreateKeyExA(base, where, 0, NULL, STB__REG_OPTION_NON_VOLATILE, STB__REG_KEY_ALL_ACCESS, NULL, &zreg, NULL);
6733 else
6734 return NULL;
6735
6736 return res ? NULL : zreg;
6737 }
6738
6739 void stb_reg_close(void *reg)
6740 {
6741 RegCloseKey((HKEY) reg);
6742 }
6743
6744 #define STB__REG_SZ 1
6745 #define STB__REG_BINARY 3
6746 #define STB__REG_DWORD 4
6747
6748 int stb_reg_read(void *zreg, const char *str, void *data, unsigned long len)
6749 {
6750 unsigned long type;
6751 unsigned long alen = len;
6752 if (0 == RegQueryValueExA((HKEY) zreg, str, 0, &type, (unsigned char *) data, &len))
6753 if (type == STB__REG_BINARY || type == STB__REG_SZ || type == STB__REG_DWORD) {
6754 if (len < alen)
6755 *((char *) data + len) = 0;
6756 return 1;
6757 }
6758 return 0;
6759 }
6760
6761 void stb_reg_write(void *zreg, const char *str, const void *data, unsigned long len)
6762 {
6763 if (zreg)
6764 RegSetValueExA((HKEY) zreg, str, 0, STB__REG_BINARY, (const unsigned char *) data, len);
6765 }
6766
6767 int stb_reg_read_string(void *zreg, const char *str, char *data, int len)
6768 {
6769 if (!stb_reg_read(zreg, str, data, len)) return 0;
6770 data[len-1] = 0; // force a 0 at the end of the string no matter what
6771 return 1;
6772 }
6773
6774 void stb_reg_write_string(void *zreg, const char *str, const char *data)
6775 {
6776 if (zreg)
6777 RegSetValueExA((HKEY) zreg, str, 0, STB__REG_SZ, (const unsigned char *) data, (int) strlen(data)+1);
6778 }
6779 #endif // STB_DEFINE
6780 #endif // _WIN32
6781
6782
6783 //////////////////////////////////////////////////////////////////////////////
6784 //
6785 // stb_cfg - This is like the registry, but the config info
6786 // is all stored in plain old files where we can
6787 // backup and restore them easily. The LOCATION of
6788 // the config files is gotten from... the registry!
6789
6790 #ifndef STB_NO_STB_STRINGS
6791 typedef struct stb_cfg_st stb_cfg;
6792
6793 STB_EXTERN stb_cfg * stb_cfg_open(char *config, const char *mode); // mode = "r", "w"
6794 STB_EXTERN void stb_cfg_close(stb_cfg *cfg);
6795 STB_EXTERN int stb_cfg_read(stb_cfg *cfg, char *key, void *value, int len);
6796 STB_EXTERN void stb_cfg_write(stb_cfg *cfg, char *key, void *value, int len);
6797 STB_EXTERN int stb_cfg_read_string(stb_cfg *cfg, char *key, char *value, int len);
6798 STB_EXTERN void stb_cfg_write_string(stb_cfg *cfg, char *key, char *value);
6799 STB_EXTERN int stb_cfg_delete(stb_cfg *cfg, char *key);
6800 STB_EXTERN void stb_cfg_set_directory(char *dir);
6801
6802 #ifdef STB_DEFINE
6803
6804 typedef struct
6805 {
6806 char *key;
6807 void *value;
6808 int value_len;
6809 } stb__cfg_item;
6810
6811 struct stb_cfg_st
6812 {
6813 stb__cfg_item *data;
6814 char *loaded_file; // this needs to be freed
6815 FILE *f; // write the data to this file on close
6816 };
6817
6818 static const char *stb__cfg_sig = "sTbCoNfIg!\0\0";
6819 static char stb__cfg_dir[512];
6820 STB_EXTERN void stb_cfg_set_directory(char *dir)
6821 {
6822 stb_p_strcpy_s(stb__cfg_dir, sizeof(stb__cfg_dir), dir);
6823 }
6824
6825 STB_EXTERN stb_cfg * stb_cfg_open(char *config, const char *mode)
6826 {
6827 size_t len;
6828 stb_cfg *z;
6829 char file[512];
6830 if (mode[0] != 'r' && mode[0] != 'w') return NULL;
6831
6832 if (!stb__cfg_dir[0]) {
6833 #ifdef _WIN32
6834 stb_p_strcpy_s(stb__cfg_dir, sizeof(stb__cfg_dir), "c:/stb");
6835 #else
6836 strcpy(stb__cfg_dir, "~/.stbconfig");
6837 #endif
6838
6839 #ifdef STB_HAS_REGISTRY
6840 {
6841 void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
6842 if (reg) {
6843 stb_reg_read_string(reg, "config_dir", stb__cfg_dir, sizeof(stb__cfg_dir));
6844 stb_reg_close(reg);
6845 }
6846 }
6847 #endif
6848 }
6849
6850 stb_p_sprintf(file stb_p_size(sizeof(file)), "%s/%s.cfg", stb__cfg_dir, config);
6851
6852 z = (stb_cfg *) stb_malloc(0, sizeof(*z));
6853 z->data = NULL;
6854
6855 z->loaded_file = stb_filec(file, &len);
6856 if (z->loaded_file) {
6857 char *s = z->loaded_file;
6858 if (!memcmp(s, stb__cfg_sig, 12)) {
6859 char *s = z->loaded_file + 12;
6860 while (s < z->loaded_file + len) {
6861 stb__cfg_item a;
6862 int n = *(stb_int16 *) s;
6863 a.key = s+2;
6864 s = s+2 + n;
6865 a.value_len = *(int *) s;
6866 s += 4;
6867 a.value = s;
6868 s += a.value_len;
6869 stb_arr_push(z->data, a);
6870 }
6871 assert(s == z->loaded_file + len);
6872 }
6873 }
6874
6875 if (mode[0] == 'w')
6876 z->f = stb_p_fopen(file, "wb");
6877 else
6878 z->f = NULL;
6879
6880 return z;
6881 }
6882
6883 void stb_cfg_close(stb_cfg *z)
6884 {
6885 if (z->f) {
6886 int i;
6887 // write the file out
6888 fwrite(stb__cfg_sig, 12, 1, z->f);
6889 for (i=0; i < stb_arr_len(z->data); ++i) {
6890 stb_int16 n = (stb_int16) strlen(z->data[i].key)+1;
6891 fwrite(&n, 2, 1, z->f);
6892 fwrite(z->data[i].key, n, 1, z->f);
6893 fwrite(&z->data[i].value_len, 4, 1, z->f);
6894 fwrite(z->data[i].value, z->data[i].value_len, 1, z->f);
6895 }
6896 fclose(z->f);
6897 }
6898 stb_arr_free(z->data);
6899 stb_free(z);
6900 }
6901
6902 int stb_cfg_read(stb_cfg *z, char *key, void *value, int len)
6903 {
6904 int i;
6905 for (i=0; i < stb_arr_len(z->data); ++i) {
6906 if (!stb_stricmp(z->data[i].key, key)) {
6907 int n = stb_min(len, z->data[i].value_len);
6908 memcpy(value, z->data[i].value, n);
6909 if (n < len)
6910 *((char *) value + n) = 0;
6911 return 1;
6912 }
6913 }
6914 return 0;
6915 }
6916
6917 void stb_cfg_write(stb_cfg *z, char *key, void *value, int len)
6918 {
6919 int i;
6920 for (i=0; i < stb_arr_len(z->data); ++i)
6921 if (!stb_stricmp(z->data[i].key, key))
6922 break;
6923 if (i == stb_arr_len(z->data)) {
6924 stb__cfg_item p;
6925 p.key = stb_strdup(key, z);
6926 p.value = NULL;
6927 p.value_len = 0;
6928 stb_arr_push(z->data, p);
6929 }
6930 z->data[i].value = stb_malloc(z, len);
6931 z->data[i].value_len = len;
6932 memcpy(z->data[i].value, value, len);
6933 }
6934
6935 int stb_cfg_delete(stb_cfg *z, char *key)
6936 {
6937 int i;
6938 for (i=0; i < stb_arr_len(z->data); ++i)
6939 if (!stb_stricmp(z->data[i].key, key)) {
6940 stb_arr_fastdelete(z->data, i);
6941 return 1;
6942 }
6943 return 0;
6944 }
6945
6946 int stb_cfg_read_string(stb_cfg *z, char *key, char *value, int len)
6947 {
6948 if (!stb_cfg_read(z, key, value, len)) return 0;
6949 value[len-1] = 0;
6950 return 1;
6951 }
6952
6953 void stb_cfg_write_string(stb_cfg *z, char *key, char *value)
6954 {
6955 stb_cfg_write(z, key, value, (int) strlen(value)+1);
6956 }
6957 #endif
6958
6959 //////////////////////////////////////////////////////////////////////////////
6960 //
6961 // stb_dirtree - load a description of a directory tree
6962 // uses a cache and stat()s the directories for changes
6963 // MUCH faster on NTFS, _wrong_ on FAT32, so should
6964 // ignore the db on FAT32
6965
6966 #ifdef _WIN32
6967
6968 typedef struct
6969 {
6970 char * path; // full path from passed-in root
6971 time_t last_modified;
6972 int num_files;
6973 int flag;
6974 } stb_dirtree_dir;
6975
6976 typedef struct
6977 {
6978 char *name; // name relative to path
6979 int dir; // index into dirs[] array
6980 stb_int64 size; // size, max 4GB
6981 time_t last_modified;
6982 int flag;
6983 } stb_dirtree_file;
6984
6985 typedef struct
6986 {
6987 stb_dirtree_dir *dirs;
6988 stb_dirtree_file *files;
6989
6990 // internal use
6991 void * string_pool; // used to free data en masse
6992 } stb_dirtree;
6993
6994 extern void stb_dirtree_free ( stb_dirtree *d );
6995 extern stb_dirtree *stb_dirtree_get ( char *dir);
6996 extern stb_dirtree *stb_dirtree_get_dir ( char *dir, char *cache_dir);
6997 extern stb_dirtree *stb_dirtree_get_with_file ( char *dir, char *cache_file);
6998
6999 // get a list of all the files recursively underneath 'dir'
7000 //
7001 // cache_file is used to store a copy of the directory tree to speed up
7002 // later calls. It must be unique to 'dir' and the current working
7003 // directory! Otherwise who knows what will happen (a good solution
7004 // is to put it _in_ dir, but this API doesn't force that).
7005 //
7006 // Also, it might be possible to break this if you have two different processes
7007 // do a call to stb_dirtree_get() with the same cache file at about the same
7008 // time, but I _think_ it might just work.
7009
7010 // i needed to build an identical data structure representing the state of
7011 // a mirrored copy WITHOUT bothering to rescan it (i.e. we're mirroring to
7012 // it WITHOUT scanning it, e.g. it's over the net), so this requires access
7013 // to all of the innards.
7014 extern void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last);
7015 extern void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last);
7016 extern void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir);
7017 extern void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir);
7018
7019 #ifdef STB_DEFINE
7020 static void stb__dirtree_add_dir(char *path, time_t last, stb_dirtree *active)
7021 {
7022 stb_dirtree_dir d;
7023 d.last_modified = last;
7024 d.num_files = 0;
7025 d.path = stb_strdup(path, active->string_pool);
7026 stb_arr_push(active->dirs, d);
7027 }
7028
7029 static void stb__dirtree_add_file(char *name, int dir, stb_int64 size, time_t last, stb_dirtree *active)
7030 {
7031 stb_dirtree_file f;
7032 f.dir = dir;
7033 f.size = size;
7034 f.last_modified = last;
7035 f.name = stb_strdup(name, active->string_pool);
7036 ++active->dirs[dir].num_files;
7037 stb_arr_push(active->files, f);
7038 }
7039
7040 // version 02 supports > 4GB files
7041 static char stb__signature[12] = { 's', 'T', 'b', 'D', 'i', 'R', 't', 'R', 'e', 'E', '0', '2' };
7042
7043 static void stb__dirtree_save_db(char *filename, stb_dirtree *data, char *root)
7044 {
7045 int i, num_dirs_final=0, num_files_final;
7046 char *info = root ? root : (char*)"";
7047 int *remap;
7048 FILE *f = stb_p_fopen(filename, "wb");
7049 if (!f) return;
7050
7051 fwrite(stb__signature, sizeof(stb__signature), 1, f);
7052 fwrite(info, strlen(info)+1, 1, f);
7053 // need to be slightly tricky and not write out NULLed directories, nor the root
7054
7055 // build remapping table of all dirs we'll be writing out
7056 remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(data->dirs));
7057 for (i=0; i < stb_arr_len(data->dirs); ++i) {
7058 if (data->dirs[i].path == NULL || (root && 0==stb_stricmp(data->dirs[i].path, root))) {
7059 remap[i] = -1;
7060 } else {
7061 remap[i] = num_dirs_final++;
7062 }
7063 }
7064
7065 fwrite(&num_dirs_final, 4, 1, f);
7066 for (i=0; i < stb_arr_len(data->dirs); ++i) {
7067 if (remap[i] >= 0) {
7068 fwrite(&data->dirs[i].last_modified, 4, 1, f);
7069 stb_fput_string(f, data->dirs[i].path);
7070 }
7071 }
7072
7073 num_files_final = 0;
7074 for (i=0; i < stb_arr_len(data->files); ++i)
7075 if (remap[data->files[i].dir] >= 0 && data->files[i].name)
7076 ++num_files_final;
7077
7078 fwrite(&num_files_final, 4, 1, f);
7079 for (i=0; i < stb_arr_len(data->files); ++i) {
7080 if (remap[data->files[i].dir] >= 0 && data->files[i].name) {
7081 stb_fput_ranged(f, remap[data->files[i].dir], 0, num_dirs_final);
7082 stb_fput_varlen64(f, data->files[i].size);
7083 fwrite(&data->files[i].last_modified, 4, 1, f);
7084 stb_fput_string(f, data->files[i].name);
7085 }
7086 }
7087
7088 fclose(f);
7089 }
7090
7091 // note: stomps any existing data, rather than appending
7092 static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir)
7093 {
7094 char sig[2048];
7095 int i,n;
7096 FILE *f = stb_p_fopen(filename, "rb");
7097
7098 if (!f) return;
7099
7100 data->string_pool = stb_malloc(0,1);
7101
7102 fread(sig, sizeof(stb__signature), 1, f);
7103 if (memcmp(stb__signature, sig, sizeof(stb__signature))) { fclose(f); return; }
7104 if (!fread(sig, strlen(dir)+1, 1, f)) { fclose(f); return; }
7105 if (stb_stricmp(sig,dir)) { fclose(f); return; }
7106
7107 // we can just read them straight in, because they're guaranteed to be valid
7108 fread(&n, 4, 1, f);
7109 stb_arr_setlen(data->dirs, n);
7110 for(i=0; i < stb_arr_len(data->dirs); ++i) {
7111 fread(&data->dirs[i].last_modified, 4, 1, f);
7112 data->dirs[i].path = stb_fget_string(f, data->string_pool);
7113 if (data->dirs[i].path == NULL) goto bail;
7114 }
7115 fread(&n, 4, 1, f);
7116 stb_arr_setlen(data->files, n);
7117 for (i=0; i < stb_arr_len(data->files); ++i) {
7118 data->files[i].dir = stb_fget_ranged(f, 0, stb_arr_len(data->dirs));
7119 data->files[i].size = stb_fget_varlen64(f);
7120 fread(&data->files[i].last_modified, 4, 1, f);
7121 data->files[i].name = stb_fget_string(f, data->string_pool);
7122 if (data->files[i].name == NULL) goto bail;
7123 }
7124
7125 if (0) {
7126 bail:
7127 stb_arr_free(data->dirs);
7128 stb_arr_free(data->files);
7129 }
7130 fclose(f);
7131 }
7132
7133 FILE *hlog;
7134
7135 static int stb__dircount, stb__dircount_mask, stb__showfile;
7136 static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active)
7137 {
7138 // this is dumb depth first; theoretically it might be faster
7139 // to fully traverse each directory before visiting its children,
7140 // but it's complicated and didn't seem like a gain in the test app
7141
7142 int n;
7143
7144 struct _wfinddatai64_t c_file;
7145 long hFile;
7146 stb__wchar full_path[1024];
7147 int has_slash;
7148 if (stb__showfile) printf("<");
7149
7150 has_slash = (path[0] && path[strlen(path)-1] == '/');
7151
7152 // @TODO: do this concatenation without using swprintf to avoid this mess:
7153 #if (defined(_MSC_VER) && _MSC_VER < 1400) // || (defined(__clang__))
7154 // confusingly, Windows Kits\10 needs to go down this path?!?
7155 // except now it doesn't, I don't know what changed
7156 if (has_slash)
7157 swprintf(full_path, L"%s*", stb__from_utf8(path));
7158 else
7159 swprintf(full_path, L"%s/*", stb__from_utf8(path));
7160 #else
7161 if (has_slash)
7162 swprintf((wchar_t *) full_path, (size_t) 1024, L"%s*", (wchar_t *) stb__from_utf8(path));
7163 else
7164 swprintf((wchar_t *) full_path, (size_t) 1024, L"%s/*", (wchar_t *) stb__from_utf8(path));
7165 #endif
7166
7167 // it's possible this directory is already present: that means it was in the
7168 // cache, but its parent wasn't... in that case, we're done with it
7169 if (stb__showfile) printf("C[%d]", stb_arr_len(active->dirs));
7170 for (n=0; n < stb_arr_len(active->dirs); ++n)
7171 if (0 == stb_stricmp(active->dirs[n].path, path)) {
7172 if (stb__showfile) printf("D");
7173 return;
7174 }
7175 if (stb__showfile) printf("E");
7176
7177 // otherwise, we need to add it
7178 stb__dirtree_add_dir(path, last_time, active);
7179 n = stb_arr_lastn(active->dirs);
7180
7181 if (stb__showfile) printf("[");
7182 if( (hFile = (long) _wfindfirsti64( (wchar_t *) full_path, &c_file )) != -1L ) {
7183 do {
7184 if (stb__showfile) printf(")");
7185 if (c_file.attrib & _A_SUBDIR) {
7186 // ignore subdirectories starting with '.', e.g. "." and ".."
7187 if (c_file.name[0] != '.') {
7188 char *new_path = (char *) full_path;
7189 char *temp = stb__to_utf8((stb__wchar *) c_file.name);
7190
7191 if (has_slash)
7192 stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s%s", path, temp);
7193 else
7194 stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s/%s", path, temp);
7195
7196 if (stb__dircount_mask) {
7197 ++stb__dircount;
7198 if (!(stb__dircount & stb__dircount_mask)) {
7199 char dummy_path[128], *pad;
7200 stb_strncpy(dummy_path, new_path, sizeof(dummy_path)-1);
7201 if (strlen(dummy_path) > 96) {
7202 stb_p_strcpy_s(dummy_path+96/2-1,128, "...");
7203 stb_p_strcpy_s(dummy_path+96/2+2,128, new_path + strlen(new_path)-96/2+2);
7204 }
7205 pad = dummy_path + strlen(dummy_path);
7206 while (pad < dummy_path+98)
7207 *pad++ = ' ';
7208 *pad = 0;
7209 printf("%s\r", dummy_path);
7210 #if 0
7211 if (hlog == 0) {
7212 hlog = stb_p_fopen("c:/x/temp.log", "w");
7213 fprintf(hlog, "%s\n", dummy_path);
7214 }
7215 #endif
7216 }
7217 }
7218
7219 stb__dirtree_scandir(new_path, c_file.time_write, active);
7220 }
7221 } else {
7222 char *temp = stb__to_utf8((stb__wchar *) c_file.name);
7223 stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active);
7224 }
7225 if (stb__showfile) printf("(");
7226 } while( _wfindnexti64( hFile, &c_file ) == 0 );
7227 if (stb__showfile) printf("]");
7228 _findclose( hFile );
7229 }
7230 if (stb__showfile) printf(">\n");
7231 }
7232
7233 // scan the database and see if it's all valid
7234 static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active)
7235 {
7236 int changes_detected = STB_FALSE;
7237 int i;
7238 int *remap;
7239 int *rescan=NULL;
7240 remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(db->dirs));
7241 memset(remap, 0, sizeof(remap[0]) * stb_arr_len(db->dirs));
7242 rescan = NULL;
7243
7244 for (i=0; i < stb_arr_len(db->dirs); ++i) {
7245 struct _stat info;
7246 if (stb__dircount_mask) {
7247 ++stb__dircount;
7248 if (!(stb__dircount & stb__dircount_mask)) {
7249 printf(".");
7250 }
7251 }
7252 if (0 == _stat(db->dirs[i].path, &info)) {
7253 if (info.st_mode & _S_IFDIR) {
7254 // it's still a directory, as expected
7255 int n = abs((int) (info.st_mtime - db->dirs[i].last_modified));
7256 if (n > 1 && n != 3600) { // the 3600 is a hack because sometimes this jumps for no apparent reason, even when no time zone or DST issues are at play
7257 // it's changed! force a rescan
7258 // we don't want to scan it until we've stat()d its
7259 // subdirs, though, so we queue it
7260 if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, (unsigned int) db->dirs[i].last_modified, (unsigned int) info.st_mtime);
7261 stb_arr_push(rescan, i);
7262 // update the last_mod time
7263 db->dirs[i].last_modified = info.st_mtime;
7264 // ignore existing files in this dir
7265 remap[i] = -1;
7266 changes_detected = STB_TRUE;
7267 } else {
7268 // it hasn't changed, just copy it through unchanged
7269 stb__dirtree_add_dir(db->dirs[i].path, db->dirs[i].last_modified, active);
7270 remap[i] = stb_arr_lastn(active->dirs);
7271 }
7272 } else {
7273 // this path used to refer to a directory, but now it's a file!
7274 // assume that the parent directory is going to be forced to rescan anyway
7275 goto delete_entry;
7276 }
7277 } else {
7278 delete_entry:
7279 // directory no longer exists, so don't copy it
7280 // we don't free it because it's in the string pool now
7281 db->dirs[i].path = NULL;
7282 remap[i] = -1;
7283 changes_detected = STB_TRUE;
7284 }
7285 }
7286
7287 // at this point, we have:
7288 //
7289 // <rescan> holds a list of directory indices that need to be scanned due to being out of date
7290 // <remap> holds the directory index in <active> for each dir in <db>, if it exists; -1 if not
7291 // directories in <rescan> are not in <active> yet
7292
7293 // so we can go ahead and remap all the known files right now
7294 for (i=0; i < stb_arr_len(db->files); ++i) {
7295 int dir = db->files[i].dir;
7296 if (remap[dir] >= 0) {
7297 stb__dirtree_add_file(db->files[i].name, remap[dir], db->files[i].size, db->files[i].last_modified, active);
7298 }
7299 }
7300
7301 // at this point we're done with db->files, and done with remap
7302 free(remap);
7303
7304 // now scan those directories using the standard scan
7305 for (i=0; i < stb_arr_len(rescan); ++i) {
7306 int z = rescan[i];
7307 stb__dirtree_scandir(db->dirs[z].path, db->dirs[z].last_modified, active);
7308 }
7309 stb_arr_free(rescan);
7310
7311 return changes_detected;
7312 }
7313
7314 static void stb__dirtree_free_raw(stb_dirtree *d)
7315 {
7316 stb_free(d->string_pool);
7317 stb_arr_free(d->dirs);
7318 stb_arr_free(d->files);
7319 }
7320
7321 stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file)
7322 {
7323 stb_dirtree *output = (stb_dirtree *) malloc(sizeof(*output));
7324 stb_dirtree db,active;
7325 int prev_dir_count, cache_mismatch;
7326
7327 char *stripped_dir; // store the directory name without a trailing '/' or '\\'
7328
7329 // load the database of last-known state on disk
7330 db.string_pool = NULL;
7331 db.files = NULL;
7332 db.dirs = NULL;
7333
7334 stripped_dir = stb_strip_final_slash(stb_p_strdup(dir));
7335
7336 if (cache_file != NULL)
7337 stb__dirtree_load_db(cache_file, &db, stripped_dir);
7338 else if (stb__showfile)
7339 printf("No cache file\n");
7340
7341 active.files = NULL;
7342 active.dirs = NULL;
7343 active.string_pool = stb_malloc(0,1); // @TODO: share string pools between both?
7344
7345 // check all the directories in the database; make note if
7346 // anything we scanned had changed, and rescan those things
7347 cache_mismatch = stb__dirtree_update_db(&db, &active);
7348
7349 // check the root tree
7350 prev_dir_count = stb_arr_len(active.dirs); // record how many directories we've seen
7351
7352 stb__dirtree_scandir(stripped_dir, 0, &active); // no last_modified time available for root
7353
7354 if (stb__dircount_mask)
7355 printf(" \r");
7356
7357 // done with the DB; write it back out if any changes, i.e. either
7358 // 1. any inconsistency found between cached information and actual disk
7359 // or 2. if scanning the root found any new directories--which we detect because
7360 // more than one directory got added to the active db during that scan
7361 if (cache_mismatch || stb_arr_len(active.dirs) > prev_dir_count+1)
7362 stb__dirtree_save_db(cache_file, &active, stripped_dir);
7363
7364 free(stripped_dir);
7365
7366 stb__dirtree_free_raw(&db);
7367
7368 *output = active;
7369 return output;
7370 }
7371
7372 stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir)
7373 {
7374 int i;
7375 stb_uint8 sha[20];
7376 char dir_lower[1024];
7377 char cache_file[1024],*s;
7378 if (cache_dir == NULL)
7379 return stb_dirtree_get_with_file(dir, NULL);
7380 stb_p_strcpy_s(dir_lower, sizeof(dir_lower), dir);
7381 stb_tolower(dir_lower);
7382 stb_sha1(sha, (unsigned char *) dir_lower, (unsigned int) strlen(dir_lower));
7383 stb_p_strcpy_s(cache_file, sizeof(cache_file), cache_dir);
7384 s = cache_file + strlen(cache_file);
7385 if (s[-1] != '/' && s[-1] != '\\') *s++ = '/';
7386 stb_p_strcpy_s(s, sizeof(cache_file), "dirtree_");
7387 s += strlen(s);
7388 for (i=0; i < 8; ++i) {
7389 char *hex = (char*)"0123456789abcdef";
7390 stb_uint z = sha[i];
7391 *s++ = hex[z >> 4];
7392 *s++ = hex[z & 15];
7393 }
7394 stb_p_strcpy_s(s, sizeof(cache_file), ".bin");
7395 return stb_dirtree_get_with_file(dir, cache_file);
7396 }
7397
7398 stb_dirtree *stb_dirtree_get(char *dir)
7399 {
7400 char cache_dir[256];
7401 stb_p_strcpy_s(cache_dir, sizeof(cache_dir), "c:/bindata");
7402 #ifdef STB_HAS_REGISTRY
7403 {
7404 void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
7405 if (reg) {
7406 stb_reg_read(reg, "dirtree", cache_dir, sizeof(cache_dir));
7407 stb_reg_close(reg);
7408 }
7409 }
7410 #endif
7411 return stb_dirtree_get_dir(dir, cache_dir);
7412 }
7413
7414 void stb_dirtree_free(stb_dirtree *d)
7415 {
7416 stb__dirtree_free_raw(d);
7417 free(d);
7418 }
7419
7420 void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last)
7421 {
7422 stb__dirtree_add_dir(path, last, active);
7423 }
7424
7425 void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last)
7426 {
7427 stb__dirtree_add_file(name, dir, size, last, active);
7428 }
7429
7430 void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir)
7431 {
7432 char *s = stb_strip_final_slash(stb_p_strdup(dir));
7433 target->dirs = 0;
7434 target->files = 0;
7435 target->string_pool = 0;
7436 stb__dirtree_load_db(filename, target, s);
7437 free(s);
7438 }
7439
7440 void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir)
7441 {
7442 stb__dirtree_save_db(filename, target, 0); // don't strip out any directories
7443 }
7444
7445 #endif // STB_DEFINE
7446
7447 #endif // _WIN32
7448 #endif // STB_NO_STB_STRINGS
7449
7450 //////////////////////////////////////////////////////////////////////////////
7451 //
7452 // STB_MALLOC_WRAPPER
7453 //
7454 // you can use the wrapper functions with your own malloc wrapper,
7455 // or define STB_MALLOC_WRAPPER project-wide to have
7456 // malloc/free/realloc/strdup all get vectored to it
7457
7458 // this has too many very specific error messages you could google for and find in stb.h,
7459 // so don't use it if they don't want any stb.h-identifiable strings
7460 #if defined(STB_DEFINE) && !defined(STB_NO_STB_STRINGS)
7461
7462 typedef struct
7463 {
7464 void *p;
7465 char *file;
7466 int line;
7467 size_t size;
7468 } stb_malloc_record;
7469
7470 #ifndef STB_MALLOC_HISTORY_COUNT
7471 #define STB_MALLOC_HISTORY_COUNT 50 // 800 bytes
7472 #endif
7473
7474 stb_malloc_record *stb__allocations;
7475 static int stb__alloc_size, stb__alloc_limit, stb__alloc_mask;
7476 int stb__alloc_count;
7477
7478 stb_malloc_record stb__alloc_history[STB_MALLOC_HISTORY_COUNT];
7479 int stb__history_pos;
7480
7481 static int stb__hashfind(void *p)
7482 {
7483 stb_uint32 h = stb_hashptr(p);
7484 int s,n = h & stb__alloc_mask;
7485 if (stb__allocations[n].p == p)
7486 return n;
7487 s = stb_rehash(h)|1;
7488 for(;;) {
7489 if (stb__allocations[n].p == NULL)
7490 return -1;
7491 n = (n+s) & stb__alloc_mask;
7492 if (stb__allocations[n].p == p)
7493 return n;
7494 }
7495 }
7496
7497 size_t stb_wrapper_allocsize(void *p)
7498 {
7499 int n = stb__hashfind(p);
7500 if (n < 0) return 0;
7501 return stb__allocations[n].size;
7502 }
7503
7504 static int stb__historyfind(void *p)
7505 {
7506 int n = stb__history_pos;
7507 int i;
7508 for (i=0; i < STB_MALLOC_HISTORY_COUNT; ++i) {
7509 if (--n < 0) n = STB_MALLOC_HISTORY_COUNT-1;
7510 if (stb__alloc_history[n].p == p)
7511 return n;
7512 }
7513 return -1;
7514 }
7515
7516 static void stb__add_alloc(void *p, size_t sz, char *file, int line);
7517 static void stb__grow_alloc(void)
7518 {
7519 int i,old_num = stb__alloc_size;
7520 stb_malloc_record *old = stb__allocations;
7521 if (stb__alloc_size == 0)
7522 stb__alloc_size = 64;
7523 else
7524 stb__alloc_size *= 2;
7525
7526 stb__allocations = (stb_malloc_record *) stb__realloc_raw(NULL, stb__alloc_size * sizeof(stb__allocations[0]));
7527 if (stb__allocations == NULL)
7528 stb_fatal("Internal error: couldn't grow malloc wrapper table");
7529 memset(stb__allocations, 0, stb__alloc_size * sizeof(stb__allocations[0]));
7530 stb__alloc_limit = (stb__alloc_size*3)>>2;
7531 stb__alloc_mask = stb__alloc_size-1;
7532
7533 stb__alloc_count = 0;
7534
7535 for (i=0; i < old_num; ++i)
7536 if (old[i].p > STB_DEL) {
7537 stb__add_alloc(old[i].p, old[i].size, old[i].file, old[i].line);
7538 assert(stb__hashfind(old[i].p) >= 0);
7539 }
7540 for (i=0; i < old_num; ++i)
7541 if (old[i].p > STB_DEL)
7542 assert(stb__hashfind(old[i].p) >= 0);
7543 stb__realloc_raw(old, 0);
7544 }
7545
7546 static void stb__add_alloc(void *p, size_t sz, char *file, int line)
7547 {
7548 stb_uint32 h;
7549 int n;
7550 if (stb__alloc_count >= stb__alloc_limit)
7551 stb__grow_alloc();
7552 h = stb_hashptr(p);
7553 n = h & stb__alloc_mask;
7554 if (stb__allocations[n].p > STB_DEL) {
7555 int s = stb_rehash(h)|1;
7556 do {
7557 n = (n+s) & stb__alloc_mask;
7558 } while (stb__allocations[n].p > STB_DEL);
7559 }
7560 assert(stb__allocations[n].p == NULL || stb__allocations[n].p == STB_DEL);
7561 stb__allocations[n].p = p;
7562 stb__allocations[n].size = sz;
7563 stb__allocations[n].line = line;
7564 stb__allocations[n].file = file;
7565 ++stb__alloc_count;
7566 }
7567
7568 static void stb__remove_alloc(int n, char *file, int line)
7569 {
7570 stb__alloc_history[stb__history_pos] = stb__allocations[n];
7571 stb__alloc_history[stb__history_pos].file = file;
7572 stb__alloc_history[stb__history_pos].line = line;
7573 if (++stb__history_pos == STB_MALLOC_HISTORY_COUNT)
7574 stb__history_pos = 0;
7575 stb__allocations[n].p = STB_DEL;
7576 --stb__alloc_count;
7577 }
7578
7579 void stb_wrapper_malloc(void *p, size_t sz, char *file, int line)
7580 {
7581 if (!p) return;
7582 stb__add_alloc(p,sz,file,line);
7583 }
7584
7585 void stb_wrapper_free(void *p, char *file, int line)
7586 {
7587 int n;
7588
7589 if (p == NULL) return;
7590
7591 n = stb__hashfind(p);
7592
7593 if (n >= 0)
7594 stb__remove_alloc(n, file, line);
7595 else {
7596 // tried to free something we hadn't allocated!
7597 n = stb__historyfind(p);
7598 assert(0); /* NOTREACHED */
7599 if (n >= 0)
7600 stb_fatal("Attempted to free %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7601 stb__alloc_history[n].size, p,
7602 file, line,
7603 stb__alloc_history[n].file, stb__alloc_history[n].line);
7604 else
7605 stb_fatal("Attempted to free unknown block %p at %s:%d", p, file,line);
7606 }
7607 }
7608
7609 void stb_wrapper_check(void *p)
7610 {
7611 int n;
7612
7613 if (p == NULL) return;
7614
7615 n = stb__hashfind(p);
7616
7617 if (n >= 0) return;
7618
7619 for (n=0; n < stb__alloc_size; ++n)
7620 if (stb__allocations[n].p == p)
7621 stb_fatal("Internal error: pointer %p was allocated, but hash search failed", p);
7622
7623 // tried to free something that wasn't allocated!
7624 n = stb__historyfind(p);
7625 if (n >= 0)
7626 stb_fatal("Checked %d-byte block %p previously freed/realloced at %s:%d",
7627 stb__alloc_history[n].size, p,
7628 stb__alloc_history[n].file, stb__alloc_history[n].line);
7629 stb_fatal("Checked unknown block %p");
7630 }
7631
7632 void stb_wrapper_realloc(void *p, void *q, size_t sz, char *file, int line)
7633 {
7634 int n;
7635 if (p == NULL) { stb_wrapper_malloc(q, sz, file, line); return; }
7636 if (q == NULL) return; // nothing happened
7637
7638 n = stb__hashfind(p);
7639 if (n == -1) {
7640 // tried to free something we hadn't allocated!
7641 // this is weird, though, because we got past the realloc!
7642 n = stb__historyfind(p);
7643 assert(0); /* NOTREACHED */
7644 if (n >= 0)
7645 stb_fatal("Attempted to realloc %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7646 stb__alloc_history[n].size, p,
7647 file, line,
7648 stb__alloc_history[n].file, stb__alloc_history[n].line);
7649 else
7650 stb_fatal("Attempted to realloc unknown block %p at %s:%d", p, file,line);
7651 } else {
7652 if (q == p) {
7653 stb__allocations[n].size = sz;
7654 stb__allocations[n].file = file;
7655 stb__allocations[n].line = line;
7656 } else {
7657 stb__remove_alloc(n, file, line);
7658 stb__add_alloc(q,sz,file,line);
7659 }
7660 }
7661 }
7662
7663 void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line))
7664 {
7665 int i;
7666 for (i=0; i < stb__alloc_size; ++i)
7667 if (stb__allocations[i].p > STB_DEL)
7668 func(stb__allocations[i].p , stb__allocations[i].size,
7669 stb__allocations[i].file, stb__allocations[i].line);
7670 }
7671
7672 void stb_wrapper_dump(char *filename)
7673 {
7674 int i;
7675 FILE *f = stb_p_fopen(filename, "w");
7676 if (!f) return;
7677 for (i=0; i < stb__alloc_size; ++i)
7678 if (stb__allocations[i].p > STB_DEL)
7679 fprintf(f, "%p %7d - %4d %s\n",
7680 stb__allocations[i].p , (int) stb__allocations[i].size,
7681 stb__allocations[i].line, stb__allocations[i].file);
7682 }
7683 #endif // STB_DEFINE
7684
7685
7686 //////////////////////////////////////////////////////////////////////////////
7687 //
7688 // stb_pointer_set
7689 //
7690 //
7691 // For data structures that support querying by key, data structure
7692 // classes always hand-wave away the issue of what to do if two entries
7693 // have the same key: basically, store a linked list of all the nodes
7694 // which have the same key (a LISP-style list).
7695 //
7696 // The thing is, it's not that trivial. If you have an O(log n)
7697 // lookup data structure, but then n/4 items have the same value,
7698 // you don't want to spend O(n) time scanning that list when
7699 // deleting an item if you already have a pointer to the item.
7700 // (You have to spend O(n) time enumerating all the items with
7701 // a given key, sure, and you can't accelerate deleting a particular
7702 // item if you only have the key, not a pointer to the item.)
7703 //
7704 // I'm going to call this data structure, whatever it turns out to
7705 // be, a "pointer set", because we don't store any associated data for
7706 // items in this data structure, we just answer the question of
7707 // whether an item is in it or not (it's effectively one bit per pointer).
7708 // Technically they don't have to be pointers; you could cast ints
7709 // to (void *) if you want, but you can't store 0 or 1 because of the
7710 // hash table.
7711 //
7712 // Since the fastest data structure we might want to add support for
7713 // identical-keys to is a hash table with O(1)-ish lookup time,
7714 // that means that the conceptual "linked list of all items with
7715 // the same indexed value" that we build needs to have the same
7716 // performance; that way when we index a table we think is arbitrary
7717 // ints, but in fact half of them are 0, we don't get screwed.
7718 //
7719 // Therefore, it needs to be a hash table, at least when it gets
7720 // large. On the other hand, when the data has totally arbitrary ints
7721 // or floats, there won't be many collisions, and we'll have tons of
7722 // 1-item bitmaps. That will be grossly inefficient as hash tables;
7723 // trade-off; the hash table is reasonably efficient per-item when
7724 // it's large, but not when it's small. So we need to do something
7725 // Judy-like and use different strategies depending on the size.
7726 //
7727 // Like Judy, we'll use the bottom bit to encode the strategy:
7728 //
7729 // bottom bits:
7730 // 00 - direct pointer
7731 // 01 - 4-item bucket (16 bytes, no length, NULLs)
7732 // 10 - N-item array
7733 // 11 - hash table
7734
7735 typedef struct stb_ps stb_ps;
7736
7737 STB_EXTERN int stb_ps_find (stb_ps *ps, void *value);
7738 STB_EXTERN stb_ps * stb_ps_add (stb_ps *ps, void *value);
7739 STB_EXTERN stb_ps * stb_ps_remove(stb_ps *ps, void *value);
7740 STB_EXTERN stb_ps * stb_ps_remove_any(stb_ps *ps, void **value);
7741 STB_EXTERN void stb_ps_delete(stb_ps *ps);
7742 STB_EXTERN int stb_ps_count (stb_ps *ps);
7743
7744 STB_EXTERN stb_ps * stb_ps_copy (stb_ps *ps);
7745 STB_EXTERN int stb_ps_subset(stb_ps *bigger, stb_ps *smaller);
7746 STB_EXTERN int stb_ps_eq (stb_ps *p0, stb_ps *p1);
7747
7748 STB_EXTERN void ** stb_ps_getlist (stb_ps *ps, int *count);
7749 STB_EXTERN int stb_ps_writelist(stb_ps *ps, void **list, int size );
7750
7751 // enum and fastlist don't allocate storage, but you must consume the
7752 // list before there's any chance the data structure gets screwed up;
7753 STB_EXTERN int stb_ps_enum (stb_ps *ps, void *data,
7754 int (*func)(void *value, void*data) );
7755 STB_EXTERN void ** stb_ps_fastlist(stb_ps *ps, int *count);
7756 // result:
7757 // returns a list, *count is the length of that list,
7758 // but some entries of the list may be invalid;
7759 // test with 'stb_ps_fastlist_valid(x)'
7760
7761 #define stb_ps_fastlist_valid(x) ((stb_uinta) (x) > 1)
7762
7763 #ifdef STB_DEFINE
7764
7765 enum
7766 {
7767 STB_ps_direct = 0,
7768 STB_ps_bucket = 1,
7769 STB_ps_array = 2,
7770 STB_ps_hash = 3,
7771 };
7772
7773 #define STB_BUCKET_SIZE 4
7774
7775 typedef struct
7776 {
7777 void *p[STB_BUCKET_SIZE];
7778 } stb_ps_bucket;
7779 #define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket))
7780 #define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket))
7781
7782 static void stb_bucket_free(stb_ps_bucket *b)
7783 {
7784 free(b);
7785 }
7786
7787 static stb_ps_bucket *stb_bucket_create2(void *v0, void *v1)
7788 {
7789 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7790 b->p[0] = v0;
7791 b->p[1] = v1;
7792 b->p[2] = NULL;
7793 b->p[3] = NULL;
7794 return b;
7795 }
7796
7797 static stb_ps_bucket * stb_bucket_create3(void **v)
7798 {
7799 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7800 b->p[0] = v[0];
7801 b->p[1] = v[1];
7802 b->p[2] = v[2];
7803 b->p[3] = NULL;
7804 return b;
7805 }
7806
7807
7808 // could use stb_arr, but this will save us memory
7809 typedef struct
7810 {
7811 int count;
7812 void *p[1];
7813 } stb_ps_array;
7814 #define GetArray(p) ((stb_ps_array *) ((char *) (p) - STB_ps_array))
7815 #define EncodeArray(p) ((stb_ps *) ((char *) (p) + STB_ps_array))
7816
7817 static int stb_ps_array_max = 13;
7818
7819 typedef struct
7820 {
7821 int size, mask;
7822 int count, count_deletes;
7823 int grow_threshhold;
7824 int shrink_threshhold;
7825 int rehash_threshhold;
7826 int any_offset;
7827 void *table[1];
7828 } stb_ps_hash;
7829 #define GetHash(p) ((stb_ps_hash *) ((char *) (p) - STB_ps_hash))
7830 #define EncodeHash(p) ((stb_ps *) ((char *) (p) + STB_ps_hash))
7831
7832 #define stb_ps_empty(v) (((stb_uint32) v) <= 1)
7833
7834 static stb_ps_hash *stb_ps_makehash(int size, int old_size, void **old_data)
7835 {
7836 int i;
7837 stb_ps_hash *h = (stb_ps_hash *) malloc(sizeof(*h) + (size-1) * sizeof(h->table[0]));
7838 assert(stb_is_pow2(size));
7839 h->size = size;
7840 h->mask = size-1;
7841 h->shrink_threshhold = (int) (0.3f * size);
7842 h-> grow_threshhold = (int) (0.8f * size);
7843 h->rehash_threshhold = (int) (0.9f * size);
7844 h->count = 0;
7845 h->count_deletes = 0;
7846 h->any_offset = 0;
7847 memset(h->table, 0, size * sizeof(h->table[0]));
7848 for (i=0; i < old_size; ++i)
7849 if (!stb_ps_empty((size_t)old_data[i]))
7850 stb_ps_add(EncodeHash(h), old_data[i]);
7851 return h;
7852 }
7853
7854 void stb_ps_delete(stb_ps *ps)
7855 {
7856 switch (3 & (int)(size_t) ps) {
7857 case STB_ps_direct: break;
7858 case STB_ps_bucket: stb_bucket_free(GetBucket(ps)); break;
7859 case STB_ps_array : free(GetArray(ps)); break;
7860 case STB_ps_hash : free(GetHash(ps)); break;
7861 }
7862 }
7863
7864 stb_ps *stb_ps_copy(stb_ps *ps)
7865 {
7866 int i;
7867 // not a switch: order based on expected performance/power-law distribution
7868 switch (3 & (int)(size_t) ps) {
7869 case STB_ps_direct: return ps;
7870 case STB_ps_bucket: {
7871 stb_ps_bucket *n = (stb_ps_bucket *) malloc(sizeof(*n));
7872 *n = *GetBucket(ps);
7873 return EncodeBucket(n);
7874 }
7875 case STB_ps_array: {
7876 stb_ps_array *a = GetArray(ps);
7877 stb_ps_array *n = (stb_ps_array *) malloc(sizeof(*n) + stb_ps_array_max * sizeof(n->p[0]));
7878 n->count = a->count;
7879 for (i=0; i < a->count; ++i)
7880 n->p[i] = a->p[i];
7881 return EncodeArray(n);
7882 }
7883 case STB_ps_hash: {
7884 stb_ps_hash *h = GetHash(ps);
7885 stb_ps_hash *n = stb_ps_makehash(h->size, h->size, h->table);
7886 return EncodeHash(n);
7887 }
7888 }
7889 assert(0); /* NOTREACHED */
7890 return NULL;
7891 }
7892
7893 int stb_ps_find(stb_ps *ps, void *value)
7894 {
7895 int i, code = 3 & (int)(size_t) ps;
7896 assert((3 & (int)(size_t) value) == STB_ps_direct);
7897 assert(stb_ps_fastlist_valid(value));
7898 // not a switch: order based on expected performance/power-law distribution
7899 if (code == STB_ps_direct)
7900 return value == ps;
7901 if (code == STB_ps_bucket) {
7902 stb_ps_bucket *b = GetBucket(ps);
7903 assert(STB_BUCKET_SIZE == 4);
7904 if (b->p[0] == value || b->p[1] == value ||
7905 b->p[2] == value || b->p[3] == value)
7906 return STB_TRUE;
7907 return STB_FALSE;
7908 }
7909 if (code == STB_ps_array) {
7910 stb_ps_array *a = GetArray(ps);
7911 for (i=0; i < a->count; ++i)
7912 if (a->p[i] == value)
7913 return STB_TRUE;
7914 return STB_FALSE;
7915 } else {
7916 stb_ps_hash *h = GetHash(ps);
7917 stb_uint32 hash = stb_hashptr(value);
7918 stb_uint32 s, n = hash & h->mask;
7919 void **t = h->table;
7920 if (t[n] == value) return STB_TRUE;
7921 if (t[n] == NULL) return STB_FALSE;
7922 s = stb_rehash(hash) | 1;
7923 do {
7924 n = (n + s) & h->mask;
7925 if (t[n] == value) return STB_TRUE;
7926 } while (t[n] != NULL);
7927 return STB_FALSE;
7928 }
7929 }
7930
7931 stb_ps * stb_ps_add (stb_ps *ps, void *value)
7932 {
7933 #ifdef STB_DEBUG
7934 assert(!stb_ps_find(ps,value));
7935 #endif
7936 if (value == NULL) return ps; // ignore NULL adds to avoid bad breakage
7937 assert((3 & (int)(size_t) value) == STB_ps_direct);
7938 assert(stb_ps_fastlist_valid(value));
7939 assert(value != STB_DEL); // STB_DEL is less likely
7940
7941 switch (3 & (int)(size_t) ps) {
7942 case STB_ps_direct:
7943 if (ps == NULL) return (stb_ps *) value;
7944 return EncodeBucket(stb_bucket_create2(ps,value));
7945
7946 case STB_ps_bucket: {
7947 stb_ps_bucket *b = GetBucket(ps);
7948 stb_ps_array *a;
7949 assert(STB_BUCKET_SIZE == 4);
7950 if (b->p[0] == NULL) { b->p[0] = value; return ps; }
7951 if (b->p[1] == NULL) { b->p[1] = value; return ps; }
7952 if (b->p[2] == NULL) { b->p[2] = value; return ps; }
7953 if (b->p[3] == NULL) { b->p[3] = value; return ps; }
7954 a = (stb_ps_array *) malloc(sizeof(*a) + 7 * sizeof(a->p[0])); // 8 slots, must be 2^k
7955 memcpy(a->p, b, sizeof(*b));
7956 a->p[4] = value;
7957 a->count = 5;
7958 stb_bucket_free(b);
7959 return EncodeArray(a);
7960 }
7961
7962 case STB_ps_array: {
7963 stb_ps_array *a = GetArray(ps);
7964 if (a->count == stb_ps_array_max) {
7965 // promote from array to hash
7966 stb_ps_hash *h = stb_ps_makehash(2 << stb_log2_ceil(a->count), a->count, a->p);
7967 free(a);
7968 return stb_ps_add(EncodeHash(h), value);
7969 }
7970 // do we need to resize the array? the array doubles in size when it
7971 // crosses a power-of-two
7972 if ((a->count & (a->count-1))==0) {
7973 int newsize = a->count*2;
7974 // clamp newsize to max if:
7975 // 1. it's larger than max
7976 // 2. newsize*1.5 is larger than max (to avoid extra resizing)
7977 if (newsize + a->count > stb_ps_array_max)
7978 newsize = stb_ps_array_max;
7979 a = (stb_ps_array *) realloc(a, sizeof(*a) + (newsize-1) * sizeof(a->p[0]));
7980 }
7981 a->p[a->count++] = value;
7982 return EncodeArray(a);
7983 }
7984 case STB_ps_hash: {
7985 stb_ps_hash *h = GetHash(ps);
7986 stb_uint32 hash = stb_hashptr(value);
7987 stb_uint32 n = hash & h->mask;
7988 void **t = h->table;
7989 // find first NULL or STB_DEL entry
7990 if (!stb_ps_empty((size_t)t[n])) {
7991 stb_uint32 s = stb_rehash(hash) | 1;
7992 do {
7993 n = (n + s) & h->mask;
7994 } while (!stb_ps_empty((size_t)t[n]));
7995 }
7996 if (t[n] == STB_DEL)
7997 -- h->count_deletes;
7998 t[n] = value;
7999 ++ h->count;
8000 if (h->count == h->grow_threshhold) {
8001 stb_ps_hash *h2 = stb_ps_makehash(h->size*2, h->size, t);
8002 free(h);
8003 return EncodeHash(h2);
8004 }
8005 if (h->count + h->count_deletes == h->rehash_threshhold) {
8006 stb_ps_hash *h2 = stb_ps_makehash(h->size, h->size, t);
8007 free(h);
8008 return EncodeHash(h2);
8009 }
8010 return ps;
8011 }
8012 }
8013 return NULL; /* NOTREACHED */
8014 }
8015
8016 stb_ps *stb_ps_remove(stb_ps *ps, void *value)
8017 {
8018 #ifdef STB_DEBUG
8019 assert(stb_ps_find(ps, value));
8020 #endif
8021 assert((3 & (int)(size_t) value) == STB_ps_direct);
8022 if (value == NULL) return ps; // ignore NULL removes to avoid bad breakage
8023 switch (3 & (int)(size_t) ps) {
8024 case STB_ps_direct:
8025 return ps == value ? NULL : ps;
8026 case STB_ps_bucket: {
8027 stb_ps_bucket *b = GetBucket(ps);
8028 int count=0;
8029 assert(STB_BUCKET_SIZE == 4);
8030 if (b->p[0] == value) b->p[0] = NULL; else count += (b->p[0] != NULL);
8031 if (b->p[1] == value) b->p[1] = NULL; else count += (b->p[1] != NULL);
8032 if (b->p[2] == value) b->p[2] = NULL; else count += (b->p[2] != NULL);
8033 if (b->p[3] == value) b->p[3] = NULL; else count += (b->p[3] != NULL);
8034 if (count == 1) { // shrink bucket at size 1
8035 value = b->p[0];
8036 if (value == NULL) value = b->p[1];
8037 if (value == NULL) value = b->p[2];
8038 if (value == NULL) value = b->p[3];
8039 assert(value != NULL);
8040 stb_bucket_free(b);
8041 return (stb_ps *) value; // return STB_ps_direct of value
8042 }
8043 return ps;
8044 }
8045 case STB_ps_array: {
8046 stb_ps_array *a = GetArray(ps);
8047 int i;
8048 for (i=0; i < a->count; ++i) {
8049 if (a->p[i] == value) {
8050 a->p[i] = a->p[--a->count];
8051 if (a->count == 3) { // shrink to bucket!
8052 stb_ps_bucket *b = stb_bucket_create3(a->p);
8053 free(a);
8054 return EncodeBucket(b);
8055 }
8056 return ps;
8057 }
8058 }
8059 return ps;
8060 }
8061 case STB_ps_hash: {
8062 stb_ps_hash *h = GetHash(ps);
8063 stb_uint32 hash = stb_hashptr(value);
8064 stb_uint32 s, n = hash & h->mask;
8065 void **t = h->table;
8066 if (t[n] != value) {
8067 s = stb_rehash(hash) | 1;
8068 do {
8069 n = (n + s) & h->mask;
8070 } while (t[n] != value);
8071 }
8072 t[n] = STB_DEL;
8073 -- h->count;
8074 ++ h->count_deletes;
8075 // should we shrink down to an array?
8076 if (h->count < stb_ps_array_max) {
8077 int n = 1 << stb_log2_floor(stb_ps_array_max);
8078 if (h->count < n) {
8079 stb_ps_array *a = (stb_ps_array *) malloc(sizeof(*a) + (n-1) * sizeof(a->p[0]));
8080 int i,j=0;
8081 for (i=0; i < h->size; ++i)
8082 if (!stb_ps_empty((size_t)t[i]))
8083 a->p[j++] = t[i];
8084 assert(j == h->count);
8085 a->count = j;
8086 free(h);
8087 return EncodeArray(a);
8088 }
8089 }
8090 if (h->count == h->shrink_threshhold) {
8091 stb_ps_hash *h2 = stb_ps_makehash(h->size >> 1, h->size, t);
8092 free(h);
8093 return EncodeHash(h2);
8094 }
8095 return ps;
8096 }
8097 }
8098 return ps; /* NOTREACHED */
8099 }
8100
8101 stb_ps *stb_ps_remove_any(stb_ps *ps, void **value)
8102 {
8103 assert(ps != NULL);
8104 switch (3 & (int)(size_t) ps) {
8105 case STB_ps_direct:
8106 *value = ps;
8107 return NULL;
8108 case STB_ps_bucket: {
8109 stb_ps_bucket *b = GetBucket(ps);
8110 int count=0, slast=0, last=0;
8111 assert(STB_BUCKET_SIZE == 4);
8112 if (b->p[0]) { ++count; last = 0; }
8113 if (b->p[1]) { ++count; slast = last; last = 1; }
8114 if (b->p[2]) { ++count; slast = last; last = 2; }
8115 if (b->p[3]) { ++count; slast = last; last = 3; }
8116 *value = b->p[last];
8117 b->p[last] = 0;
8118 if (count == 2) {
8119 void *leftover = b->p[slast]; // second to last
8120 stb_bucket_free(b);
8121 return (stb_ps *) leftover;
8122 }
8123 return ps;
8124 }
8125 case STB_ps_array: {
8126 stb_ps_array *a = GetArray(ps);
8127 *value = a->p[a->count-1];
8128 if (a->count == 4)
8129 return stb_ps_remove(ps, *value);
8130 --a->count;
8131 return ps;
8132 }
8133 case STB_ps_hash: {
8134 stb_ps_hash *h = GetHash(ps);
8135 void **t = h->table;
8136 stb_uint32 n = h->any_offset;
8137 while (stb_ps_empty((size_t)t[n]))
8138 n = (n + 1) & h->mask;
8139 *value = t[n];
8140 h->any_offset = (n+1) & h->mask;
8141 // check if we need to skip down to the previous type
8142 if (h->count-1 < stb_ps_array_max || h->count-1 == h->shrink_threshhold)
8143 return stb_ps_remove(ps, *value);
8144 t[n] = STB_DEL;
8145 -- h->count;
8146 ++ h->count_deletes;
8147 return ps;
8148 }
8149 }
8150 return ps; /* NOTREACHED */
8151 }
8152
8153
8154 void ** stb_ps_getlist(stb_ps *ps, int *count)
8155 {
8156 int i,n=0;
8157 void **p = NULL;
8158 switch (3 & (int)(size_t) ps) {
8159 case STB_ps_direct:
8160 if (ps == NULL) { *count = 0; return NULL; }
8161 p = (void **) malloc(sizeof(*p) * 1);
8162 p[0] = ps;
8163 *count = 1;
8164 return p;
8165 case STB_ps_bucket: {
8166 stb_ps_bucket *b = GetBucket(ps);
8167 p = (void **) malloc(sizeof(*p) * STB_BUCKET_SIZE);
8168 for (i=0; i < STB_BUCKET_SIZE; ++i)
8169 if (b->p[i] != NULL)
8170 p[n++] = b->p[i];
8171 break;
8172 }
8173 case STB_ps_array: {
8174 stb_ps_array *a = GetArray(ps);
8175 p = (void **) malloc(sizeof(*p) * a->count);
8176 memcpy(p, a->p, sizeof(*p) * a->count);
8177 *count = a->count;
8178 return p;
8179 }
8180 case STB_ps_hash: {
8181 stb_ps_hash *h = GetHash(ps);
8182 p = (void **) malloc(sizeof(*p) * h->count);
8183 for (i=0; i < h->size; ++i)
8184 if (!stb_ps_empty((size_t)h->table[i]))
8185 p[n++] = h->table[i];
8186 break;
8187 }
8188 }
8189 *count = n;
8190 return p;
8191 }
8192
8193 int stb_ps_writelist(stb_ps *ps, void **list, int size )
8194 {
8195 int i,n=0;
8196 switch (3 & (int)(size_t) ps) {
8197 case STB_ps_direct:
8198 if (ps == NULL || size <= 0) return 0;
8199 list[0] = ps;
8200 return 1;
8201 case STB_ps_bucket: {
8202 stb_ps_bucket *b = GetBucket(ps);
8203 for (i=0; i < STB_BUCKET_SIZE; ++i)
8204 if (b->p[i] != NULL && n < size)
8205 list[n++] = b->p[i];
8206 return n;
8207 }
8208 case STB_ps_array: {
8209 stb_ps_array *a = GetArray(ps);
8210 n = stb_min(size, a->count);
8211 memcpy(list, a->p, sizeof(*list) * n);
8212 return n;
8213 }
8214 case STB_ps_hash: {
8215 stb_ps_hash *h = GetHash(ps);
8216 if (size <= 0) return 0;
8217 for (i=0; i < h->count; ++i) {
8218 if (!stb_ps_empty((size_t)h->table[i])) {
8219 list[n++] = h->table[i];
8220 if (n == size) break;
8221 }
8222 }
8223 return n;
8224 }
8225 }
8226 return 0; /* NOTREACHED */
8227 }
8228
8229 int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data))
8230 {
8231 int i;
8232 switch (3 & (int)(size_t) ps) {
8233 case STB_ps_direct:
8234 if (ps == NULL) return STB_TRUE;
8235 return func(ps, data);
8236 case STB_ps_bucket: {
8237 stb_ps_bucket *b = GetBucket(ps);
8238 for (i=0; i < STB_BUCKET_SIZE; ++i)
8239 if (b->p[i] != NULL)
8240 if (!func(b->p[i], data))
8241 return STB_FALSE;
8242 return STB_TRUE;
8243 }
8244 case STB_ps_array: {
8245 stb_ps_array *a = GetArray(ps);
8246 for (i=0; i < a->count; ++i)
8247 if (!func(a->p[i], data))
8248 return STB_FALSE;
8249 return STB_TRUE;
8250 }
8251 case STB_ps_hash: {
8252 stb_ps_hash *h = GetHash(ps);
8253 for (i=0; i < h->count; ++i)
8254 if (!stb_ps_empty((size_t)h->table[i]))
8255 if (!func(h->table[i], data))
8256 return STB_FALSE;
8257 return STB_TRUE;
8258 }
8259 }
8260 return STB_TRUE; /* NOTREACHED */
8261 }
8262
8263 int stb_ps_count (stb_ps *ps)
8264 {
8265 switch (3 & (int)(size_t) ps) {
8266 case STB_ps_direct:
8267 return ps != NULL;
8268 case STB_ps_bucket: {
8269 stb_ps_bucket *b = GetBucket(ps);
8270 return (b->p[0] != NULL) + (b->p[1] != NULL) +
8271 (b->p[2] != NULL) + (b->p[3] != NULL);
8272 }
8273 case STB_ps_array: {
8274 stb_ps_array *a = GetArray(ps);
8275 return a->count;
8276 }
8277 case STB_ps_hash: {
8278 stb_ps_hash *h = GetHash(ps);
8279 return h->count;
8280 }
8281 }
8282 return 0;
8283 }
8284
8285 void ** stb_ps_fastlist(stb_ps *ps, int *count)
8286 {
8287 static void *storage;
8288
8289 switch (3 & (int)(size_t) ps) {
8290 case STB_ps_direct:
8291 if (ps == NULL) { *count = 0; return NULL; }
8292 storage = ps;
8293 *count = 1;
8294 return &storage;
8295 case STB_ps_bucket: {
8296 stb_ps_bucket *b = GetBucket(ps);
8297 *count = STB_BUCKET_SIZE;
8298 return b->p;
8299 }
8300 case STB_ps_array: {
8301 stb_ps_array *a = GetArray(ps);
8302 *count = a->count;
8303 return a->p;
8304 }
8305 case STB_ps_hash: {
8306 stb_ps_hash *h = GetHash(ps);
8307 *count = h->size;
8308 return h->table;
8309 }
8310 }
8311 return NULL; /* NOTREACHED */
8312 }
8313
8314 int stb_ps_subset(stb_ps *bigger, stb_ps *smaller)
8315 {
8316 int i, listlen;
8317 void **list = stb_ps_fastlist(smaller, &listlen);
8318 for(i=0; i < listlen; ++i)
8319 if (stb_ps_fastlist_valid(list[i]))
8320 if (!stb_ps_find(bigger, list[i]))
8321 return 0;
8322 return 1;
8323 }
8324
8325 int stb_ps_eq(stb_ps *p0, stb_ps *p1)
8326 {
8327 if (stb_ps_count(p0) != stb_ps_count(p1))
8328 return 0;
8329 return stb_ps_subset(p0, p1);
8330 }
8331
8332 #undef GetBucket
8333 #undef GetArray
8334 #undef GetHash
8335
8336 #undef EncodeBucket
8337 #undef EncodeArray
8338 #undef EncodeHash
8339
8340 #endif
8341
8342
8343 //////////////////////////////////////////////////////////////////////////////
8344 //
8345 // Random Numbers via Meresenne Twister or LCG
8346 //
8347
8348 STB_EXTERN unsigned int stb_srandLCG(unsigned int seed);
8349 STB_EXTERN unsigned int stb_randLCG(void);
8350 STB_EXTERN double stb_frandLCG(void);
8351
8352 STB_EXTERN void stb_srand(unsigned int seed);
8353 STB_EXTERN unsigned int stb_rand(void);
8354 STB_EXTERN double stb_frand(void);
8355 STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz,
8356 unsigned int seed);
8357 STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz);
8358
8359 STB_EXTERN unsigned int stb_randLCG_explicit(unsigned int seed);
8360
8361 #define stb_rand_define(x,y) \
8362 \
8363 unsigned int x(void) \
8364 { \
8365 static unsigned int stb__rand = y; \
8366 stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \
8367 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \
8368 }
8369
8370 #ifdef STB_DEFINE
8371 unsigned int stb_randLCG_explicit(unsigned int seed)
8372 {
8373 return seed * 2147001325 + 715136305;
8374 }
8375
8376 static unsigned int stb__rand_seed=0;
8377
8378 unsigned int stb_srandLCG(unsigned int seed)
8379 {
8380 unsigned int previous = stb__rand_seed;
8381 stb__rand_seed = seed;
8382 return previous;
8383 }
8384
8385 unsigned int stb_randLCG(void)
8386 {
8387 stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator
8388 // shuffle non-random bits to the middle, and xor to decorrelate with seed
8389 return 0x31415926 ^ ((stb__rand_seed >> 16) + (stb__rand_seed << 16));
8390 }
8391
8392 double stb_frandLCG(void)
8393 {
8394 return stb_randLCG() / ((double) (1 << 16) * (1 << 16));
8395 }
8396
8397 void stb_shuffle(void *p, size_t n, size_t sz, unsigned int seed)
8398 {
8399 char *a;
8400 unsigned int old_seed;
8401 int i;
8402 if (seed)
8403 old_seed = stb_srandLCG(seed);
8404 a = (char *) p + (n-1) * sz;
8405
8406 for (i=(int) n; i > 1; --i) {
8407 int j = stb_randLCG() % i;
8408 stb_swap(a, (char *) p + j * sz, sz);
8409 a -= sz;
8410 }
8411 if (seed)
8412 stb_srandLCG(old_seed);
8413 }
8414
8415 void stb_reverse(void *p, size_t n, size_t sz)
8416 {
8417 size_t i,j = n-1;
8418 for (i=0; i < j; ++i,--j) {
8419 stb_swap((char *) p + i * sz, (char *) p + j * sz, sz);
8420 }
8421 }
8422
8423 // public domain Mersenne Twister by Michael Brundage
8424 #define STB__MT_LEN 624
8425
8426 int stb__mt_index = STB__MT_LEN*sizeof(int)+1;
8427 unsigned int stb__mt_buffer[STB__MT_LEN];
8428
8429 void stb_srand(unsigned int seed)
8430 {
8431 int i;
8432 unsigned int old = stb_srandLCG(seed);
8433 for (i = 0; i < STB__MT_LEN; i++)
8434 stb__mt_buffer[i] = stb_randLCG();
8435 stb_srandLCG(old);
8436 stb__mt_index = STB__MT_LEN*sizeof(unsigned int);
8437 }
8438
8439 #define STB__MT_IA 397
8440 #define STB__MT_IB (STB__MT_LEN - STB__MT_IA)
8441 #define STB__UPPER_MASK 0x80000000
8442 #define STB__LOWER_MASK 0x7FFFFFFF
8443 #define STB__MATRIX_A 0x9908B0DF
8444 #define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK)
8445 #define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A)
8446
8447 unsigned int stb_rand()
8448 {
8449 unsigned int * b = stb__mt_buffer;
8450 int idx = stb__mt_index;
8451 unsigned int s,r;
8452 int i;
8453
8454 if (idx >= STB__MT_LEN*sizeof(unsigned int)) {
8455 if (idx > STB__MT_LEN*sizeof(unsigned int))
8456 stb_srand(0);
8457 idx = 0;
8458 i = 0;
8459 for (; i < STB__MT_IB; i++) {
8460 s = STB__TWIST(b, i, i+1);
8461 b[i] = b[i + STB__MT_IA] ^ (s >> 1) ^ STB__MAGIC(s);
8462 }
8463 for (; i < STB__MT_LEN-1; i++) {
8464 s = STB__TWIST(b, i, i+1);
8465 b[i] = b[i - STB__MT_IB] ^ (s >> 1) ^ STB__MAGIC(s);
8466 }
8467
8468 s = STB__TWIST(b, STB__MT_LEN-1, 0);
8469 b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s);
8470 }
8471 stb__mt_index = idx + sizeof(unsigned int);
8472
8473 r = *(unsigned int *)((unsigned char *)b + idx);
8474
8475 r ^= (r >> 11);
8476 r ^= (r << 7) & 0x9D2C5680;
8477 r ^= (r << 15) & 0xEFC60000;
8478 r ^= (r >> 18);
8479
8480 return r;
8481 }
8482
8483 double stb_frand(void)
8484 {
8485 return stb_rand() / ((double) (1 << 16) * (1 << 16));
8486 }
8487
8488 #endif
8489
8490
8491 //////////////////////////////////////////////////////////////////////////////
8492 //
8493 // stb_dupe
8494 //
8495 // stb_dupe is a duplicate-finding system for very, very large data
8496 // structures--large enough that sorting is too slow, but not so large
8497 // that we can't keep all the data in memory. using it works as follows:
8498 //
8499 // 1. create an stb_dupe:
8500 // provide a hash function
8501 // provide an equality function
8502 // provide an estimate for the size
8503 // optionally provide a comparison function
8504 //
8505 // 2. traverse your data, 'adding' pointers to the stb_dupe
8506 //
8507 // 3. finish and ask for duplicates
8508 //
8509 // the stb_dupe will discard its intermediate data and build
8510 // a collection of sorted lists of duplicates, with non-duplicate
8511 // entries omitted entirely
8512 //
8513 //
8514 // Implementation strategy:
8515 //
8516 // while collecting the N items, we keep a hash table of approximate
8517 // size sqrt(N). (if you tell use the N up front, the hash table is
8518 // just that size exactly)
8519 //
8520 // each entry in the hash table is just an stb__arr of pointers (no need
8521 // to use stb_ps, because we don't need to delete from these)
8522 //
8523 // for step 3, for each entry in the hash table, we apply stb_dupe to it
8524 // recursively. once the size gets small enough (or doesn't decrease
8525 // significantly), we switch to either using qsort() on the comparison
8526 // function, or else we just do the icky N^2 gather
8527
8528
8529 typedef struct stb_dupe stb_dupe;
8530
8531 typedef int (*stb_compare_func)(void *a, void *b);
8532 typedef int (*stb_hash_func)(void *a, unsigned int seed);
8533
8534 STB_EXTERN void stb_dupe_free(stb_dupe *sd);
8535 STB_EXTERN stb_dupe *stb_dupe_create(stb_hash_func hash,
8536 stb_compare_func eq, int size, stb_compare_func ineq);
8537 STB_EXTERN void stb_dupe_add(stb_dupe *sd, void *item);
8538 STB_EXTERN void stb_dupe_finish(stb_dupe *sd);
8539 STB_EXTERN int stb_dupe_numsets(stb_dupe *sd);
8540 STB_EXTERN void **stb_dupe_set(stb_dupe *sd, int num);
8541 STB_EXTERN int stb_dupe_set_count(stb_dupe *sd, int num);
8542
8543 struct stb_dupe
8544 {
8545 void ***hash_table;
8546 int hash_size;
8547 int size_log2;
8548 int population;
8549
8550 int hash_shift;
8551 stb_hash_func hash;
8552
8553 stb_compare_func eq;
8554 stb_compare_func ineq;
8555
8556 void ***dupes;
8557 };
8558
8559 #ifdef STB_DEFINE
8560
8561 int stb_dupe_numsets(stb_dupe *sd)
8562 {
8563 assert(sd->hash_table == NULL);
8564 return stb_arr_len(sd->dupes);
8565 }
8566
8567 void **stb_dupe_set(stb_dupe *sd, int num)
8568 {
8569 assert(sd->hash_table == NULL);
8570 return sd->dupes[num];
8571 }
8572
8573 int stb_dupe_set_count(stb_dupe *sd, int num)
8574 {
8575 assert(sd->hash_table == NULL);
8576 return stb_arr_len(sd->dupes[num]);
8577 }
8578
8579 stb_dupe *stb_dupe_create(stb_hash_func hash, stb_compare_func eq, int size,
8580 stb_compare_func ineq)
8581 {
8582 int i, hsize;
8583 stb_dupe *sd = (stb_dupe *) malloc(sizeof(*sd));
8584
8585 sd->size_log2 = 4;
8586 hsize = 1 << sd->size_log2;
8587 while (hsize * hsize < size) {
8588 ++sd->size_log2;
8589 hsize *= 2;
8590 }
8591
8592 sd->hash = hash;
8593 sd->eq = eq;
8594 sd->ineq = ineq;
8595 sd->hash_shift = 0;
8596
8597 sd->population = 0;
8598 sd->hash_size = hsize;
8599 sd->hash_table = (void ***) malloc(sizeof(*sd->hash_table) * hsize);
8600 for (i=0; i < hsize; ++i)
8601 sd->hash_table[i] = NULL;
8602
8603 sd->dupes = NULL;
8604
8605 return sd;
8606 }
8607
8608 void stb_dupe_add(stb_dupe *sd, void *item)
8609 {
8610 stb_uint32 hash = sd->hash(item, sd->hash_shift);
8611 int z = hash & (sd->hash_size-1);
8612 stb_arr_push(sd->hash_table[z], item);
8613 ++sd->population;
8614 }
8615
8616 void stb_dupe_free(stb_dupe *sd)
8617 {
8618 int i;
8619 for (i=0; i < stb_arr_len(sd->dupes); ++i)
8620 if (sd->dupes[i])
8621 stb_arr_free(sd->dupes[i]);
8622 stb_arr_free(sd->dupes);
8623 free(sd);
8624 }
8625
8626 static stb_compare_func stb__compare;
8627
8628 static int stb__dupe_compare(const void *a, const void *b)
8629 {
8630 void *p = *(void **) a;
8631 void *q = *(void **) b;
8632
8633 return stb__compare(p,q);
8634 }
8635
8636 void stb_dupe_finish(stb_dupe *sd)
8637 {
8638 int i,j,k;
8639 assert(sd->dupes == NULL);
8640 for (i=0; i < sd->hash_size; ++i) {
8641 void ** list = sd->hash_table[i];
8642 if (list != NULL) {
8643 int n = stb_arr_len(list);
8644 // @TODO: measure to find good numbers instead of just making them up!
8645 int thresh = (sd->ineq ? 200 : 20);
8646 // if n is large enough to be worth it, and n is smaller than
8647 // before (so we can guarantee we'll use a smaller hash table);
8648 // and there are enough hash bits left, assuming full 32-bit hash
8649 if (n > thresh && n < (sd->population >> 3) && sd->hash_shift + sd->size_log2*2 < 32) {
8650
8651 // recursively process this row using stb_dupe, O(N log log N)
8652
8653 stb_dupe *d = stb_dupe_create(sd->hash, sd->eq, n, sd->ineq);
8654 d->hash_shift = stb_randLCG_explicit(sd->hash_shift);
8655 for (j=0; j < n; ++j)
8656 stb_dupe_add(d, list[j]);
8657 stb_arr_free(sd->hash_table[i]);
8658 stb_dupe_finish(d);
8659 for (j=0; j < stb_arr_len(d->dupes); ++j) {
8660 stb_arr_push(sd->dupes, d->dupes[j]);
8661 d->dupes[j] = NULL; // take over ownership
8662 }
8663 stb_dupe_free(d);
8664
8665 } else if (sd->ineq) {
8666
8667 // process this row using qsort(), O(N log N)
8668 stb__compare = sd->ineq;
8669 qsort(list, n, sizeof(list[0]), stb__dupe_compare);
8670
8671 // find equal subsequences of the list
8672 for (j=0; j < n-1; ) {
8673 // find a subsequence from j..k
8674 for (k=j; k < n; ++k)
8675 // only use ineq so eq can be left undefined
8676 if (sd->ineq(list[j], list[k]))
8677 break;
8678 // k is the first one not in the subsequence
8679 if (k-j > 1) {
8680 void **mylist = NULL;
8681 stb_arr_setlen(mylist, k-j);
8682 memcpy(mylist, list+j, sizeof(list[j]) * (k-j));
8683 stb_arr_push(sd->dupes, mylist);
8684 }
8685 j = k;
8686 }
8687 stb_arr_free(sd->hash_table[i]);
8688 } else {
8689
8690 // process this row using eq(), O(N^2)
8691 for (j=0; j < n; ++j) {
8692 if (list[j] != NULL) {
8693 void **output = NULL;
8694 for (k=j+1; k < n; ++k) {
8695 if (sd->eq(list[j], list[k])) {
8696 if (output == NULL)
8697 stb_arr_push(output, list[j]);
8698 stb_arr_push(output, list[k]);
8699 list[k] = NULL;
8700 }
8701 }
8702 list[j] = NULL;
8703 if (output)
8704 stb_arr_push(sd->dupes, output);
8705 }
8706 }
8707 stb_arr_free(sd->hash_table[i]);
8708 }
8709 }
8710 }
8711 free(sd->hash_table);
8712 sd->hash_table = NULL;
8713 }
8714 #endif
8715
8716 //////////////////////////////////////////////////////////////////////////////
8717 //
8718 // templatized Sort routine
8719 //
8720 // This is an attempt to implement a templated sorting algorithm.
8721 // To use it, you have to explicitly instantiate it as a _function_,
8722 // then you call that function. This allows the comparison to be inlined,
8723 // giving the sort similar performance to C++ sorts.
8724 //
8725 // It implements quicksort with three-way-median partitioning (generally
8726 // well-behaved), with a final insertion sort pass.
8727 //
8728 // When you define the compare expression, you should assume you have
8729 // elements of your array pointed to by 'a' and 'b', and perform the comparison
8730 // on those. OR you can use one or more statements; first say '0;', then
8731 // write whatever code you want, and compute the result into a variable 'c'.
8732
8733 #define stb_declare_sort(FUNCNAME, TYPE) \
8734 void FUNCNAME(TYPE *p, int n)
8735 #define stb_define_sort(FUNCNAME,TYPE,COMPARE) \
8736 stb__define_sort( void, FUNCNAME,TYPE,COMPARE)
8737 #define stb_define_sort_static(FUNCNAME,TYPE,COMPARE) \
8738 stb__define_sort(static void, FUNCNAME,TYPE,COMPARE)
8739
8740 #define stb__define_sort(MODE, FUNCNAME, TYPE, COMPARE) \
8741 \
8742 static void STB_(FUNCNAME,_ins_sort)(TYPE *p, int n) \
8743 { \
8744 int i,j; \
8745 for (i=1; i < n; ++i) { \
8746 TYPE t = p[i], *a = &t; \
8747 j = i; \
8748 while (j > 0) { \
8749 TYPE *b = &p[j-1]; \
8750 int c = COMPARE; \
8751 if (!c) break; \
8752 p[j] = p[j-1]; \
8753 --j; \
8754 } \
8755 if (i != j) \
8756 p[j] = t; \
8757 } \
8758 } \
8759 \
8760 static void STB_(FUNCNAME,_quicksort)(TYPE *p, int n) \
8761 { \
8762 /* threshold for transitioning to insertion sort */ \
8763 while (n > 12) { \
8764 TYPE *a,*b,t; \
8765 int c01,c12,c,m,i,j; \
8766 \
8767 /* compute median of three */ \
8768 m = n >> 1; \
8769 a = &p[0]; \
8770 b = &p[m]; \
8771 c = COMPARE; \
8772 c01 = c; \
8773 a = &p[m]; \
8774 b = &p[n-1]; \
8775 c = COMPARE; \
8776 c12 = c; \
8777 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ \
8778 if (c01 != c12) { \
8779 /* otherwise, we'll need to swap something else to middle */ \
8780 int z; \
8781 a = &p[0]; \
8782 b = &p[n-1]; \
8783 c = COMPARE; \
8784 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ \
8785 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ \
8786 z = (c == c12) ? 0 : n-1; \
8787 t = p[z]; \
8788 p[z] = p[m]; \
8789 p[m] = t; \
8790 } \
8791 /* now p[m] is the median-of-three */ \
8792 /* swap it to the beginning so it won't move around */ \
8793 t = p[0]; \
8794 p[0] = p[m]; \
8795 p[m] = t; \
8796 \
8797 /* partition loop */ \
8798 i=1; \
8799 j=n-1; \
8800 for(;;) { \
8801 /* handling of equality is crucial here */ \
8802 /* for sentinels & efficiency with duplicates */ \
8803 b = &p[0]; \
8804 for (;;++i) { \
8805 a=&p[i]; \
8806 c = COMPARE; \
8807 if (!c) break; \
8808 } \
8809 a = &p[0]; \
8810 for (;;--j) { \
8811 b=&p[j]; \
8812 c = COMPARE; \
8813 if (!c) break; \
8814 } \
8815 /* make sure we haven't crossed */ \
8816 if (i >= j) break; \
8817 t = p[i]; \
8818 p[i] = p[j]; \
8819 p[j] = t; \
8820 \
8821 ++i; \
8822 --j; \
8823 } \
8824 /* recurse on smaller side, iterate on larger */ \
8825 if (j < (n-i)) { \
8826 STB_(FUNCNAME,_quicksort)(p,j); \
8827 p = p+i; \
8828 n = n-i; \
8829 } else { \
8830 STB_(FUNCNAME,_quicksort)(p+i, n-i); \
8831 n = j; \
8832 } \
8833 } \
8834 } \
8835 \
8836 MODE FUNCNAME(TYPE *p, int n) \
8837 { \
8838 STB_(FUNCNAME, _quicksort)(p, n); \
8839 STB_(FUNCNAME, _ins_sort)(p, n); \
8840 } \
8841
8842
8843 //////////////////////////////////////////////////////////////////////////////
8844 //
8845 // stb_bitset an array of booleans indexed by integers
8846 //
8847
8848 typedef stb_uint32 stb_bitset;
8849
8850 STB_EXTERN stb_bitset *stb_bitset_new(int value, int len);
8851
8852 #define stb_bitset_clearall(arr,len) (memset(arr, 0, 4 * (len)))
8853 #define stb_bitset_setall(arr,len) (memset(arr, 255, 4 * (len)))
8854
8855 #define stb_bitset_setbit(arr,n) ((arr)[(n) >> 5] |= (1 << (n & 31)))
8856 #define stb_bitset_clearbit(arr,n) ((arr)[(n) >> 5] &= ~(1 << (n & 31)))
8857 #define stb_bitset_testbit(arr,n) ((arr)[(n) >> 5] & (1 << (n & 31)))
8858
8859 STB_EXTERN stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len);
8860
8861 STB_EXTERN int *stb_bitset_getlist(stb_bitset *out, int start, int end);
8862
8863 STB_EXTERN int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len);
8864 STB_EXTERN int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len);
8865 STB_EXTERN int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len);
8866 STB_EXTERN int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len);
8867 STB_EXTERN int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len);
8868
8869 #ifdef STB_DEFINE
8870 int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len)
8871 {
8872 int i;
8873 for (i=0; i < len; ++i)
8874 if (p0[i] != p1[i]) return 0;
8875 return 1;
8876 }
8877
8878 int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len)
8879 {
8880 int i;
8881 for (i=0; i < len; ++i)
8882 if (p0[i] & p1[i]) return 0;
8883 return 1;
8884 }
8885
8886 int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len)
8887 {
8888 int i;
8889 for (i=0; i < len; ++i)
8890 if ((p0[i] | p1[i]) != 0xffffffff) return 0;
8891 return 1;
8892 }
8893
8894 int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len)
8895 {
8896 int i;
8897 for (i=0; i < len; ++i)
8898 if ((bigger[i] & smaller[i]) != smaller[i]) return 0;
8899 return 1;
8900 }
8901
8902 stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len)
8903 {
8904 int i;
8905 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8906 for (i=0; i < len; ++i) d[i] = p0[i] | p1[i];
8907 return d;
8908 }
8909
8910 int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len)
8911 {
8912 int i, changed=0;
8913 for (i=0; i < len; ++i) {
8914 stb_bitset d = p0[i] | p1[i];
8915 if (d != p0[i]) {
8916 p0[i] = d;
8917 changed = 1;
8918 }
8919 }
8920 return changed;
8921 }
8922
8923 stb_bitset *stb_bitset_new(int value, int len)
8924 {
8925 int i;
8926 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8927 if (value) value = 0xffffffff;
8928 for (i=0; i < len; ++i) d[i] = value;
8929 return d;
8930 }
8931
8932 int *stb_bitset_getlist(stb_bitset *out, int start, int end)
8933 {
8934 int *list = NULL;
8935 int i;
8936 for (i=start; i < end; ++i)
8937 if (stb_bitset_testbit(out, i))
8938 stb_arr_push(list, i);
8939 return list;
8940 }
8941 #endif
8942
8943 //////////////////////////////////////////////////////////////////////////////
8944 //
8945 // stb_wordwrap quality word-wrapping for fixed-width fonts
8946 //
8947
8948 STB_EXTERN int stb_wordwrap(int *pairs, int pair_max, int count, char *str);
8949 STB_EXTERN int *stb_wordwrapalloc(int count, char *str);
8950
8951 #ifdef STB_DEFINE
8952
8953 int stb_wordwrap(int *pairs, int pair_max, int count, char *str)
8954 {
8955 int n=0,i=0, start=0,nonwhite=0;
8956 if (pairs == NULL) pair_max = 0x7ffffff0;
8957 else pair_max *= 2;
8958 // parse
8959 for(;;) {
8960 int s=i; // first whitespace char; last nonwhite+1
8961 int w; // word start
8962 // accept whitespace
8963 while (isspace(str[i])) {
8964 if (str[i] == '\n' || str[i] == '\r') {
8965 if (str[i] + str[i+1] == '\n' + '\r') ++i;
8966 if (n >= pair_max) return -1;
8967 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8968 n += 2;
8969 nonwhite=0;
8970 start = i+1;
8971 s = start;
8972 }
8973 ++i;
8974 }
8975 if (i >= start+count) {
8976 // we've gone off the end using whitespace
8977 if (nonwhite) {
8978 if (n >= pair_max) return -1;
8979 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8980 n += 2;
8981 start = s = i;
8982 nonwhite=0;
8983 } else {
8984 // output all the whitespace
8985 while (i >= start+count) {
8986 if (n >= pair_max) return -1;
8987 if (pairs) pairs[n] = start, pairs[n+1] = count;
8988 n += 2;
8989 start += count;
8990 }
8991 s = start;
8992 }
8993 }
8994
8995 if (str[i] == 0) break;
8996 // now scan out a word and see if it fits
8997 w = i;
8998 while (str[i] && !isspace(str[i])) {
8999 ++i;
9000 }
9001 // wrapped?
9002 if (i > start + count) {
9003 // huge?
9004 if (i-s <= count) {
9005 if (n >= pair_max) return -1;
9006 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
9007 n += 2;
9008 start = w;
9009 } else {
9010 // This word is longer than one line. If we wrap it onto N lines
9011 // there are leftover chars. do those chars fit on the cur line?
9012 // But if we have leading whitespace, we force it to start here.
9013 if ((w-start) + ((i-w) % count) <= count || !nonwhite) {
9014 // output a full line
9015 if (n >= pair_max) return -1;
9016 if (pairs) pairs[n] = start, pairs[n+1] = count;
9017 n += 2;
9018 start += count;
9019 w = start;
9020 } else {
9021 // output a partial line, trimming trailing whitespace
9022 if (s != start) {
9023 if (n >= pair_max) return -1;
9024 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
9025 n += 2;
9026 start = w;
9027 }
9028 }
9029 // now output full lines as needed
9030 while (start + count <= i) {
9031 if (n >= pair_max) return -1;
9032 if (pairs) pairs[n] = start, pairs[n+1] = count;
9033 n += 2;
9034 start += count;
9035 }
9036 }
9037 }
9038 nonwhite=1;
9039 }
9040 if (start < i) {
9041 if (n >= pair_max) return -1;
9042 if (pairs) pairs[n] = start, pairs[n+1] = i-start;
9043 n += 2;
9044 }
9045 return n>>1;
9046 }
9047
9048 int *stb_wordwrapalloc(int count, char *str)
9049 {
9050 int n = stb_wordwrap(NULL,0,count,str);
9051 int *z = NULL;
9052 stb_arr_setlen(z, n*2);
9053 stb_wordwrap(z, n, count, str);
9054 return z;
9055 }
9056 #endif
9057
9058
9059 //////////////////////////////////////////////////////////////////////////////
9060 //
9061 // stb_match: wildcards and regexping
9062 //
9063
9064 STB_EXTERN int stb_wildmatch (char *expr, char *candidate);
9065 STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
9066 STB_EXTERN int stb_wildfind (char *expr, char *candidate);
9067 STB_EXTERN int stb_wildfindi (char *expr, char *candidate);
9068
9069 STB_EXTERN int stb_regex(char *regex, char *candidate);
9070
9071 typedef struct stb_matcher stb_matcher;
9072
9073 STB_EXTERN stb_matcher *stb_regex_matcher(char *regex);
9074 STB_EXTERN int stb_matcher_match(stb_matcher *m, char *str);
9075 STB_EXTERN int stb_matcher_find(stb_matcher *m, char *str);
9076 STB_EXTERN void stb_matcher_free(stb_matcher *f);
9077
9078 STB_EXTERN stb_matcher *stb_lex_matcher(void);
9079 STB_EXTERN int stb_lex_item(stb_matcher *m, const char *str, int result);
9080 STB_EXTERN int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result);
9081 STB_EXTERN int stb_lex(stb_matcher *m, char *str, int *len);
9082
9083
9084
9085 #ifdef STB_DEFINE
9086
9087 static int stb__match_qstring(char *candidate, char *qstring, int qlen, int insensitive)
9088 {
9089 int i;
9090 if (insensitive) {
9091 for (i=0; i < qlen; ++i)
9092 if (qstring[i] == '?') {
9093 if (!candidate[i]) return 0;
9094 } else
9095 if (tolower(qstring[i]) != tolower(candidate[i]))
9096 return 0;
9097 } else {
9098 for (i=0; i < qlen; ++i)
9099 if (qstring[i] == '?') {
9100 if (!candidate[i]) return 0;
9101 } else
9102 if (qstring[i] != candidate[i])
9103 return 0;
9104 }
9105 return 1;
9106 }
9107
9108 static int stb__find_qstring(char *candidate, char *qstring, int qlen, int insensitive)
9109 {
9110 char c;
9111
9112 int offset=0;
9113 while (*qstring == '?') {
9114 ++qstring;
9115 --qlen;
9116 ++candidate;
9117 if (qlen == 0) return 0;
9118 if (*candidate == 0) return -1;
9119 }
9120
9121 c = *qstring++;
9122 --qlen;
9123 if (insensitive) c = tolower(c);
9124
9125 while (candidate[offset]) {
9126 if (c == (insensitive ? tolower(candidate[offset]) : candidate[offset]))
9127 if (stb__match_qstring(candidate+offset+1, qstring, qlen, insensitive))
9128 return offset;
9129 ++offset;
9130 }
9131
9132 return -1;
9133 }
9134
9135 int stb__wildmatch_raw2(char *expr, char *candidate, int search, int insensitive)
9136 {
9137 int where=0;
9138 int start = -1;
9139
9140 if (!search) {
9141 // parse to first '*'
9142 if (*expr != '*')
9143 start = 0;
9144 while (*expr != '*') {
9145 if (!*expr)
9146 return *candidate == 0 ? 0 : -1;
9147 if (*expr == '?') {
9148 if (!*candidate) return -1;
9149 } else {
9150 if (insensitive) {
9151 if (tolower(*candidate) != tolower(*expr))
9152 return -1;
9153 } else
9154 if (*candidate != *expr)
9155 return -1;
9156 }
9157 ++candidate, ++expr, ++where;
9158 }
9159 } else {
9160 // 0-length search string
9161 if (!*expr)
9162 return 0;
9163 }
9164
9165 assert(search || *expr == '*');
9166 if (!search)
9167 ++expr;
9168
9169 // implicit '*' at this point
9170
9171 while (*expr) {
9172 int o=0;
9173 // combine redundant * characters
9174 while (expr[0] == '*') ++expr;
9175
9176 // ok, at this point, expr[-1] == '*',
9177 // and expr[0] != '*'
9178
9179 if (!expr[0]) return start >= 0 ? start : 0;
9180
9181 // now find next '*'
9182 o = 0;
9183 while (expr[o] != '*') {
9184 if (expr[o] == 0)
9185 break;
9186 ++o;
9187 }
9188 // if no '*', scan to end, then match at end
9189 if (expr[o] == 0 && !search) {
9190 int z;
9191 for (z=0; z < o; ++z)
9192 if (candidate[z] == 0)
9193 return -1;
9194 while (candidate[z])
9195 ++z;
9196 // ok, now check if they match
9197 if (stb__match_qstring(candidate+z-o, expr, o, insensitive))
9198 return start >= 0 ? start : 0;
9199 return -1;
9200 } else {
9201 // if yes '*', then do stb__find_qmatch on the intervening chars
9202 int n = stb__find_qstring(candidate, expr, o, insensitive);
9203 if (n < 0)
9204 return -1;
9205 if (start < 0)
9206 start = where + n;
9207 expr += o;
9208 candidate += n+o;
9209 }
9210
9211 if (*expr == 0) {
9212 assert(search);
9213 return start;
9214 }
9215
9216 assert(*expr == '*');
9217 ++expr;
9218 }
9219
9220 return start >= 0 ? start : 0;
9221 }
9222
9223 int stb__wildmatch_raw(char *expr, char *candidate, int search, int insensitive)
9224 {
9225 char buffer[256];
9226 // handle multiple search strings
9227 char *s = strchr(expr, ';');
9228 char *last = expr;
9229 while (s) {
9230 int z;
9231 // need to allow for non-writeable strings... assume they're small
9232 if (s - last < 256) {
9233 stb_strncpy(buffer, last, (int) (s-last+1));
9234 z = stb__wildmatch_raw2(buffer, candidate, search, insensitive);
9235 } else {
9236 *s = 0;
9237 z = stb__wildmatch_raw2(last, candidate, search, insensitive);
9238 *s = ';';
9239 }
9240 if (z >= 0) return z;
9241 last = s+1;
9242 s = strchr(last, ';');
9243 }
9244 return stb__wildmatch_raw2(last, candidate, search, insensitive);
9245 }
9246
9247 int stb_wildmatch(char *expr, char *candidate)
9248 {
9249 return stb__wildmatch_raw(expr, candidate, 0,0) >= 0;
9250 }
9251
9252 int stb_wildmatchi(char *expr, char *candidate)
9253 {
9254 return stb__wildmatch_raw(expr, candidate, 0,1) >= 0;
9255 }
9256
9257 int stb_wildfind(char *expr, char *candidate)
9258 {
9259 return stb__wildmatch_raw(expr, candidate, 1,0);
9260 }
9261
9262 int stb_wildfindi(char *expr, char *candidate)
9263 {
9264 return stb__wildmatch_raw(expr, candidate, 1,1);
9265 }
9266
9267 typedef struct
9268 {
9269 stb_int16 transition[256];
9270 } stb_dfa;
9271
9272 // an NFA node represents a state you're in; it then has
9273 // an arbitrary number of edges dangling off of it
9274 // note this isn't utf8-y
9275 typedef struct
9276 {
9277 stb_int16 match; // character/set to match
9278 stb_uint16 node; // output node to go to
9279 } stb_nfa_edge;
9280
9281 typedef struct
9282 {
9283 stb_int16 goal; // does reaching this win the prize?
9284 stb_uint8 active; // is this in the active list
9285 stb_nfa_edge *out;
9286 stb_uint16 *eps; // list of epsilon closures
9287 } stb_nfa_node;
9288
9289 #define STB__DFA_UNDEF -1
9290 #define STB__DFA_GOAL -2
9291 #define STB__DFA_END -3
9292 #define STB__DFA_MGOAL -4
9293 #define STB__DFA_VALID 0
9294
9295 #define STB__NFA_STOP_GOAL -1
9296
9297 // compiled regexp
9298 struct stb_matcher
9299 {
9300 stb_uint16 start_node;
9301 stb_int16 dfa_start;
9302 stb_uint32 *charset;
9303 int num_charset;
9304 int match_start;
9305 stb_nfa_node *nodes;
9306 int does_lex;
9307
9308 // dfa matcher
9309 stb_dfa * dfa;
9310 stb_uint32 * dfa_mapping;
9311 stb_int16 * dfa_result;
9312 int num_words_per_dfa;
9313 };
9314
9315 static int stb__add_node(stb_matcher *matcher)
9316 {
9317 stb_nfa_node z;
9318 z.active = 0;
9319 z.eps = 0;
9320 z.goal = 0;
9321 z.out = 0;
9322 stb_arr_push(matcher->nodes, z);
9323 return stb_arr_len(matcher->nodes)-1;
9324 }
9325
9326 static void stb__add_epsilon(stb_matcher *matcher, int from, int to)
9327 {
9328 assert(from != to);
9329 if (matcher->nodes[from].eps == NULL)
9330 stb_arr_malloc((void **) &matcher->nodes[from].eps, matcher);
9331 stb_arr_push(matcher->nodes[from].eps, to);
9332 }
9333
9334 static void stb__add_edge(stb_matcher *matcher, int from, int to, int type)
9335 {
9336 stb_nfa_edge z = { (stb_int16)type, (stb_uint16)to };
9337 if (matcher->nodes[from].out == NULL)
9338 stb_arr_malloc((void **) &matcher->nodes[from].out, matcher);
9339 stb_arr_push(matcher->nodes[from].out, z);
9340 }
9341
9342 static char *stb__reg_parse_alt(stb_matcher *m, int s, char *r, stb_uint16 *e);
9343 static char *stb__reg_parse(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9344 {
9345 int n;
9346 int last_start = -1;
9347 stb_uint16 last_end = start;
9348
9349 while (*regex) {
9350 switch (*regex) {
9351 case '(':
9352 last_start = last_end;
9353 regex = stb__reg_parse_alt(matcher, last_end, regex+1, &last_end);
9354 if (regex == NULL || *regex != ')')
9355 return NULL;
9356 ++regex;
9357 break;
9358
9359 case '|':
9360 case ')':
9361 *end = last_end;
9362 return regex;
9363
9364 case '?':
9365 if (last_start < 0) return NULL;
9366 stb__add_epsilon(matcher, last_start, last_end);
9367 ++regex;
9368 break;
9369
9370 case '*':
9371 if (last_start < 0) return NULL;
9372 stb__add_epsilon(matcher, last_start, last_end);
9373
9374 // fall through
9375
9376 case '+':
9377 if (last_start < 0) return NULL;
9378 stb__add_epsilon(matcher, last_end, last_start);
9379 // prevent links back to last_end from chaining to last_start
9380 n = stb__add_node(matcher);
9381 stb__add_epsilon(matcher, last_end, n);
9382 last_end = n;
9383 ++regex;
9384 break;
9385
9386 case '{': // not supported!
9387 // @TODO: given {n,m}, clone last_start to last_end m times,
9388 // and include epsilons from start to first m-n blocks
9389 return NULL;
9390
9391 case '\\':
9392 ++regex;
9393 if (!*regex) return NULL;
9394
9395 // fallthrough
9396 default: // match exactly this character
9397 n = stb__add_node(matcher);
9398 stb__add_edge(matcher, last_end, n, *regex);
9399 last_start = last_end;
9400 last_end = n;
9401 ++regex;
9402 break;
9403
9404 case '$':
9405 n = stb__add_node(matcher);
9406 stb__add_edge(matcher, last_end, n, '\n');
9407 last_start = last_end;
9408 last_end = n;
9409 ++regex;
9410 break;
9411
9412 case '.':
9413 n = stb__add_node(matcher);
9414 stb__add_edge(matcher, last_end, n, -1);
9415 last_start = last_end;
9416 last_end = n;
9417 ++regex;
9418 break;
9419
9420 case '[': {
9421 stb_uint8 flags[256];
9422 int invert = 0,z;
9423 ++regex;
9424 if (matcher->num_charset == 0) {
9425 matcher->charset = (stb_uint *) stb_malloc(matcher, sizeof(*matcher->charset) * 256);
9426 memset(matcher->charset, 0, sizeof(*matcher->charset) * 256);
9427 }
9428
9429 memset(flags,0,sizeof(flags));
9430
9431 // leading ^ is special
9432 if (*regex == '^')
9433 ++regex, invert = 1;
9434
9435 // leading ] is special
9436 if (*regex == ']') {
9437 flags[(int) ']'] = 1;
9438 ++regex;
9439 }
9440 while (*regex != ']') {
9441 stb_uint a;
9442 if (!*regex) return NULL;
9443 a = *regex++;
9444 if (regex[0] == '-' && regex[1] != ']') {
9445 stb_uint i,b = regex[1];
9446 regex += 2;
9447 if (b == 0) return NULL;
9448 if (a > b) return NULL;
9449 for (i=a; i <= b; ++i)
9450 flags[i] = 1;
9451 } else
9452 flags[a] = 1;
9453 }
9454 ++regex;
9455 if (invert) {
9456 int i;
9457 for (i=0; i < 256; ++i)
9458 flags[i] = 1-flags[i];
9459 }
9460
9461 // now check if any existing charset matches
9462 for (z=0; z < matcher->num_charset; ++z) {
9463 int i, k[2] = { 0, 1 << z};
9464 for (i=0; i < 256; ++i) {
9465 unsigned int f = k[flags[i]];
9466 if ((matcher->charset[i] & k[1]) != f)
9467 break;
9468 }
9469 if (i == 256) break;
9470 }
9471
9472 if (z == matcher->num_charset) {
9473 int i;
9474 ++matcher->num_charset;
9475 if (matcher->num_charset > 32) {
9476 assert(0); /* NOTREACHED */
9477 return NULL; // too many charsets, oops
9478 }
9479 for (i=0; i < 256; ++i)
9480 if (flags[i])
9481 matcher->charset[i] |= (1 << z);
9482 }
9483
9484 n = stb__add_node(matcher);
9485 stb__add_edge(matcher, last_end, n, -2 - z);
9486 last_start = last_end;
9487 last_end = n;
9488 break;
9489 }
9490 }
9491 }
9492 *end = last_end;
9493 return regex;
9494 }
9495
9496 static char *stb__reg_parse_alt(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9497 {
9498 stb_uint16 last_end = start;
9499 stb_uint16 main_end;
9500
9501 int head, tail;
9502
9503 head = stb__add_node(matcher);
9504 stb__add_epsilon(matcher, start, head);
9505
9506 regex = stb__reg_parse(matcher, head, regex, &last_end);
9507 if (regex == NULL) return NULL;
9508 if (*regex == 0 || *regex == ')') {
9509 *end = last_end;
9510 return regex;
9511 }
9512
9513 main_end = last_end;
9514 tail = stb__add_node(matcher);
9515
9516 stb__add_epsilon(matcher, last_end, tail);
9517
9518 // start alternatives from the same starting node; use epsilon
9519 // transitions to combine their endings
9520 while(*regex && *regex != ')') {
9521 assert(*regex == '|');
9522 head = stb__add_node(matcher);
9523 stb__add_epsilon(matcher, start, head);
9524 regex = stb__reg_parse(matcher, head, regex+1, &last_end);
9525 if (regex == NULL)
9526 return NULL;
9527 stb__add_epsilon(matcher, last_end, tail);
9528 }
9529
9530 *end = tail;
9531 return regex;
9532 }
9533
9534 static char *stb__wild_parse(stb_matcher *matcher, int start, char *str, stb_uint16 *end)
9535 {
9536 int n;
9537 stb_uint16 last_end;
9538
9539 last_end = stb__add_node(matcher);
9540 stb__add_epsilon(matcher, start, last_end);
9541
9542 while (*str) {
9543 switch (*str) {
9544 // fallthrough
9545 default: // match exactly this character
9546 n = stb__add_node(matcher);
9547 if (toupper(*str) == tolower(*str)) {
9548 stb__add_edge(matcher, last_end, n, *str);
9549 } else {
9550 stb__add_edge(matcher, last_end, n, tolower(*str));
9551 stb__add_edge(matcher, last_end, n, toupper(*str));
9552 }
9553 last_end = n;
9554 ++str;
9555 break;
9556
9557 case '?':
9558 n = stb__add_node(matcher);
9559 stb__add_edge(matcher, last_end, n, -1);
9560 last_end = n;
9561 ++str;
9562 break;
9563
9564 case '*':
9565 n = stb__add_node(matcher);
9566 stb__add_edge(matcher, last_end, n, -1);
9567 stb__add_epsilon(matcher, last_end, n);
9568 stb__add_epsilon(matcher, n, last_end);
9569 last_end = n;
9570 ++str;
9571 break;
9572 }
9573 }
9574
9575 // now require end of string to match
9576 n = stb__add_node(matcher);
9577 stb__add_edge(matcher, last_end, n, 0);
9578 last_end = n;
9579
9580 *end = last_end;
9581 return str;
9582 }
9583
9584 static int stb__opt(stb_matcher *m, int n)
9585 {
9586 for(;;) {
9587 stb_nfa_node *p = &m->nodes[n];
9588 if (p->goal) return n;
9589 if (stb_arr_len(p->out)) return n;
9590 if (stb_arr_len(p->eps) != 1) return n;
9591 n = p->eps[0];
9592 }
9593 }
9594
9595 static void stb__optimize(stb_matcher *m)
9596 {
9597 // if the target of any edge is a node with exactly
9598 // one out-epsilon, shorten it
9599 int i,j;
9600 for (i=0; i < stb_arr_len(m->nodes); ++i) {
9601 stb_nfa_node *p = &m->nodes[i];
9602 for (j=0; j < stb_arr_len(p->out); ++j)
9603 p->out[j].node = stb__opt(m,p->out[j].node);
9604 for (j=0; j < stb_arr_len(p->eps); ++j)
9605 p->eps[j] = stb__opt(m,p->eps[j] );
9606 }
9607 m->start_node = stb__opt(m,m->start_node);
9608 }
9609
9610 void stb_matcher_free(stb_matcher *f)
9611 {
9612 stb_free(f);
9613 }
9614
9615 static stb_matcher *stb__alloc_matcher(void)
9616 {
9617 stb_matcher *matcher = (stb_matcher *) stb_malloc(0,sizeof(*matcher));
9618
9619 matcher->start_node = 0;
9620 stb_arr_malloc((void **) &matcher->nodes, matcher);
9621 matcher->num_charset = 0;
9622 matcher->match_start = 0;
9623 matcher->does_lex = 0;
9624
9625 matcher->dfa_start = STB__DFA_UNDEF;
9626 stb_arr_malloc((void **) &matcher->dfa, matcher);
9627 stb_arr_malloc((void **) &matcher->dfa_mapping, matcher);
9628 stb_arr_malloc((void **) &matcher->dfa_result, matcher);
9629
9630 stb__add_node(matcher);
9631
9632 return matcher;
9633 }
9634
9635 static void stb__lex_reset(stb_matcher *matcher)
9636 {
9637 // flush cached dfa data
9638 stb_arr_setlen(matcher->dfa, 0);
9639 stb_arr_setlen(matcher->dfa_mapping, 0);
9640 stb_arr_setlen(matcher->dfa_result, 0);
9641 matcher->dfa_start = STB__DFA_UNDEF;
9642 }
9643
9644 stb_matcher *stb_regex_matcher(char *regex)
9645 {
9646 char *z;
9647 stb_uint16 end;
9648 stb_matcher *matcher = stb__alloc_matcher();
9649 if (*regex == '^') {
9650 matcher->match_start = 1;
9651 ++regex;
9652 }
9653
9654 z = stb__reg_parse_alt(matcher, matcher->start_node, regex, &end);
9655
9656 if (!z || *z) {
9657 stb_free(matcher);
9658 return NULL;
9659 }
9660
9661 ((matcher->nodes)[(int) end]).goal = STB__NFA_STOP_GOAL;
9662
9663 return matcher;
9664 }
9665
9666 stb_matcher *stb_lex_matcher(void)
9667 {
9668 stb_matcher *matcher = stb__alloc_matcher();
9669
9670 matcher->match_start = 1;
9671 matcher->does_lex = 1;
9672
9673 return matcher;
9674 }
9675
9676 int stb_lex_item(stb_matcher *matcher, const char *regex, int result)
9677 {
9678 char *z;
9679 stb_uint16 end;
9680
9681 z = stb__reg_parse_alt(matcher, matcher->start_node, (char*) regex, &end);
9682
9683 if (z == NULL)
9684 return 0;
9685
9686 stb__lex_reset(matcher);
9687
9688 matcher->nodes[(int) end].goal = result;
9689 return 1;
9690 }
9691
9692 int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result)
9693 {
9694 char *z;
9695 stb_uint16 end;
9696
9697 z = stb__wild_parse(matcher, matcher->start_node, (char*) regex, &end);
9698
9699 if (z == NULL)
9700 return 0;
9701
9702 stb__lex_reset(matcher);
9703
9704 matcher->nodes[(int) end].goal = result;
9705 return 1;
9706 }
9707
9708 static void stb__clear(stb_matcher *m, stb_uint16 *list)
9709 {
9710 int i;
9711 for (i=0; i < stb_arr_len(list); ++i)
9712 m->nodes[(int) list[i]].active = 0;
9713 }
9714
9715 static int stb__clear_goalcheck(stb_matcher *m, stb_uint16 *list)
9716 {
9717 int i, t=0;
9718 for (i=0; i < stb_arr_len(list); ++i) {
9719 t += m->nodes[(int) list[i]].goal;
9720 m->nodes[(int) list[i]].active = 0;
9721 }
9722 return t;
9723 }
9724
9725 static stb_uint16 * stb__add_if_inactive(stb_matcher *m, stb_uint16 *list, int n)
9726 {
9727 if (!m->nodes[n].active) {
9728 stb_arr_push(list, n);
9729 m->nodes[n].active = 1;
9730 }
9731 return list;
9732 }
9733
9734 static stb_uint16 * stb__eps_closure(stb_matcher *m, stb_uint16 *list)
9735 {
9736 int i,n = stb_arr_len(list);
9737
9738 for(i=0; i < n; ++i) {
9739 stb_uint16 *e = m->nodes[(int) list[i]].eps;
9740 if (e) {
9741 int j,k = stb_arr_len(e);
9742 for (j=0; j < k; ++j)
9743 list = stb__add_if_inactive(m, list, e[j]);
9744 n = stb_arr_len(list);
9745 }
9746 }
9747
9748 return list;
9749 }
9750
9751 int stb_matcher_match(stb_matcher *m, char *str)
9752 {
9753 int result = 0;
9754 int i,j,y,z;
9755 stb_uint16 *previous = NULL;
9756 stb_uint16 *current = NULL;
9757 stb_uint16 *temp;
9758
9759 stb_arr_setsize(previous, 4);
9760 stb_arr_setsize(current, 4);
9761
9762 previous = stb__add_if_inactive(m, previous, m->start_node);
9763 previous = stb__eps_closure(m,previous);
9764 stb__clear(m, previous);
9765
9766 while (*str && stb_arr_len(previous)) {
9767 y = stb_arr_len(previous);
9768 for (i=0; i < y; ++i) {
9769 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9770 z = stb_arr_len(n->out);
9771 for (j=0; j < z; ++j) {
9772 if (n->out[j].match >= 0) {
9773 if (n->out[j].match == *str)
9774 current = stb__add_if_inactive(m, current, n->out[j].node);
9775 } else if (n->out[j].match == -1) {
9776 if (*str != '\n')
9777 current = stb__add_if_inactive(m, current, n->out[j].node);
9778 } else if (n->out[j].match < -1) {
9779 int z = -n->out[j].match - 2;
9780 if (m->charset[(stb_uint8) *str] & (1 << z))
9781 current = stb__add_if_inactive(m, current, n->out[j].node);
9782 }
9783 }
9784 }
9785 stb_arr_setlen(previous, 0);
9786
9787 temp = previous;
9788 previous = current;
9789 current = temp;
9790
9791 previous = stb__eps_closure(m,previous);
9792 stb__clear(m, previous);
9793
9794 ++str;
9795 }
9796
9797 // transition to pick up a '$' at the end
9798 y = stb_arr_len(previous);
9799 for (i=0; i < y; ++i)
9800 m->nodes[(int) previous[i]].active = 1;
9801
9802 for (i=0; i < y; ++i) {
9803 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9804 z = stb_arr_len(n->out);
9805 for (j=0; j < z; ++j) {
9806 if (n->out[j].match == '\n')
9807 current = stb__add_if_inactive(m, current, n->out[j].node);
9808 }
9809 }
9810
9811 previous = stb__eps_closure(m,previous);
9812 stb__clear(m, previous);
9813
9814 y = stb_arr_len(previous);
9815 for (i=0; i < y; ++i)
9816 if (m->nodes[(int) previous[i]].goal)
9817 result = 1;
9818
9819 stb_arr_free(previous);
9820 stb_arr_free(current);
9821
9822 return result && *str == 0;
9823 }
9824
9825 stb_int16 stb__get_dfa_node(stb_matcher *m, stb_uint16 *list)
9826 {
9827 stb_uint16 node;
9828 stb_uint32 data[8], *state, *newstate;
9829 int i,j,n;
9830
9831 state = (stb_uint32 *) stb_temp(data, m->num_words_per_dfa * 4);
9832 memset(state, 0, m->num_words_per_dfa*4);
9833
9834 n = stb_arr_len(list);
9835 for (i=0; i < n; ++i) {
9836 int x = list[i];
9837 state[x >> 5] |= 1 << (x & 31);
9838 }
9839
9840 // @TODO use a hash table
9841 n = stb_arr_len(m->dfa_mapping);
9842 i=j=0;
9843 for(; j < n; ++i, j += m->num_words_per_dfa) {
9844 // @TODO special case for <= 32
9845 if (!memcmp(state, m->dfa_mapping + j, m->num_words_per_dfa*4)) {
9846 node = i;
9847 goto done;
9848 }
9849 }
9850
9851 assert(stb_arr_len(m->dfa) == i);
9852 node = i;
9853
9854 newstate = stb_arr_addn(m->dfa_mapping, m->num_words_per_dfa);
9855 memcpy(newstate, state, m->num_words_per_dfa*4);
9856
9857 // set all transitions to 'unknown'
9858 stb_arr_add(m->dfa);
9859 memset(m->dfa[i].transition, -1, sizeof(m->dfa[i].transition));
9860
9861 if (m->does_lex) {
9862 int result = -1;
9863 n = stb_arr_len(list);
9864 for (i=0; i < n; ++i) {
9865 if (m->nodes[(int) list[i]].goal > result)
9866 result = m->nodes[(int) list[i]].goal;
9867 }
9868
9869 stb_arr_push(m->dfa_result, result);
9870 }
9871
9872 done:
9873 stb_tempfree(data, state);
9874 return node;
9875 }
9876
9877 static int stb__matcher_dfa(stb_matcher *m, char *str_c, int *len)
9878 {
9879 stb_uint8 *str = (stb_uint8 *) str_c;
9880 stb_int16 node,prevnode;
9881 stb_dfa *trans;
9882 int match_length = 0;
9883 stb_int16 match_result=0;
9884
9885 if (m->dfa_start == STB__DFA_UNDEF) {
9886 stb_uint16 *list;
9887
9888 m->num_words_per_dfa = (stb_arr_len(m->nodes)+31) >> 5;
9889 stb__optimize(m);
9890
9891 list = stb__add_if_inactive(m, NULL, m->start_node);
9892 list = stb__eps_closure(m,list);
9893 if (m->does_lex) {
9894 m->dfa_start = stb__get_dfa_node(m,list);
9895 stb__clear(m, list);
9896 // DON'T allow start state to be a goal state!
9897 // this allows people to specify regexes that can match 0
9898 // characters without them actually matching (also we don't
9899 // check _before_ advancing anyway
9900 if (m->dfa_start <= STB__DFA_MGOAL)
9901 m->dfa_start = -(m->dfa_start - STB__DFA_MGOAL);
9902 } else {
9903 if (stb__clear_goalcheck(m, list))
9904 m->dfa_start = STB__DFA_GOAL;
9905 else
9906 m->dfa_start = stb__get_dfa_node(m,list);
9907 }
9908 stb_arr_free(list);
9909 }
9910
9911 prevnode = STB__DFA_UNDEF;
9912 node = m->dfa_start;
9913 trans = m->dfa;
9914
9915 if (m->dfa_start == STB__DFA_GOAL)
9916 return 1;
9917
9918 for(;;) {
9919 assert(node >= STB__DFA_VALID);
9920
9921 // fast inner DFA loop; especially if STB__DFA_VALID is 0
9922
9923 do {
9924 prevnode = node;
9925 node = trans[node].transition[*str++];
9926 } while (node >= STB__DFA_VALID);
9927
9928 assert(node >= STB__DFA_MGOAL - stb_arr_len(m->dfa));
9929 assert(node < stb_arr_len(m->dfa));
9930
9931 // special case for lex: need _longest_ match, so notice goal
9932 // state without stopping
9933 if (node <= STB__DFA_MGOAL) {
9934 match_length = (int) (str - (stb_uint8 *) str_c);
9935 node = -(node - STB__DFA_MGOAL);
9936 match_result = node;
9937 continue;
9938 }
9939
9940 // slow NFA->DFA conversion
9941
9942 // or we hit the goal or the end of the string, but those
9943 // can only happen once per search...
9944
9945 if (node == STB__DFA_UNDEF) {
9946 // build a list -- @TODO special case <= 32 states
9947 // heck, use a more compact data structure for <= 16 and <= 8 ?!
9948
9949 // @TODO keep states/newstates around instead of reallocating them
9950 stb_uint16 *states = NULL;
9951 stb_uint16 *newstates = NULL;
9952 int i,j,y,z;
9953 stb_uint32 *flags = &m->dfa_mapping[prevnode * m->num_words_per_dfa];
9954 assert(prevnode != STB__DFA_UNDEF);
9955 stb_arr_setsize(states, 4);
9956 stb_arr_setsize(newstates,4);
9957 for (j=0; j < m->num_words_per_dfa; ++j) {
9958 for (i=0; i < 32; ++i) {
9959 if (*flags & (1 << i))
9960 stb_arr_push(states, j*32+i);
9961 }
9962 ++flags;
9963 }
9964 // states is now the states we were in in the previous node;
9965 // so now we can compute what node it transitions to on str[-1]
9966
9967 y = stb_arr_len(states);
9968 for (i=0; i < y; ++i) {
9969 stb_nfa_node *n = &m->nodes[(int) states[i]];
9970 z = stb_arr_len(n->out);
9971 for (j=0; j < z; ++j) {
9972 if (n->out[j].match >= 0) {
9973 if (n->out[j].match == str[-1] || (str[-1] == 0 && n->out[j].match == '\n'))
9974 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9975 } else if (n->out[j].match == -1) {
9976 if (str[-1] != '\n' && str[-1])
9977 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9978 } else if (n->out[j].match < -1) {
9979 int z = -n->out[j].match - 2;
9980 if (m->charset[str[-1]] & (1 << z))
9981 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9982 }
9983 }
9984 }
9985 // AND add in the start state!
9986 if (!m->match_start || (str[-1] == '\n' && !m->does_lex))
9987 newstates = stb__add_if_inactive(m, newstates, m->start_node);
9988 // AND epsilon close it
9989 newstates = stb__eps_closure(m, newstates);
9990 // if it's a goal state, then that's all there is to it
9991 if (stb__clear_goalcheck(m, newstates)) {
9992 if (m->does_lex) {
9993 match_length = (int) (str - (stb_uint8 *) str_c);
9994 node = stb__get_dfa_node(m,newstates);
9995 match_result = node;
9996 node = -node + STB__DFA_MGOAL;
9997 trans = m->dfa; // could have gotten realloc()ed
9998 } else
9999 node = STB__DFA_GOAL;
10000 } else if (str[-1] == 0 || stb_arr_len(newstates) == 0) {
10001 node = STB__DFA_END;
10002 } else {
10003 node = stb__get_dfa_node(m,newstates);
10004 trans = m->dfa; // could have gotten realloc()ed
10005 }
10006 trans[prevnode].transition[str[-1]] = node;
10007 if (node <= STB__DFA_MGOAL)
10008 node = -(node - STB__DFA_MGOAL);
10009 stb_arr_free(newstates);
10010 stb_arr_free(states);
10011 }
10012
10013 if (node == STB__DFA_GOAL) {
10014 return 1;
10015 }
10016 if (node == STB__DFA_END) {
10017 if (m->does_lex) {
10018 if (match_result) {
10019 if (len) *len = match_length;
10020 return m->dfa_result[(int) match_result];
10021 }
10022 }
10023 return 0;
10024 }
10025
10026 assert(node != STB__DFA_UNDEF);
10027 }
10028 }
10029
10030 int stb_matcher_find(stb_matcher *m, char *str)
10031 {
10032 assert(m->does_lex == 0);
10033 return stb__matcher_dfa(m, str, NULL);
10034 }
10035
10036 int stb_lex(stb_matcher *m, char *str, int *len)
10037 {
10038 assert(m->does_lex);
10039 return stb__matcher_dfa(m, str, len);
10040 }
10041
10042 #ifdef STB_PERFECT_HASH
10043 int stb_regex(char *regex, char *str)
10044 {
10045 static stb_perfect p;
10046 static stb_matcher ** matchers;
10047 static char ** regexps;
10048 static char ** regexp_cache;
10049 static unsigned short *mapping;
10050 int z = stb_perfect_hash(&p, (int)(size_t) regex);
10051 if (z >= 0) {
10052 if (strcmp(regex, regexp_cache[(int) mapping[z]])) {
10053 int i = mapping[z];
10054 stb_matcher_free(matchers[i]);
10055 free(regexp_cache[i]);
10056 regexps[i] = regex;
10057 regexp_cache[i] = stb_p_strdup(regex);
10058 matchers[i] = stb_regex_matcher(regex);
10059 }
10060 } else {
10061 int i,n;
10062 if (regex == NULL) {
10063 for (i=0; i < stb_arr_len(matchers); ++i) {
10064 stb_matcher_free(matchers[i]);
10065 free(regexp_cache[i]);
10066 }
10067 stb_arr_free(matchers);
10068 stb_arr_free(regexps);
10069 stb_arr_free(regexp_cache);
10070 stb_perfect_destroy(&p);
10071 free(mapping); mapping = NULL;
10072 return -1;
10073 }
10074 stb_arr_push(regexps, regex);
10075 stb_arr_push(regexp_cache, stb_p_strdup(regex));
10076 stb_arr_push(matchers, stb_regex_matcher(regex));
10077 stb_perfect_destroy(&p);
10078 n = stb_perfect_create(&p, (unsigned int *) (char **) regexps, stb_arr_len(regexps));
10079 mapping = (unsigned short *) realloc(mapping, n * sizeof(*mapping));
10080 for (i=0; i < stb_arr_len(regexps); ++i)
10081 mapping[stb_perfect_hash(&p, (int)(size_t) regexps[i])] = i;
10082 z = stb_perfect_hash(&p, (int)(size_t) regex);
10083 }
10084 return stb_matcher_find(matchers[(int) mapping[z]], str);
10085 }
10086 #endif
10087 #endif // STB_DEFINE
10088
10089
10090 #if 0
10091 //////////////////////////////////////////////////////////////////////////////
10092 //
10093 // C source-code introspection
10094 //
10095
10096 // runtime structure
10097 typedef struct
10098 {
10099 char *name;
10100 char *type; // base type
10101 char *comment; // content of comment field
10102 int size; // size of base type
10103 int offset; // field offset
10104 int arrcount[8]; // array sizes; -1 = pointer indirection; 0 = end of list
10105 } stb_info_field;
10106
10107 typedef struct
10108 {
10109 char *structname;
10110 int size;
10111 int num_fields;
10112 stb_info_field *fields;
10113 } stb_info_struct;
10114
10115 extern stb_info_struct stb_introspect_output[];
10116
10117 //
10118
10119 STB_EXTERN void stb_introspect_precompiled(stb_info_struct *compiled);
10120 STB_EXTERN void stb__introspect(char *path, char *file);
10121
10122 #define stb_introspect_ship() stb__introspect(NULL, NULL, stb__introspect_output)
10123
10124 #ifdef STB_SHIP
10125 #define stb_introspect() stb_introspect_ship()
10126 #define stb_introspect_path(p) stb_introspect_ship()
10127 #else
10128 // bootstrapping: define stb_introspect() (or 'path') the first time
10129 #define stb_introspect() stb__introspect(NULL, __FILE__, NULL)
10130 #define stb_introspect_auto() stb__introspect(NULL, __FILE__, stb__introspect_output)
10131
10132 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
10133 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
10134 #endif
10135
10136 #ifdef STB_DEFINE
10137
10138 #ifndef STB_INTROSPECT_CPP
10139 #ifdef __cplusplus
10140 #define STB_INTROSPECT_CPP 1
10141 #else
10142 #define STB_INTROSPECT_CPP 0
10143 #endif
10144 #endif
10145
10146 void stb_introspect_precompiled(stb_info_struct *compiled)
10147 {
10148
10149 }
10150
10151
10152 static void stb__introspect_filename(char *buffer, char *path)
10153 {
10154 #if STB_INTROSPECT_CPP
10155 stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.cpp", path);
10156 #else
10157 stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.c", path);
10158 #endif
10159 }
10160
10161 static void stb__introspect_compute(char *path, char *file)
10162 {
10163 int i;
10164 char ** include_list = NULL;
10165 char ** introspect_list = NULL;
10166 FILE *f;
10167 f = stb_p_fopen(file, "w");
10168 if (!f) return;
10169
10170 fputs("// if you get compiler errors, change the following 0 to a 1:\n", f);
10171 fputs("#define STB_INTROSPECT_INVALID 0\n\n", f);
10172 fputs("// this will force the code to compile, and force the introspector\n", f);
10173 fputs("// to run and then exit, allowing you to recompile\n\n\n", f);
10174 fputs("#include \"stb.h\"\n\n",f );
10175 fputs("#if STB_INTROSPECT_INVALID\n", f);
10176 fputs(" stb_info_struct stb__introspect_output[] = { (void *) 1 }\n", f);
10177 fputs("#else\n\n", f);
10178 for (i=0; i < stb_arr_len(include_list); ++i)
10179 fprintf(f, " #include \"%s\"\n", include_list[i]);
10180
10181 fputs(" stb_info_struct stb__introspect_output[] =\n{\n", f);
10182 for (i=0; i < stb_arr_len(introspect_list); ++i)
10183 fprintf(f, " stb_introspect_%s,\n", introspect_list[i]);
10184 fputs(" };\n", f);
10185 fputs("#endif\n", f);
10186 fclose(f);
10187 }
10188
10189 static stb_info_struct *stb__introspect_info;
10190
10191 #ifndef STB_SHIP
10192
10193 #endif
10194
10195 void stb__introspect(char *path, char *file, stb_info_struct *compiled)
10196 {
10197 static int first=1;
10198 if (!first) return;
10199 first=0;
10200
10201 stb__introspect_info = compiled;
10202
10203 #ifndef STB_SHIP
10204 if (path || file) {
10205 int bail_flag = compiled && compiled[0].structname == (void *) 1;
10206 int needs_building = bail_flag;
10207 struct stb__stat st;
10208 char buffer[1024], buffer2[1024];
10209 if (!path) {
10210 stb_splitpath(buffer, file, STB_PATH);
10211 path = buffer;
10212 }
10213 // bail if the source path doesn't exist
10214 if (!stb_fexists(path)) return;
10215
10216 stb__introspect_filename(buffer2, path);
10217
10218 // get source/include files timestamps, compare to output-file timestamp;
10219 // if mismatched, regenerate
10220
10221 if (stb__stat(buffer2, &st))
10222 needs_building = STB_TRUE;
10223
10224 {
10225 // find any file that contains an introspection command and is newer
10226 // if needs_building is already true, we don't need to do this test,
10227 // but we still need these arrays, so go ahead and get them
10228 char **all[3];
10229 all[0] = stb_readdir_files_mask(path, "*.h");
10230 all[1] = stb_readdir_files_mask(path, "*.c");
10231 all[2] = stb_readdir_files_mask(path, "*.cpp");
10232 int i,j;
10233 if (needs_building) {
10234 for (j=0; j < 3; ++j) {
10235 for (i=0; i < stb_arr_len(all[j]); ++i) {
10236 struct stb__stat st2;
10237 if (!stb__stat(all[j][i], &st2)) {
10238 if (st.st_mtime < st2.st_mtime) {
10239 char *z = stb_filec(all[j][i], NULL);
10240 int found=STB_FALSE;
10241 while (y) {
10242 y = strstr(y, "//si");
10243 if (y && isspace(y[4])) {
10244 found = STB_TRUE;
10245 break;
10246 }
10247 }
10248 needs_building = STB_TRUE;
10249 goto done;
10250 }
10251 }
10252 }
10253 }
10254 done:;
10255 }
10256 char *z = stb_filec(all[i], NULL), *y = z;
10257 int found=STB_FALSE;
10258 while (y) {
10259 y = strstr(y, "//si");
10260 if (y && isspace(y[4])) {
10261 found = STB_TRUE;
10262 break;
10263 }
10264 }
10265 if (found)
10266 stb_arr_push(introspect_h, stb_p_strdup(all[i]));
10267 free(z);
10268 }
10269 }
10270 stb_readdir_free(all);
10271 if (!needs_building) {
10272 for (i=0; i < stb_arr_len(introspect_h); ++i) {
10273 struct stb__stat st2;
10274 if (!stb__stat(introspect_h[i], &st2))
10275 if (st.st_mtime < st2.st_mtime)
10276 needs_building = STB_TRUE;
10277 }
10278 }
10279
10280 if (needs_building) {
10281 stb__introspect_compute(path, buffer2);
10282 }
10283 }
10284 }
10285 #endif
10286 }
10287 #endif
10288 #endif
10289
10290 #ifdef STB_INTROSPECT
10291 // compile-time code-generator
10292 #define INTROSPECT(x) int main(int argc, char **argv) { stb__introspect(__FILE__); return 0; }
10293 #define FILE(x)
10294
10295 void stb__introspect(char *filename)
10296 {
10297 char *file = stb_file(filename, NULL);
10298 char *s = file, *t, **p;
10299 char *out_name = "stb_introspect.c";
10300 char *out_path;
10301 STB_ARR(char) filelist = NULL;
10302 int i,n;
10303 if (!file) stb_fatal("Couldn't open %s", filename);
10304
10305 out_path = stb_splitpathdup(filename, STB_PATH);
10306
10307 // search for the macros
10308 while (*s) {
10309 char buffer[256];
10310 while (*s && !isupper(*s)) ++s;
10311 s = stb_strtok_invert(buffer, s, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
10312 s = stb_skipwhite(s);
10313 if (*s == '(') {
10314 ++s;
10315 t = strchr(s, ')');
10316 if (t == NULL) stb_fatal("Error parsing %s", filename);
10317
10318 }
10319 }
10320 }
10321
10322
10323
10324 #endif
10325
10326
10327 //////////////////////////////////////////////////////////////////////////////
10328 //
10329 // STB-C sliding-window dictionary compression
10330 //
10331 // This uses a DEFLATE-style sliding window, but no bitwise entropy.
10332 // Everything is on byte boundaries, so you could then apply a byte-wise
10333 // entropy code, though that's nowhere near as effective.
10334 //
10335 // An STB-C stream begins with a 16-byte header:
10336 // 4 bytes: 0x57 0xBC 0x00 0x00
10337 // 8 bytes: big-endian size of decompressed data, 64-bits
10338 // 4 bytes: big-endian size of window (how far back decompressor may need)
10339 //
10340 // The following symbols appear in the stream (these were determined ad hoc,
10341 // not by analysis):
10342 //
10343 // [dict] 00000100 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10344 // [END] 00000101 11111010 cccccccc cccccccc cccccccc cccccccc
10345 // [dict] 00000110 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx
10346 // [literals] 00000111 zzzzzzzz zzzzzzzz
10347 // [literals] 00001zzz zzzzzzzz
10348 // [dict] 00010yyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10349 // [dict] 00011yyy yyyyyyyy yyyyyyyy xxxxxxxx
10350 // [literals] 001zzzzz
10351 // [dict] 01yyyyyy yyyyyyyy xxxxxxxx
10352 // [dict] 1xxxxxxx yyyyyyyy
10353 //
10354 // xxxxxxxx: match length - 1
10355 // yyyyyyyy: backwards distance - 1
10356 // zzzzzzzz: num literals - 1
10357 // cccccccc: adler32 checksum of decompressed data
10358 // (all big-endian)
10359
10360
10361 STB_EXTERN stb_uint stb_decompress_length(stb_uchar *input);
10362 STB_EXTERN stb_uint stb_decompress(stb_uchar *out,stb_uchar *in,stb_uint len);
10363 STB_EXTERN stb_uint stb_compress (stb_uchar *out,stb_uchar *in,stb_uint len);
10364 STB_EXTERN void stb_compress_window(int z);
10365 STB_EXTERN void stb_compress_hashsize(unsigned int z);
10366
10367 STB_EXTERN int stb_compress_tofile(char *filename, char *in, stb_uint len);
10368 STB_EXTERN int stb_compress_intofile(FILE *f, char *input, stb_uint len);
10369 STB_EXTERN char *stb_decompress_fromfile(char *filename, stb_uint *len);
10370
10371 STB_EXTERN int stb_compress_stream_start(FILE *f);
10372 STB_EXTERN void stb_compress_stream_end(int close);
10373 STB_EXTERN void stb_write(char *data, int data_len);
10374
10375 #ifdef STB_DEFINE
10376
10377 stb_uint stb_decompress_length(stb_uchar *input)
10378 {
10379 return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
10380 }
10381
10382 //////////////////// decompressor ///////////////////////
10383
10384 // simple implementation that just writes whole thing into big block
10385
10386 static unsigned char *stb__barrier;
10387 static unsigned char *stb__barrier2;
10388 static unsigned char *stb__barrier3;
10389 static unsigned char *stb__barrier4;
10390
10391 static stb_uchar *stb__dout;
10392 static void stb__match(stb_uchar *data, stb_uint length)
10393 {
10394 // INVERSE of memmove... write each byte before copying the next...
10395 assert (stb__dout + length <= stb__barrier);
10396 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10397 if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }
10398 while (length--) *stb__dout++ = *data++;
10399 }
10400
10401 static void stb__lit(stb_uchar *data, stb_uint length)
10402 {
10403 assert (stb__dout + length <= stb__barrier);
10404 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10405 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10406 memcpy(stb__dout, data, length);
10407 stb__dout += length;
10408 }
10409
10410 #define stb__in2(x) ((i[x] << 8) + i[(x)+1])
10411 #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
10412 #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
10413
10414 static stb_uchar *stb_decompress_token(stb_uchar *i)
10415 {
10416 if (*i >= 0x20) { // use fewer if's for cases that expand small
10417 if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10418 else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10419 else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
10420 } else { // more ifs for cases that expand large, since overhead is amortized
10421 if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10422 else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10423 else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
10424 else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
10425 else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10426 else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10427 }
10428 return i;
10429 }
10430
10431 stb_uint stb_decompress(stb_uchar *output, stb_uchar *i, stb_uint length)
10432 {
10433 stb_uint olen;
10434 if (stb__in4(0) != 0x57bC0000) return 0;
10435 if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
10436 olen = stb_decompress_length(i);
10437 stb__barrier2 = i;
10438 stb__barrier3 = i+length;
10439 stb__barrier = output + olen;
10440 stb__barrier4 = output;
10441 i += 16;
10442
10443 stb__dout = output;
10444 while (1) {
10445 stb_uchar *old_i = i;
10446 i = stb_decompress_token(i);
10447 if (i == old_i) {
10448 if (*i == 0x05 && i[1] == 0xfa) {
10449 assert(stb__dout == output + olen);
10450 if (stb__dout != output + olen) return 0;
10451 if (stb_adler32(1, output, olen) != (stb_uint) stb__in4(2))
10452 return 0;
10453 return olen;
10454 } else {
10455 assert(0); /* NOTREACHED */
10456 return 0;
10457 }
10458 }
10459 assert(stb__dout <= output + olen);
10460 if (stb__dout > output + olen)
10461 return 0;
10462 }
10463 }
10464
10465 char *stb_decompress_fromfile(char *filename, unsigned int *len)
10466 {
10467 unsigned int n;
10468 char *q;
10469 unsigned char *p;
10470 FILE *f = stb_p_fopen(filename, "rb"); if (f == NULL) return NULL;
10471 fseek(f, 0, SEEK_END);
10472 n = ftell(f);
10473 fseek(f, 0, SEEK_SET);
10474 p = (unsigned char * ) malloc(n); if (p == NULL) return NULL;
10475 fread(p, 1, n, f);
10476 fclose(f);
10477 if (p == NULL) return NULL;
10478 if (p[0] != 0x57 || p[1] != 0xBc || p[2] || p[3]) { free(p); return NULL; }
10479 q = (char *) malloc(stb_decompress_length(p)+1);
10480 if (!q) { free(p); return NULL; }
10481 *len = stb_decompress((unsigned char *) q, p, n);
10482 if (*len) q[*len] = 0;
10483 free(p);
10484 return q;
10485 }
10486
10487 #if 0
10488 // streaming decompressor
10489
10490 static struct
10491 {
10492 stb__uchar *in_buffer;
10493 stb__uchar *match;
10494
10495 stb__uint pending_literals;
10496 stb__uint pending_match;
10497 } xx;
10498
10499
10500
10501 static void stb__match(stb_uchar *data, stb_uint length)
10502 {
10503 // INVERSE of memmove... write each byte before copying the next...
10504 assert (stb__dout + length <= stb__barrier);
10505 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10506 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10507 while (length--) *stb__dout++ = *data++;
10508 }
10509
10510 static void stb__lit(stb_uchar *data, stb_uint length)
10511 {
10512 assert (stb__dout + length <= stb__barrier);
10513 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10514 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10515 memcpy(stb__dout, data, length);
10516 stb__dout += length;
10517 }
10518
10519 static void sx_match(stb_uchar *data, stb_uint length)
10520 {
10521 xx.match = data;
10522 xx.pending_match = length;
10523 }
10524
10525 static void sx_lit(stb_uchar *data, stb_uint length)
10526 {
10527 xx.pending_lit = length;
10528 }
10529
10530 static int stb_decompress_token_state(void)
10531 {
10532 stb__uchar *i = xx.in_buffer;
10533
10534 if (*i >= 0x20) { // use fewer if's for cases that expand small
10535 if (*i >= 0x80) sx_match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10536 else if (*i >= 0x40) sx_match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10537 else /* *i >= 0x20 */ sx_lit(i+1, i[0] - 0x20 + 1), i += 1;
10538 } else { // more ifs for cases that expand large, since overhead is amortized
10539 if (*i >= 0x18) sx_match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10540 else if (*i >= 0x10) sx_match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10541 else if (*i >= 0x08) sx_lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2;
10542 else if (*i == 0x07) sx_lit(i+3, stb__in2(1) + 1), i += 3;
10543 else if (*i == 0x06) sx_match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10544 else if (*i == 0x04) sx_match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10545 else return 0;
10546 }
10547 xx.in_buffer = i;
10548 return 1;
10549 }
10550 #endif
10551
10552
10553
10554 //////////////////// compressor ///////////////////////
10555
10556 static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
10557 {
10558 stb_uint i;
10559 for (i=0; i < maxlen; ++i)
10560 if (m1[i] != m2[i]) return i;
10561 return i;
10562 }
10563
10564 // simple implementation that just takes the source data in a big block
10565
10566 static stb_uchar *stb__out;
10567 static FILE *stb__outfile;
10568 static stb_uint stb__outbytes;
10569
10570 static void stb__write(unsigned char v)
10571 {
10572 fputc(v, stb__outfile);
10573 ++stb__outbytes;
10574 }
10575
10576 #define stb_out(v) (stb__out ? (void)(*stb__out++ = (stb_uchar) (v)) : stb__write((stb_uchar) (v)))
10577
10578 static void stb_out2(stb_uint v)
10579 {
10580 stb_out(v >> 8);
10581 stb_out(v);
10582 }
10583
10584 static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
10585 static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
10586 stb_out(v >> 8 ); stb_out(v); }
10587
10588 static void outliterals(stb_uchar *in, ptrdiff_t numlit)
10589 {
10590 while (numlit > 65536) {
10591 outliterals(in,65536);
10592 in += 65536;
10593 numlit -= 65536;
10594 }
10595
10596 if (numlit == 0) ;
10597 else if (numlit <= 32) stb_out (0x000020 + (stb_uint) numlit-1);
10598 else if (numlit <= 2048) stb_out2(0x000800 + (stb_uint) numlit-1);
10599 else /* numlit <= 65536) */ stb_out3(0x070000 + (stb_uint) numlit-1);
10600
10601 if (stb__out) {
10602 memcpy(stb__out,in,numlit);
10603 stb__out += numlit;
10604 } else
10605 fwrite(in, 1, numlit, stb__outfile);
10606 }
10607
10608 static int stb__window = 0x40000; // 256K
10609 void stb_compress_window(int z)
10610 {
10611 if (z >= 0x1000000) z = 0x1000000; // limit of implementation
10612 if (z < 0x100) z = 0x100; // insanely small
10613 stb__window = z;
10614 }
10615
10616 static int stb_not_crap(int best, int dist)
10617 {
10618 return ((best > 2 && dist <= 0x00100)
10619 || (best > 5 && dist <= 0x04000)
10620 || (best > 7 && dist <= 0x80000));
10621 }
10622
10623 static stb_uint stb__hashsize = 32768;
10624 void stb_compress_hashsize(unsigned int y)
10625 {
10626 unsigned int z = 1024;
10627 while (z < y) z <<= 1;
10628 stb__hashsize = z >> 2; // pass in bytes, store #pointers
10629 }
10630
10631 // note that you can play with the hashing functions all you
10632 // want without needing to change the decompressor
10633 #define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
10634 #define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
10635 #define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
10636
10637 static stb_uint32 stb__running_adler;
10638
10639 static int stb_compress_chunk(stb_uchar *history,
10640 stb_uchar *start,
10641 stb_uchar *end,
10642 int length,
10643 int *pending_literals,
10644 stb_uchar **chash,
10645 stb_uint mask)
10646 {
10647 int window = stb__window;
10648 stb_uint match_max;
10649 stb_uchar *lit_start = start - *pending_literals;
10650 stb_uchar *q = start;
10651
10652 #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
10653
10654 // stop short of the end so we don't scan off the end doing
10655 // the hashing; this means we won't compress the last few bytes
10656 // unless they were part of something longer
10657 while (q < start+length && q+12 < end) {
10658 int m;
10659 stb_uint h1,h2,h3,h4, h;
10660 stb_uchar *t;
10661 int best = 2, dist=0;
10662
10663 if (q+65536 > end)
10664 match_max = (stb_uint) (end-q);
10665 else
10666 match_max = 65536u;
10667
10668 #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
10669
10670 #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
10671 if (p ? dist != (int) (q-t) : 1) \
10672 if ((m = (int) stb_matchlen(t, q, match_max)) > best)\
10673 if (stb__nc(m,(int) (q-(t)))) \
10674 best = m, dist = (int) (q - (t))
10675
10676 // rather than search for all matches, only try 4 candidate locations,
10677 // chosen based on 4 different hash functions of different lengths.
10678 // this strategy is inspired by LZO; hashing is unrolled here using the
10679 // 'hc' macro
10680 h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
10681 t = chash[h1]; if (t) STB__TRY(t,0);
10682 h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
10683 h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
10684 h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
10685 h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
10686 h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
10687 t = chash[h4]; if (t) STB__TRY(t,1);
10688
10689 // because we use a shared hash table, can only update it
10690 // _after_ we've probed all of them
10691 chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
10692
10693 if (best > 2)
10694 assert(dist > 0);
10695
10696 // see if our best match qualifies
10697 if (best < 3) { // fast path literals
10698 ++q;
10699 } else if (best > 2 && best <= 0x80 && dist <= 0x100) {
10700 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10701 stb_out(0x80 + best-1);
10702 stb_out(dist-1);
10703 } else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
10704 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10705 stb_out2(0x4000 + dist-1);
10706 stb_out(best-1);
10707 } else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
10708 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10709 stb_out3(0x180000 + dist-1);
10710 stb_out(best-1);
10711 } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
10712 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10713 stb_out3(0x100000 + dist-1);
10714 stb_out2(best-1);
10715 } else if (best > 9 && dist <= 0x1000000) {
10716 if (best > 65536) best = 65536;
10717 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10718 if (best <= 0x100) {
10719 stb_out(0x06);
10720 stb_out3(dist-1);
10721 stb_out(best-1);
10722 } else {
10723 stb_out(0x04);
10724 stb_out3(dist-1);
10725 stb_out2(best-1);
10726 }
10727 } else { // fallback literals if no match was a balanced tradeoff
10728 ++q;
10729 }
10730 }
10731
10732 // if we didn't get all the way, add the rest to literals
10733 if (q-start < length)
10734 q = start+length;
10735
10736 // the literals are everything from lit_start to q
10737 *pending_literals = (int) (q - lit_start);
10738
10739 stb__running_adler = stb_adler32(stb__running_adler, start, (int) (q - start));
10740 return (int) (q - start);
10741 }
10742
10743 static int stb_compress_inner(stb_uchar *input, stb_uint length)
10744 {
10745 int literals = 0;
10746 stb_uint len,i;
10747
10748 stb_uchar **chash;
10749 chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
10750 if (chash == NULL) return 0; // failure
10751 for (i=0; i < stb__hashsize; ++i)
10752 chash[i] = NULL;
10753
10754 // stream signature
10755 stb_out(0x57); stb_out(0xbc);
10756 stb_out2(0);
10757
10758 stb_out4(0); // 64-bit length requires 32-bit leading 0
10759 stb_out4(length);
10760 stb_out4(stb__window);
10761
10762 stb__running_adler = 1;
10763
10764 len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
10765 assert(len == length);
10766
10767 outliterals(input+length - literals, literals);
10768
10769 free(chash);
10770
10771 stb_out2(0x05fa); // end opcode
10772
10773 stb_out4(stb__running_adler);
10774
10775 return 1; // success
10776 }
10777
10778 stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
10779 {
10780 stb__out = out;
10781 stb__outfile = NULL;
10782
10783 stb_compress_inner(input, length);
10784
10785 return (stb_uint) (stb__out - out);
10786 }
10787
10788 int stb_compress_tofile(char *filename, char *input, unsigned int length)
10789 {
10790 //int maxlen = length + 512 + (length >> 2); // total guess
10791 //char *buffer = (char *) malloc(maxlen);
10792 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10793
10794 stb__out = NULL;
10795 stb__outfile = stb_p_fopen(filename, "wb");
10796 if (!stb__outfile) return 0;
10797
10798 stb__outbytes = 0;
10799
10800 if (!stb_compress_inner((stb_uchar*)input, length))
10801 return 0;
10802
10803 fclose(stb__outfile);
10804
10805 return stb__outbytes;
10806 }
10807
10808 int stb_compress_intofile(FILE *f, char *input, unsigned int length)
10809 {
10810 //int maxlen = length + 512 + (length >> 2); // total guess
10811 //char *buffer = (char*)malloc(maxlen);
10812 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10813
10814 stb__out = NULL;
10815 stb__outfile = f;
10816 if (!stb__outfile) return 0;
10817
10818 stb__outbytes = 0;
10819
10820 if (!stb_compress_inner((stb_uchar*)input, length))
10821 return 0;
10822
10823 return stb__outbytes;
10824 }
10825
10826 ////////////////////// streaming I/O version /////////////////////
10827
10828
10829 static size_t stb_out_backpatch_id(void)
10830 {
10831 if (stb__out)
10832 return (size_t) stb__out;
10833 else
10834 return ftell(stb__outfile);
10835 }
10836
10837 static void stb_out_backpatch(size_t id, stb_uint value)
10838 {
10839 stb_uchar data[4] = { (stb_uchar)(value >> 24), (stb_uchar)(value >> 16), (stb_uchar)(value >> 8), (stb_uchar)(value) };
10840 if (stb__out) {
10841 memcpy((void *) id, data, 4);
10842 } else {
10843 stb_uint where = ftell(stb__outfile);
10844 fseek(stb__outfile, (long) id, SEEK_SET);
10845 fwrite(data, 4, 1, stb__outfile);
10846 fseek(stb__outfile, where, SEEK_SET);
10847 }
10848 }
10849
10850 // ok, the wraparound buffer was a total failure. let's instead
10851 // use a copying-in-place buffer, which lets us share the code.
10852 // This is way less efficient but it'll do for now.
10853
10854 static struct
10855 {
10856 stb_uchar *buffer;
10857 int size; // physical size of buffer in bytes
10858
10859 int valid; // amount of valid data in bytes
10860 int start; // bytes of data already output
10861
10862 int window;
10863 int fsize;
10864
10865 int pending_literals; // bytes not-quite output but counted in start
10866 int length_id;
10867
10868 stb_uint total_bytes;
10869
10870 stb_uchar **chash;
10871 stb_uint hashmask;
10872 } xtb;
10873
10874 static int stb_compress_streaming_start(void)
10875 {
10876 stb_uint i;
10877 xtb.size = stb__window * 3;
10878 xtb.buffer = (stb_uchar*)malloc(xtb.size);
10879 if (!xtb.buffer) return 0;
10880
10881 xtb.chash = (stb_uchar**)malloc(sizeof(*xtb.chash) * stb__hashsize);
10882 if (!xtb.chash) {
10883 free(xtb.buffer);
10884 return 0;
10885 }
10886
10887 for (i=0; i < stb__hashsize; ++i)
10888 xtb.chash[i] = NULL;
10889
10890 xtb.hashmask = stb__hashsize-1;
10891
10892 xtb.valid = 0;
10893 xtb.start = 0;
10894 xtb.window = stb__window;
10895 xtb.fsize = stb__window;
10896 xtb.pending_literals = 0;
10897 xtb.total_bytes = 0;
10898
10899 // stream signature
10900 stb_out(0x57); stb_out(0xbc); stb_out2(0);
10901
10902 stb_out4(0); // 64-bit length requires 32-bit leading 0
10903
10904 xtb.length_id = (int) stb_out_backpatch_id();
10905 stb_out4(0); // we don't know the output length yet
10906
10907 stb_out4(stb__window);
10908
10909 stb__running_adler = 1;
10910
10911 return 1;
10912 }
10913
10914 static int stb_compress_streaming_end(void)
10915 {
10916 // flush out any remaining data
10917 stb_compress_chunk(xtb.buffer, xtb.buffer+xtb.start, xtb.buffer+xtb.valid,
10918 xtb.valid-xtb.start, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10919
10920 // write out pending literals
10921 outliterals(xtb.buffer + xtb.valid - xtb.pending_literals, xtb.pending_literals);
10922
10923 stb_out2(0x05fa); // end opcode
10924 stb_out4(stb__running_adler);
10925
10926 stb_out_backpatch(xtb.length_id, xtb.total_bytes);
10927
10928 free(xtb.buffer);
10929 free(xtb.chash);
10930 return 1;
10931 }
10932
10933 void stb_write(char *data, int data_len)
10934 {
10935 stb_uint i;
10936
10937 // @TODO: fast path for filling the buffer and doing nothing else
10938 // if (xtb.valid + data_len < xtb.size)
10939
10940 xtb.total_bytes += data_len;
10941
10942 while (data_len) {
10943 // fill buffer
10944 if (xtb.valid < xtb.size) {
10945 int amt = xtb.size - xtb.valid;
10946 if (data_len < amt) amt = data_len;
10947 memcpy(xtb.buffer + xtb.valid, data, amt);
10948 data_len -= amt;
10949 data += amt;
10950 xtb.valid += amt;
10951 }
10952 if (xtb.valid < xtb.size)
10953 return;
10954
10955 // at this point, the buffer is full
10956
10957 // if we can process some data, go for it; make sure
10958 // we leave an 'fsize's worth of data, though
10959 if (xtb.start + xtb.fsize < xtb.valid) {
10960 int amount = (xtb.valid - xtb.fsize) - xtb.start;
10961 int n;
10962 assert(amount > 0);
10963 n = stb_compress_chunk(xtb.buffer, xtb.buffer + xtb.start, xtb.buffer + xtb.valid,
10964 amount, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10965 xtb.start += n;
10966 }
10967
10968 assert(xtb.start + xtb.fsize >= xtb.valid);
10969 // at this point, our future size is too small, so we
10970 // need to flush some history. we, in fact, flush exactly
10971 // one window's worth of history
10972
10973 {
10974 int flush = xtb.window;
10975 assert(xtb.start >= flush);
10976 assert(xtb.valid >= flush);
10977
10978 // if 'pending literals' extends back into the shift region,
10979 // write them out
10980 if (xtb.start - xtb.pending_literals < flush) {
10981 outliterals(xtb.buffer + xtb.start - xtb.pending_literals, xtb.pending_literals);
10982 xtb.pending_literals = 0;
10983 }
10984
10985 // now shift the window
10986 memmove(xtb.buffer, xtb.buffer + flush, xtb.valid - flush);
10987 xtb.start -= flush;
10988 xtb.valid -= flush;
10989
10990 for (i=0; i <= xtb.hashmask; ++i)
10991 if (xtb.chash[i] < xtb.buffer + flush)
10992 xtb.chash[i] = NULL;
10993 else
10994 xtb.chash[i] -= flush;
10995 }
10996 // and now that we've made room for more data, go back to the top
10997 }
10998 }
10999
11000 int stb_compress_stream_start(FILE *f)
11001 {
11002 stb__out = NULL;
11003 stb__outfile = f;
11004
11005 if (f == NULL)
11006 return 0;
11007
11008 if (!stb_compress_streaming_start())
11009 return 0;
11010
11011 return 1;
11012 }
11013
11014 void stb_compress_stream_end(int close)
11015 {
11016 stb_compress_streaming_end();
11017 if (close && stb__outfile) {
11018 fclose(stb__outfile);
11019 }
11020 }
11021
11022 #endif // STB_DEFINE
11023
11024 //////////////////////////////////////////////////////////////////////////////
11025 //
11026 // File abstraction... tired of not having this... we can write
11027 // compressors to be layers over these that auto-close their children.
11028
11029
11030 typedef struct stbfile
11031 {
11032 int (*getbyte)(struct stbfile *); // -1 on EOF
11033 unsigned int (*getdata)(struct stbfile *, void *block, unsigned int len);
11034
11035 int (*putbyte)(struct stbfile *, int byte);
11036 unsigned int (*putdata)(struct stbfile *, void *block, unsigned int len);
11037
11038 unsigned int (*size)(struct stbfile *);
11039
11040 unsigned int (*tell)(struct stbfile *);
11041 void (*backpatch)(struct stbfile *, unsigned int tell, void *block, unsigned int len);
11042
11043 void (*close)(struct stbfile *);
11044
11045 FILE *f; // file to fread/fwrite
11046 unsigned char *buffer; // input/output buffer
11047 unsigned char *indata, *inend; // input buffer
11048 union {
11049 int various;
11050 void *ptr;
11051 };
11052 } stbfile;
11053
11054 STB_EXTERN unsigned int stb_getc(stbfile *f); // read
11055 STB_EXTERN int stb_putc(stbfile *f, int ch); // write
11056 STB_EXTERN unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len); // read
11057 STB_EXTERN unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len); // write
11058 STB_EXTERN unsigned int stb_tell(stbfile *f); // read
11059 STB_EXTERN unsigned int stb_size(stbfile *f); // read/write
11060 STB_EXTERN void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len); // write
11061
11062 #ifdef STB_DEFINE
11063
11064 unsigned int stb_getc(stbfile *f) { return f->getbyte(f); }
11065 int stb_putc(stbfile *f, int ch) { return f->putbyte(f, ch); }
11066
11067 unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len)
11068 {
11069 return f->getdata(f, buffer, len);
11070 }
11071 unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len)
11072 {
11073 return f->putdata(f, buffer, len);
11074 }
11075 void stb_close(stbfile *f)
11076 {
11077 f->close(f);
11078 free(f);
11079 }
11080 unsigned int stb_tell(stbfile *f) { return f->tell(f); }
11081 unsigned int stb_size(stbfile *f) { return f->size(f); }
11082 void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len)
11083 {
11084 f->backpatch(f,tell,buffer,len);
11085 }
11086
11087 // FILE * implementation
11088 static int stb__fgetbyte(stbfile *f) { return fgetc(f->f); }
11089 static int stb__fputbyte(stbfile *f, int ch) { return fputc(ch, f->f)==0; }
11090 static unsigned int stb__fgetdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fread(buffer,1,len,f->f); }
11091 static unsigned int stb__fputdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fwrite(buffer,1,len,f->f); }
11092 static unsigned int stb__fsize(stbfile *f) { return (unsigned int) stb_filelen(f->f); }
11093 static unsigned int stb__ftell(stbfile *f) { return (unsigned int) ftell(f->f); }
11094 static void stb__fbackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len)
11095 {
11096 fseek(f->f, where, SEEK_SET);
11097 fwrite(buffer, 1, len, f->f);
11098 fseek(f->f, 0, SEEK_END);
11099 }
11100 static void stb__fclose(stbfile *f) { fclose(f->f); }
11101
11102 stbfile *stb_openf(FILE *f)
11103 {
11104 stbfile m = { stb__fgetbyte, stb__fgetdata,
11105 stb__fputbyte, stb__fputdata,
11106 stb__fsize, stb__ftell, stb__fbackpatch, stb__fclose,
11107 0,0,0, };
11108 stbfile *z = (stbfile *) malloc(sizeof(*z));
11109 if (z) {
11110 *z = m;
11111 z->f = f;
11112 }
11113 return z;
11114 }
11115
11116 static int stb__nogetbyte(stbfile *f) { assert(0); return -1; }
11117 static unsigned int stb__nogetdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
11118 static int stb__noputbyte(stbfile *f, int ch) { assert(0); return 0; }
11119 static unsigned int stb__noputdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
11120 static void stb__nobackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len) { assert(0); }
11121
11122 static int stb__bgetbyte(stbfile *s)
11123 {
11124 if (s->indata < s->inend)
11125 return *s->indata++;
11126 else
11127 return -1;
11128 }
11129
11130 static unsigned int stb__bgetdata(stbfile *s, void *buffer, unsigned int len)
11131 {
11132 if (s->indata + len > s->inend)
11133 len = (unsigned int) (s->inend - s->indata);
11134 memcpy(buffer, s->indata, len);
11135 s->indata += len;
11136 return len;
11137 }
11138 static unsigned int stb__bsize(stbfile *s) { return (unsigned int) (s->inend - s->buffer); }
11139 static unsigned int stb__btell(stbfile *s) { return (unsigned int) (s->indata - s->buffer); }
11140
11141 static void stb__bclose(stbfile *s)
11142 {
11143 if (s->various)
11144 free(s->buffer);
11145 }
11146
11147 stbfile *stb_open_inbuffer(void *buffer, unsigned int len)
11148 {
11149 stbfile m = { stb__bgetbyte, stb__bgetdata,
11150 stb__noputbyte, stb__noputdata,
11151 stb__bsize, stb__btell, stb__nobackpatch, stb__bclose };
11152 stbfile *z = (stbfile *) malloc(sizeof(*z));
11153 if (z) {
11154 *z = m;
11155 z->buffer = (unsigned char *) buffer;
11156 z->indata = z->buffer;
11157 z->inend = z->indata + len;
11158 }
11159 return z;
11160 }
11161
11162 stbfile *stb_open_inbuffer_free(void *buffer, unsigned int len)
11163 {
11164 stbfile *z = stb_open_inbuffer(buffer, len);
11165 if (z)
11166 z->various = 1; // free
11167 return z;
11168 }
11169
11170 #ifndef STB_VERSION
11171 // if we've been cut-and-pasted elsewhere, you get a limited
11172 // version of stb_open, without the 'k' flag and utf8 support
11173 static void stb__fclose2(stbfile *f)
11174 {
11175 fclose(f->f);
11176 }
11177
11178 stbfile *stb_open(char *filename, char *mode)
11179 {
11180 FILE *f = stb_p_fopen(filename, mode);
11181 stbfile *s;
11182 if (f == NULL) return NULL;
11183 s = stb_openf(f);
11184 if (s)
11185 s->close = stb__fclose2;
11186 return s;
11187 }
11188 #else
11189 // the full version depends on some code in stb.h; this
11190 // also includes the memory buffer output format implemented with stb_arr
11191 static void stb__fclose2(stbfile *f)
11192 {
11193 stb_fclose(f->f, f->various);
11194 }
11195
11196 stbfile *stb_open(char *filename, char *mode)
11197 {
11198 FILE *f = stb_fopen(filename, mode[0] == 'k' ? mode+1 : mode);
11199 stbfile *s;
11200 if (f == NULL) return NULL;
11201 s = stb_openf(f);
11202 if (s) {
11203 s->close = stb__fclose2;
11204 s->various = mode[0] == 'k' ? stb_keep_if_different : stb_keep_yes;
11205 }
11206 return s;
11207 }
11208
11209 static int stb__aputbyte(stbfile *f, int ch)
11210 {
11211 stb_arr_push(f->buffer, ch);
11212 return 1;
11213 }
11214 static unsigned int stb__aputdata(stbfile *f, void *data, unsigned int len)
11215 {
11216 memcpy(stb_arr_addn(f->buffer, (int) len), data, len);
11217 return len;
11218 }
11219 static unsigned int stb__asize(stbfile *f) { return stb_arr_len(f->buffer); }
11220 static void stb__abackpatch(stbfile *f, unsigned int where, void *data, unsigned int len)
11221 {
11222 memcpy(f->buffer+where, data, len);
11223 }
11224 static void stb__aclose(stbfile *f)
11225 {
11226 *(unsigned char **) f->ptr = f->buffer;
11227 }
11228
11229 stbfile *stb_open_outbuffer(unsigned char **update_on_close)
11230 {
11231 stbfile m = { stb__nogetbyte, stb__nogetdata,
11232 stb__aputbyte, stb__aputdata,
11233 stb__asize, stb__asize, stb__abackpatch, stb__aclose };
11234 stbfile *z = (stbfile *) malloc(sizeof(*z));
11235 if (z) {
11236 z->ptr = update_on_close;
11237 *z = m;
11238 }
11239 return z;
11240 }
11241 #endif
11242 #endif
11243
11244
11245 //////////////////////////////////////////////////////////////////////////////
11246 //
11247 // Arithmetic coder... based on cbloom's notes on the subject, should be
11248 // less code than a huffman code.
11249
11250 typedef struct
11251 {
11252 unsigned int range_low;
11253 unsigned int range_high;
11254 unsigned int code, range; // decode
11255 int buffered_u8;
11256 int pending_ffs;
11257 stbfile *output;
11258 } stb_arith;
11259
11260 STB_EXTERN void stb_arith_init_encode(stb_arith *a, stbfile *out);
11261 STB_EXTERN void stb_arith_init_decode(stb_arith *a, stbfile *in);
11262 STB_EXTERN stbfile *stb_arith_encode_close(stb_arith *a);
11263 STB_EXTERN stbfile *stb_arith_decode_close(stb_arith *a);
11264
11265 STB_EXTERN void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11266 STB_EXTERN void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11267 STB_EXTERN unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq);
11268 STB_EXTERN void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11269 STB_EXTERN unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2);
11270 STB_EXTERN void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11271
11272 STB_EXTERN void stb_arith_encode_byte(stb_arith *a, int byte);
11273 STB_EXTERN int stb_arith_decode_byte(stb_arith *a);
11274
11275 // this is a memory-inefficient way of doing things, but it's
11276 // fast(?) and simple
11277 typedef struct
11278 {
11279 unsigned short cumfreq;
11280 unsigned short samples;
11281 } stb_arith_symstate_item;
11282
11283 typedef struct
11284 {
11285 int num_sym;
11286 unsigned int pow2;
11287 int countdown;
11288 stb_arith_symstate_item data[1];
11289 } stb_arith_symstate;
11290
11291 #ifdef STB_DEFINE
11292 void stb_arith_init_encode(stb_arith *a, stbfile *out)
11293 {
11294 a->range_low = 0;
11295 a->range_high = 0xffffffff;
11296 a->pending_ffs = -1; // means no buffered character currently, to speed up normal case
11297 a->output = out;
11298 }
11299
11300 static void stb__arith_carry(stb_arith *a)
11301 {
11302 int i;
11303 assert(a->pending_ffs != -1); // can't carry with no data
11304 stb_putc(a->output, a->buffered_u8);
11305 for (i=0; i < a->pending_ffs; ++i)
11306 stb_putc(a->output, 0);
11307 }
11308
11309 static void stb__arith_putbyte(stb_arith *a, int byte)
11310 {
11311 if (a->pending_ffs) {
11312 if (a->pending_ffs == -1) { // means no buffered data; encoded for fast path efficiency
11313 if (byte == 0xff)
11314 stb_putc(a->output, byte); // just write it immediately
11315 else {
11316 a->buffered_u8 = byte;
11317 a->pending_ffs = 0;
11318 }
11319 } else if (byte == 0xff) {
11320 ++a->pending_ffs;
11321 } else {
11322 int i;
11323 stb_putc(a->output, a->buffered_u8);
11324 for (i=0; i < a->pending_ffs; ++i)
11325 stb_putc(a->output, 0xff);
11326 }
11327 } else if (byte == 0xff) {
11328 ++a->pending_ffs;
11329 } else {
11330 // fast path
11331 stb_putc(a->output, a->buffered_u8);
11332 a->buffered_u8 = byte;
11333 }
11334 }
11335
11336 static void stb__arith_flush(stb_arith *a)
11337 {
11338 if (a->pending_ffs >= 0) {
11339 int i;
11340 stb_putc(a->output, a->buffered_u8);
11341 for (i=0; i < a->pending_ffs; ++i)
11342 stb_putc(a->output, 0xff);
11343 }
11344 }
11345
11346 static void stb__renorm_encoder(stb_arith *a)
11347 {
11348 stb__arith_putbyte(a, a->range_low >> 24);
11349 a->range_low <<= 8;
11350 a->range_high = (a->range_high << 8) | 0xff;
11351 }
11352
11353 static void stb__renorm_decoder(stb_arith *a)
11354 {
11355 int c = stb_getc(a->output);
11356 a->code = (a->code << 8) + (c >= 0 ? c : 0); // if EOF, insert 0
11357 }
11358
11359 void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11360 {
11361 unsigned int range = a->range_high - a->range_low;
11362 unsigned int old = a->range_low;
11363 range /= totalfreq;
11364 a->range_low += range * cumfreq;
11365 a->range_high = a->range_low + range*freq;
11366 if (a->range_low < old)
11367 stb__arith_carry(a);
11368 while (a->range_high - a->range_low < 0x1000000)
11369 stb__renorm_encoder(a);
11370 }
11371
11372 void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11373 {
11374 unsigned int range = a->range_high - a->range_low;
11375 unsigned int old = a->range_low;
11376 range >>= totalfreq2;
11377 a->range_low += range * cumfreq;
11378 a->range_high = a->range_low + range*freq;
11379 if (a->range_low < old)
11380 stb__arith_carry(a);
11381 while (a->range_high - a->range_low < 0x1000000)
11382 stb__renorm_encoder(a);
11383 }
11384
11385 unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq)
11386 {
11387 unsigned int freqsize = a->range / totalfreq;
11388 unsigned int z = a->code / freqsize;
11389 return z >= totalfreq ? totalfreq-1 : z;
11390 }
11391
11392 void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11393 {
11394 unsigned int freqsize = a->range / totalfreq; // @OPTIMIZE, share with above divide somehow?
11395 a->code -= freqsize * cumfreq;
11396 a->range = freqsize * freq;
11397 while (a->range < 0x1000000)
11398 stb__renorm_decoder(a);
11399 }
11400
11401 unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2)
11402 {
11403 unsigned int freqsize = a->range >> totalfreq2;
11404 unsigned int z = a->code / freqsize;
11405 return z >= (1U<<totalfreq2) ? (1U<<totalfreq2)-1 : z;
11406 }
11407
11408 void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11409 {
11410 unsigned int freqsize = a->range >> totalfreq2;
11411 a->code -= freqsize * cumfreq;
11412 a->range = freqsize * freq;
11413 while (a->range < 0x1000000)
11414 stb__renorm_decoder(a);
11415 }
11416
11417 stbfile *stb_arith_encode_close(stb_arith *a)
11418 {
11419 // put exactly as many bytes as we'll read, so we can turn on/off arithmetic coding in a stream
11420 stb__arith_putbyte(a, a->range_low >> 24);
11421 stb__arith_putbyte(a, a->range_low >> 16);
11422 stb__arith_putbyte(a, a->range_low >> 8);
11423 stb__arith_putbyte(a, a->range_low >> 0);
11424 stb__arith_flush(a);
11425 return a->output;
11426 }
11427
11428 stbfile *stb_arith_decode_close(stb_arith *a)
11429 {
11430 return a->output;
11431 }
11432 #endif
11433
11434 //////////////////////////////////////////////////////////////////////////////
11435 //
11436 // Threads
11437 //
11438
11439 #ifndef _WIN32
11440 #ifdef STB_THREADS
11441 #error "threads not implemented except for Windows"
11442 #endif
11443 #endif
11444
11445 // call this function to free any global variables for memory testing
11446 STB_EXTERN void stb_thread_cleanup(void);
11447
11448 typedef void * (*stb_thread_func)(void *);
11449
11450 // do not rely on these types, this is an implementation detail.
11451 // compare against STB_THREAD_NULL and ST_SEMAPHORE_NULL
11452 typedef void *stb_thread;
11453 typedef void *stb_semaphore;
11454 typedef void *stb_mutex;
11455 typedef struct stb__sync *stb_sync;
11456
11457 #define STB_SEMAPHORE_NULL NULL
11458 #define STB_THREAD_NULL NULL
11459 #define STB_MUTEX_NULL NULL
11460 #define STB_SYNC_NULL NULL
11461
11462 // get the number of processors (limited to those in the affinity mask for this process).
11463 STB_EXTERN int stb_processor_count(void);
11464 // force to run on a single core -- needed for RDTSC to work, e.g. for iprof
11465 STB_EXTERN void stb_force_uniprocessor(void);
11466
11467 // stb_work functions: queue up work to be done by some worker threads
11468
11469 // set number of threads to serve the queue; you can change this on the fly,
11470 // but if you decrease it, it won't decrease until things currently on the
11471 // queue are finished
11472 STB_EXTERN void stb_work_numthreads(int n);
11473 // set maximum number of units in the queue; you can only set this BEFORE running any work functions
11474 STB_EXTERN int stb_work_maxunits(int n);
11475 // enqueue some work to be done (can do this from any thread, or even from a piece of work);
11476 // return value of f is stored in *return_code if non-NULL
11477 STB_EXTERN int stb_work(stb_thread_func f, void *d, volatile void **return_code);
11478 // as above, but stb_sync_reach is called on 'rel' after work is complete
11479 STB_EXTERN int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11480
11481
11482 // necessary to call this when using volatile to order writes/reads
11483 STB_EXTERN void stb_barrier(void);
11484
11485 // support for independent queues with their own threads
11486
11487 typedef struct stb__workqueue stb_workqueue;
11488
11489 STB_EXTERN stb_workqueue*stb_workq_new(int numthreads, int max_units);
11490 STB_EXTERN stb_workqueue*stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex);
11491 STB_EXTERN void stb_workq_delete(stb_workqueue *q);
11492 STB_EXTERN void stb_workq_numthreads(stb_workqueue *q, int n);
11493 STB_EXTERN int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code);
11494 STB_EXTERN int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11495 STB_EXTERN int stb_workq_length(stb_workqueue *q);
11496
11497 STB_EXTERN stb_thread stb_create_thread (stb_thread_func f, void *d);
11498 STB_EXTERN stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel);
11499 STB_EXTERN void stb_destroy_thread(stb_thread t);
11500
11501 STB_EXTERN stb_semaphore stb_sem_new(int max_val);
11502 STB_EXTERN stb_semaphore stb_sem_new_extra(int max_val, int start_val);
11503 STB_EXTERN void stb_sem_delete (stb_semaphore s);
11504 STB_EXTERN void stb_sem_waitfor(stb_semaphore s);
11505 STB_EXTERN void stb_sem_release(stb_semaphore s);
11506
11507 STB_EXTERN stb_mutex stb_mutex_new(void);
11508 STB_EXTERN void stb_mutex_delete(stb_mutex m);
11509 STB_EXTERN void stb_mutex_begin(stb_mutex m);
11510 STB_EXTERN void stb_mutex_end(stb_mutex m);
11511
11512 STB_EXTERN stb_sync stb_sync_new(void);
11513 STB_EXTERN void stb_sync_delete(stb_sync s);
11514 STB_EXTERN int stb_sync_set_target(stb_sync s, int count);
11515 STB_EXTERN void stb_sync_reach_and_wait(stb_sync s); // wait for 'target' reachers
11516 STB_EXTERN int stb_sync_reach(stb_sync s);
11517
11518 typedef struct stb__threadqueue stb_threadqueue;
11519 #define STB_THREADQ_DYNAMIC 0
11520 STB_EXTERN stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove);
11521 STB_EXTERN void stb_threadq_delete(stb_threadqueue *tq);
11522 STB_EXTERN int stb_threadq_get(stb_threadqueue *tq, void *output);
11523 STB_EXTERN void stb_threadq_get_block(stb_threadqueue *tq, void *output);
11524 STB_EXTERN int stb_threadq_add(stb_threadqueue *tq, void *input);
11525 // can return FALSE if STB_THREADQ_DYNAMIC and attempt to grow fails
11526 STB_EXTERN int stb_threadq_add_block(stb_threadqueue *tq, void *input);
11527
11528 #ifdef STB_THREADS
11529 #ifdef STB_DEFINE
11530
11531 typedef struct
11532 {
11533 stb_thread_func f;
11534 void *d;
11535 volatile void **return_val;
11536 stb_semaphore sem;
11537 } stb__thread;
11538
11539 // this is initialized along all possible paths to create threads, therefore
11540 // it's always initialized before any other threads are create, therefore
11541 // it's free of races AS LONG AS you only create threads through stb_*
11542 static stb_mutex stb__threadmutex, stb__workmutex;
11543
11544 static void stb__threadmutex_init(void)
11545 {
11546 if (stb__threadmutex == STB_SEMAPHORE_NULL) {
11547 stb__threadmutex = stb_mutex_new();
11548 stb__workmutex = stb_mutex_new();
11549 }
11550 }
11551
11552 #ifdef STB_THREAD_TEST
11553 volatile float stb__t1=1, stb__t2;
11554
11555 static void stb__wait(int n)
11556 {
11557 float z = 0;
11558 int i;
11559 for (i=0; i < n; ++i)
11560 z += 1 / (stb__t1+i);
11561 stb__t2 = z;
11562 }
11563 #else
11564 #define stb__wait(x)
11565 #endif
11566
11567 #ifdef _WIN32
11568
11569 // avoid including windows.h -- note that our definitions aren't
11570 // exactly the same (we don't define the security descriptor struct)
11571 // so if you want to include windows.h, make sure you do it first.
11572 #include <process.h>
11573
11574 #ifndef _WINDOWS_ // check windows.h guard
11575 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
11576 #define STB__DW unsigned long
11577
11578 STB__IMPORT int __stdcall TerminateThread(void *, STB__DW);
11579 STB__IMPORT void * __stdcall CreateSemaphoreA(void *sec, long,long,char*);
11580 STB__IMPORT int __stdcall CloseHandle(void *);
11581 STB__IMPORT STB__DW __stdcall WaitForSingleObject(void *, STB__DW);
11582 STB__IMPORT int __stdcall ReleaseSemaphore(void *, long, long *);
11583 STB__IMPORT void __stdcall Sleep(STB__DW);
11584 #endif
11585
11586 // necessary to call this when using volatile to order writes/reads
11587 void stb_barrier(void)
11588 {
11589 #ifdef MemoryBarrier
11590 MemoryBarrier();
11591 #else
11592 long temp;
11593 __asm xchg temp,eax;
11594 #endif
11595 }
11596
11597 static void stb__thread_run(void *t)
11598 {
11599 void *res;
11600 stb__thread info = * (stb__thread *) t;
11601 free(t);
11602 res = info.f(info.d);
11603 if (info.return_val)
11604 *info.return_val = res;
11605 if (info.sem != STB_SEMAPHORE_NULL)
11606 stb_sem_release(info.sem);
11607 }
11608
11609 static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11610 {
11611 #ifdef _MT
11612 #if defined(STB_FASTMALLOC) && !defined(STB_FASTMALLOC_ITS_OKAY_I_ONLY_MALLOC_IN_ONE_THREAD)
11613 stb_fatal("Error! Cannot use STB_FASTMALLOC with threads.\n");
11614 return STB_THREAD_NULL;
11615 #else
11616 unsigned long id;
11617 stb__thread *data = (stb__thread *) malloc(sizeof(*data));
11618 if (!data) return NULL;
11619 stb__threadmutex_init();
11620 data->f = f;
11621 data->d = d;
11622 data->return_val = return_code;
11623 data->sem = rel;
11624 id = _beginthread(stb__thread_run, 0, data);
11625 if (id == -1) return NULL;
11626 return (void *) id;
11627 #endif
11628 #else
11629 #ifdef STB_NO_STB_STRINGS
11630 stb_fatal("Invalid compilation");
11631 #else
11632 stb_fatal("Must compile mult-threaded to use stb_thread/stb_work.");
11633 #endif
11634 return NULL;
11635 #endif
11636 }
11637
11638 // trivial win32 wrappers
11639 void stb_destroy_thread(stb_thread t) { TerminateThread(t,0); }
11640 stb_semaphore stb_sem_new(int maxv) {return CreateSemaphoreA(NULL,0,maxv,NULL); }
11641 stb_semaphore stb_sem_new_extra(int maxv,int start){return CreateSemaphoreA(NULL,start,maxv,NULL); }
11642 void stb_sem_delete(stb_semaphore s) { if (s != NULL) CloseHandle(s); }
11643 void stb_sem_waitfor(stb_semaphore s) { WaitForSingleObject(s, 0xffffffff); } // INFINITE
11644 void stb_sem_release(stb_semaphore s) { ReleaseSemaphore(s,1,NULL); }
11645 static void stb__thread_sleep(int ms) { Sleep(ms); }
11646
11647 #ifndef _WINDOWS_
11648 STB__IMPORT int __stdcall GetProcessAffinityMask(void *, STB__DW *, STB__DW *);
11649 STB__IMPORT void * __stdcall GetCurrentProcess(void);
11650 STB__IMPORT int __stdcall SetProcessAffinityMask(void *, STB__DW);
11651 #endif
11652
11653 int stb_processor_count(void)
11654 {
11655 unsigned long proc,sys;
11656 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11657 return stb_bitcount(proc);
11658 }
11659
11660 void stb_force_uniprocessor(void)
11661 {
11662 unsigned long proc,sys;
11663 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11664 if (stb_bitcount(proc) > 1) {
11665 int z;
11666 for (z=0; z < 32; ++z)
11667 if (proc & (1 << z))
11668 break;
11669 if (z < 32) {
11670 proc = 1 << z;
11671 SetProcessAffinityMask(GetCurrentProcess(), proc);
11672 }
11673 }
11674 }
11675
11676 #ifdef _WINDOWS_
11677 #define STB_MUTEX_NATIVE
11678 void *stb_mutex_new(void)
11679 {
11680 CRITICAL_SECTION *p = (CRITICAL_SECTION *) malloc(sizeof(*p));
11681 if (p)
11682 #if _WIN32_WINNT >= 0x0500
11683 InitializeCriticalSectionAndSpinCount(p, 500);
11684 #else
11685 InitializeCriticalSection(p);
11686 #endif
11687 return p;
11688 }
11689
11690 void stb_mutex_delete(void *p)
11691 {
11692 if (p) {
11693 DeleteCriticalSection((CRITICAL_SECTION *) p);
11694 free(p);
11695 }
11696 }
11697
11698 void stb_mutex_begin(void *p)
11699 {
11700 stb__wait(500);
11701 if (p)
11702 EnterCriticalSection((CRITICAL_SECTION *) p);
11703 }
11704
11705 void stb_mutex_end(void *p)
11706 {
11707 if (p)
11708 LeaveCriticalSection((CRITICAL_SECTION *) p);
11709 stb__wait(500);
11710 }
11711 #endif // _WINDOWS_
11712
11713 #if 0
11714 // for future reference,
11715 // InterlockedCompareExchange for x86:
11716 int cas64_mp(void * dest, void * xcmp, void * xxchg) {
11717 __asm
11718 {
11719 mov esi, [xxchg] ; exchange
11720 mov ebx, [esi + 0]
11721 mov ecx, [esi + 4]
11722
11723 mov esi, [xcmp] ; comparand
11724 mov eax, [esi + 0]
11725 mov edx, [esi + 4]
11726
11727 mov edi, [dest] ; destination
11728 lock cmpxchg8b [edi]
11729 jz yyyy;
11730
11731 mov [esi + 0], eax;
11732 mov [esi + 4], edx;
11733
11734 yyyy:
11735 xor eax, eax;
11736 setz al;
11737 };
11738
11739 inline unsigned __int64 _InterlockedCompareExchange64(volatile unsigned __int64 *dest
11740 ,unsigned __int64 exchange
11741 ,unsigned __int64 comperand)
11742 {
11743 //value returned in eax::edx
11744 __asm {
11745 lea esi,comperand;
11746 lea edi,exchange;
11747
11748 mov eax,[esi];
11749 mov edx,4[esi];
11750 mov ebx,[edi];
11751 mov ecx,4[edi];
11752 mov esi,dest;
11753 lock CMPXCHG8B [esi];
11754 }
11755 #endif // #if 0
11756
11757 #endif // _WIN32
11758
11759 stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11760 {
11761 return stb_create_thread_raw(f,d,return_code,rel);
11762 }
11763
11764 stb_thread stb_create_thread(stb_thread_func f, void *d)
11765 {
11766 return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL);
11767 }
11768
11769 // mutex implemented by wrapping semaphore
11770 #ifndef STB_MUTEX_NATIVE
11771 stb_mutex stb_mutex_new(void) { return stb_sem_new_extra(1,1); }
11772 void stb_mutex_delete(stb_mutex m) { stb_sem_delete (m); }
11773 void stb_mutex_begin(stb_mutex m) { stb__wait(500); if (m) stb_sem_waitfor(m); }
11774 void stb_mutex_end(stb_mutex m) { if (m) stb_sem_release(m); stb__wait(500); }
11775 #endif
11776
11777 // thread merge operation
11778 struct stb__sync
11779 {
11780 int target; // target number of threads to hit it
11781 int sofar; // total threads that hit it
11782 int waiting; // total threads waiting
11783
11784 stb_mutex start; // mutex to prevent starting again before finishing previous
11785 stb_mutex mutex; // mutex while tweaking state
11786 stb_semaphore release; // semaphore wake up waiting threads
11787 // we have to wake them up one at a time, rather than using a single release
11788 // call, because win32 semaphores don't let you dynamically change the max count!
11789 };
11790
11791 stb_sync stb_sync_new(void)
11792 {
11793 stb_sync s = (stb_sync) malloc(sizeof(*s));
11794 if (!s) return s;
11795
11796 s->target = s->sofar = s->waiting = 0;
11797 s->mutex = stb_mutex_new();
11798 s->start = stb_mutex_new();
11799 s->release = stb_sem_new(1);
11800 if (s->mutex == STB_MUTEX_NULL || s->release == STB_SEMAPHORE_NULL || s->start == STB_MUTEX_NULL) {
11801 stb_mutex_delete(s->mutex);
11802 stb_mutex_delete(s->mutex);
11803 stb_sem_delete(s->release);
11804 free(s);
11805 return NULL;
11806 }
11807 return s;
11808 }
11809
11810 void stb_sync_delete(stb_sync s)
11811 {
11812 if (s->waiting) {
11813 // it's bad to delete while there are threads waiting!
11814 // shall we wait for them to reach, or just bail? just bail
11815 assert(0);
11816 }
11817 stb_mutex_delete(s->mutex);
11818 stb_mutex_delete(s->release);
11819 free(s);
11820 }
11821
11822 int stb_sync_set_target(stb_sync s, int count)
11823 {
11824 // don't allow setting a target until the last one is fully released;
11825 // note that this can lead to inefficient pipelining, and maybe we'd
11826 // be better off ping-ponging between two internal syncs?
11827 // I tried seeing how often this happened using TryEnterCriticalSection
11828 // and could _never_ get it to happen in imv(stb), even with more threads
11829 // than processors. So who knows!
11830 stb_mutex_begin(s->start);
11831
11832 // this mutex is pointless, since it's not valid for threads
11833 // to call reach() before anyone calls set_target() anyway
11834 stb_mutex_begin(s->mutex);
11835
11836 assert(s->target == 0); // enforced by start mutex
11837 s->target = count;
11838 s->sofar = 0;
11839 s->waiting = 0;
11840 stb_mutex_end(s->mutex);
11841 return STB_TRUE;
11842 }
11843
11844 void stb__sync_release(stb_sync s)
11845 {
11846 if (s->waiting)
11847 stb_sem_release(s->release);
11848 else {
11849 s->target = 0;
11850 stb_mutex_end(s->start);
11851 }
11852 }
11853
11854 int stb_sync_reach(stb_sync s)
11855 {
11856 int n;
11857 stb_mutex_begin(s->mutex);
11858 assert(s->sofar < s->target);
11859 n = ++s->sofar; // record this value to avoid possible race if we did 'return s->sofar';
11860 if (s->sofar == s->target)
11861 stb__sync_release(s);
11862 stb_mutex_end(s->mutex);
11863 return n;
11864 }
11865
11866 void stb_sync_reach_and_wait(stb_sync s)
11867 {
11868 stb_mutex_begin(s->mutex);
11869 assert(s->sofar < s->target);
11870 ++s->sofar;
11871 if (s->sofar == s->target) {
11872 stb__sync_release(s);
11873 stb_mutex_end(s->mutex);
11874 } else {
11875 ++s->waiting; // we're waiting, so one more waiter
11876 stb_mutex_end(s->mutex); // release the mutex to other threads
11877
11878 stb_sem_waitfor(s->release); // wait for merge completion
11879
11880 stb_mutex_begin(s->mutex); // on merge completion, grab the mutex
11881 --s->waiting; // we're done waiting
11882 stb__sync_release(s); // restart the next waiter
11883 stb_mutex_end(s->mutex); // and now we're done
11884 // this ends the same as the first case, but it's a lot
11885 // clearer to understand without sharing the code
11886 }
11887 }
11888
11889 struct stb__threadqueue
11890 {
11891 stb_mutex add, remove;
11892 stb_semaphore nonempty, nonfull;
11893 int head_blockers; // number of threads blocking--used to know whether to release(avail)
11894 int tail_blockers;
11895 int head, tail, array_size, growable;
11896 int item_size;
11897 char *data;
11898 };
11899
11900 static int stb__tq_wrap(volatile stb_threadqueue *z, int p)
11901 {
11902 if (p == z->array_size)
11903 return p - z->array_size;
11904 else
11905 return p;
11906 }
11907
11908 int stb__threadq_get_raw(stb_threadqueue *tq2, void *output, int block)
11909 {
11910 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11911 if (tq->head == tq->tail && !block) return 0;
11912
11913 stb_mutex_begin(tq->remove);
11914
11915 while (tq->head == tq->tail) {
11916 if (!block) {
11917 stb_mutex_end(tq->remove);
11918 return 0;
11919 }
11920 ++tq->head_blockers;
11921 stb_mutex_end(tq->remove);
11922
11923 stb_sem_waitfor(tq->nonempty);
11924
11925 stb_mutex_begin(tq->remove);
11926 --tq->head_blockers;
11927 }
11928
11929 memcpy(output, tq->data + tq->head*tq->item_size, tq->item_size);
11930 stb_barrier();
11931 tq->head = stb__tq_wrap(tq, tq->head+1);
11932
11933 stb_sem_release(tq->nonfull);
11934 if (tq->head_blockers) // can't check if actually non-empty due to race?
11935 stb_sem_release(tq->nonempty); // if there are other blockers, wake one
11936
11937 stb_mutex_end(tq->remove);
11938 return STB_TRUE;
11939 }
11940
11941 int stb__threadq_grow(volatile stb_threadqueue *tq)
11942 {
11943 int n;
11944 char *p;
11945 assert(tq->remove != STB_MUTEX_NULL); // must have this to allow growth!
11946 stb_mutex_begin(tq->remove);
11947
11948 n = tq->array_size * 2;
11949 p = (char *) realloc(tq->data, n * tq->item_size);
11950 if (p == NULL) {
11951 stb_mutex_end(tq->remove);
11952 stb_mutex_end(tq->add);
11953 return STB_FALSE;
11954 }
11955 if (tq->tail < tq->head) {
11956 memcpy(p + tq->array_size * tq->item_size, p, tq->tail * tq->item_size);
11957 tq->tail += tq->array_size;
11958 }
11959 tq->data = p;
11960 tq->array_size = n;
11961
11962 stb_mutex_end(tq->remove);
11963 return STB_TRUE;
11964 }
11965
11966 int stb__threadq_add_raw(stb_threadqueue *tq2, void *input, int block)
11967 {
11968 int tail,pos;
11969 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11970 stb_mutex_begin(tq->add);
11971 for(;;) {
11972 pos = tq->tail;
11973 tail = stb__tq_wrap(tq, pos+1);
11974 if (tail != tq->head) break;
11975
11976 // full
11977 if (tq->growable) {
11978 if (!stb__threadq_grow(tq)) {
11979 stb_mutex_end(tq->add);
11980 return STB_FALSE; // out of memory
11981 }
11982 } else if (!block) {
11983 stb_mutex_end(tq->add);
11984 return STB_FALSE;
11985 } else {
11986 ++tq->tail_blockers;
11987 stb_mutex_end(tq->add);
11988
11989 stb_sem_waitfor(tq->nonfull);
11990
11991 stb_mutex_begin(tq->add);
11992 --tq->tail_blockers;
11993 }
11994 }
11995 memcpy(tq->data + tq->item_size * pos, input, tq->item_size);
11996 stb_barrier();
11997 tq->tail = tail;
11998 stb_sem_release(tq->nonempty);
11999 if (tq->tail_blockers) // can't check if actually non-full due to race?
12000 stb_sem_release(tq->nonfull);
12001 stb_mutex_end(tq->add);
12002 return STB_TRUE;
12003 }
12004
12005 int stb_threadq_length(stb_threadqueue *tq2)
12006 {
12007 int a,b,n;
12008 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
12009 stb_mutex_begin(tq->add);
12010 a = tq->head;
12011 b = tq->tail;
12012 n = tq->array_size;
12013 stb_mutex_end(tq->add);
12014 if (a > b) b += n;
12015 return b-a;
12016 }
12017
12018 int stb_threadq_get(stb_threadqueue *tq, void *output)
12019 {
12020 return stb__threadq_get_raw(tq, output, STB_FALSE);
12021 }
12022
12023 void stb_threadq_get_block(stb_threadqueue *tq, void *output)
12024 {
12025 stb__threadq_get_raw(tq, output, STB_TRUE);
12026 }
12027
12028 int stb_threadq_add(stb_threadqueue *tq, void *input)
12029 {
12030 return stb__threadq_add_raw(tq, input, STB_FALSE);
12031 }
12032
12033 int stb_threadq_add_block(stb_threadqueue *tq, void *input)
12034 {
12035 return stb__threadq_add_raw(tq, input, STB_TRUE);
12036 }
12037
12038 void stb_threadq_delete(stb_threadqueue *tq)
12039 {
12040 if (tq) {
12041 free(tq->data);
12042 stb_mutex_delete(tq->add);
12043 stb_mutex_delete(tq->remove);
12044 stb_sem_delete(tq->nonempty);
12045 stb_sem_delete(tq->nonfull);
12046 free(tq);
12047 }
12048 }
12049
12050 #define STB_THREADQUEUE_DYNAMIC 0
12051 stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove)
12052 {
12053 int error=0;
12054 stb_threadqueue *tq = (stb_threadqueue *) malloc(sizeof(*tq));
12055 if (tq == NULL) return NULL;
12056
12057 if (num_items == STB_THREADQUEUE_DYNAMIC) {
12058 tq->growable = STB_TRUE;
12059 num_items = 32;
12060 } else
12061 tq->growable = STB_FALSE;
12062
12063 tq->item_size = item_size;
12064 tq->array_size = num_items+1;
12065
12066 tq->add = tq->remove = STB_MUTEX_NULL;
12067 tq->nonempty = tq->nonfull = STB_SEMAPHORE_NULL;
12068 tq->data = NULL;
12069 if (many_add)
12070 { tq->add = stb_mutex_new(); if (tq->add == STB_MUTEX_NULL) goto error; }
12071 if (many_remove || tq->growable)
12072 { tq->remove = stb_mutex_new(); if (tq->remove == STB_MUTEX_NULL) goto error; }
12073 tq->nonempty = stb_sem_new(1); if (tq->nonempty == STB_SEMAPHORE_NULL) goto error;
12074 tq->nonfull = stb_sem_new(1); if (tq->nonfull == STB_SEMAPHORE_NULL) goto error;
12075 tq->data = (char *) malloc(tq->item_size * tq->array_size);
12076 if (tq->data == NULL) goto error;
12077
12078 tq->head = tq->tail = 0;
12079 tq->head_blockers = tq->tail_blockers = 0;
12080
12081 return tq;
12082
12083 error:
12084 stb_threadq_delete(tq);
12085 return NULL;
12086 }
12087
12088 typedef struct
12089 {
12090 stb_thread_func f;
12091 void *d;
12092 volatile void **retval;
12093 stb_sync sync;
12094 } stb__workinfo;
12095
12096 //static volatile stb__workinfo *stb__work;
12097
12098 struct stb__workqueue
12099 {
12100 int numthreads;
12101 stb_threadqueue *tq;
12102 };
12103
12104 static stb_workqueue *stb__work_global;
12105
12106 static void *stb__thread_workloop(void *p)
12107 {
12108 volatile stb_workqueue *q = (volatile stb_workqueue *) p;
12109 for(;;) {
12110 void *z;
12111 stb__workinfo w;
12112 stb_threadq_get_block(q->tq, &w);
12113 if (w.f == NULL) // null work is a signal to end the thread
12114 return NULL;
12115 z = w.f(w.d);
12116 if (w.retval) { stb_barrier(); *w.retval = z; }
12117 if (w.sync != STB_SYNC_NULL) stb_sync_reach(w.sync);
12118 }
12119 }
12120
12121 stb_workqueue *stb_workq_new(int num_threads, int max_units)
12122 {
12123 return stb_workq_new_flags(num_threads, max_units, 0,0);
12124 }
12125
12126 stb_workqueue *stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex)
12127 {
12128 stb_workqueue *q = (stb_workqueue *) malloc(sizeof(*q));
12129 if (q == NULL) return NULL;
12130 q->tq = stb_threadq_new(sizeof(stb__workinfo), max_units, !no_add_mutex, !no_remove_mutex);
12131 if (q->tq == NULL) { free(q); return NULL; }
12132 q->numthreads = 0;
12133 stb_workq_numthreads(q, numthreads);
12134 return q;
12135 }
12136
12137 void stb_workq_delete(stb_workqueue *q)
12138 {
12139 while (stb_workq_length(q) != 0)
12140 stb__thread_sleep(1);
12141 stb_threadq_delete(q->tq);
12142 free(q);
12143 }
12144
12145 static int stb__work_maxitems = STB_THREADQUEUE_DYNAMIC;
12146
12147 static void stb_work_init(int num_threads)
12148 {
12149 if (stb__work_global == NULL) {
12150 stb__threadmutex_init();
12151 stb_mutex_begin(stb__workmutex);
12152 stb_barrier();
12153 if (*(stb_workqueue * volatile *) &stb__work_global == NULL)
12154 stb__work_global = stb_workq_new(num_threads, stb__work_maxitems);
12155 stb_mutex_end(stb__workmutex);
12156 }
12157 }
12158
12159 static int stb__work_raw(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12160 {
12161 stb__workinfo w;
12162 if (q == NULL) {
12163 stb_work_init(1);
12164 q = stb__work_global;
12165 }
12166 w.f = f;
12167 w.d = d;
12168 w.retval = return_code;
12169 w.sync = rel;
12170 return stb_threadq_add(q->tq, &w);
12171 }
12172
12173 int stb_workq_length(stb_workqueue *q)
12174 {
12175 return stb_threadq_length(q->tq);
12176 }
12177
12178 int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code)
12179 {
12180 if (f == NULL) return 0;
12181 return stb_workq_reach(q, f, d, return_code, NULL);
12182 }
12183
12184 int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12185 {
12186 if (f == NULL) return 0;
12187 return stb__work_raw(q, f, d, return_code, rel);
12188 }
12189
12190 static void stb__workq_numthreads(stb_workqueue *q, int n)
12191 {
12192 while (q->numthreads < n) {
12193 stb_create_thread(stb__thread_workloop, q);
12194 ++q->numthreads;
12195 }
12196 while (q->numthreads > n) {
12197 stb__work_raw(q, NULL, NULL, NULL, NULL);
12198 --q->numthreads;
12199 }
12200 }
12201
12202 void stb_workq_numthreads(stb_workqueue *q, int n)
12203 {
12204 stb_mutex_begin(stb__threadmutex);
12205 stb__workq_numthreads(q,n);
12206 stb_mutex_end(stb__threadmutex);
12207 }
12208
12209 int stb_work_maxunits(int n)
12210 {
12211 if (stb__work_global == NULL) {
12212 stb__work_maxitems = n;
12213 stb_work_init(1);
12214 }
12215 return stb__work_maxitems;
12216 }
12217
12218 int stb_work(stb_thread_func f, void *d, volatile void **return_code)
12219 {
12220 return stb_workq(stb__work_global, f,d,return_code);
12221 }
12222
12223 int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12224 {
12225 return stb_workq_reach(stb__work_global, f,d,return_code,rel);
12226 }
12227
12228 void stb_work_numthreads(int n)
12229 {
12230 if (stb__work_global == NULL)
12231 stb_work_init(n);
12232 else
12233 stb_workq_numthreads(stb__work_global, n);
12234 }
12235 #endif // STB_DEFINE
12236
12237
12238 //////////////////////////////////////////////////////////////////////////////
12239 //
12240 // Background disk I/O
12241 //
12242 //
12243
12244 #define STB_BGIO_READ_ALL (-1)
12245 STB_EXTERN int stb_bgio_read (char *filename, int offset, int len, stb_uchar **result, int *olen);
12246 STB_EXTERN int stb_bgio_readf (FILE *f , int offset, int len, stb_uchar **result, int *olen);
12247 STB_EXTERN int stb_bgio_read_to (char *filename, int offset, int len, stb_uchar *buffer, int *olen);
12248 STB_EXTERN int stb_bgio_readf_to(FILE *f , int offset, int len, stb_uchar *buffer, int *olen);
12249
12250 typedef struct
12251 {
12252 int have_data;
12253 int is_valid;
12254 int is_dir;
12255 time_t filetime;
12256 stb_int64 filesize;
12257 } stb_bgstat;
12258
12259 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result);
12260
12261 #ifdef STB_DEFINE
12262
12263 static stb_workqueue *stb__diskio;
12264 static stb_mutex stb__diskio_mutex;
12265
12266 void stb_thread_cleanup(void)
12267 {
12268 if (stb__work_global) stb_workq_delete(stb__work_global); stb__work_global = NULL;
12269 if (stb__threadmutex) stb_mutex_delete(stb__threadmutex); stb__threadmutex = NULL;
12270 if (stb__workmutex) stb_mutex_delete(stb__workmutex); stb__workmutex = NULL;
12271 if (stb__diskio) stb_workq_delete(stb__diskio); stb__diskio = NULL;
12272 if (stb__diskio_mutex)stb_mutex_delete(stb__diskio_mutex);stb__diskio_mutex= NULL;
12273 }
12274
12275
12276 typedef struct
12277 {
12278 char *filename;
12279 FILE *f;
12280 int offset;
12281 int len;
12282
12283 stb_bgstat *stat_out;
12284 stb_uchar *output;
12285 stb_uchar **result;
12286 int *len_output;
12287 int *flag;
12288 } stb__disk_command;
12289
12290 #define STB__MAX_DISK_COMMAND 100
12291 static stb__disk_command stb__dc_queue[STB__MAX_DISK_COMMAND];
12292 static int stb__dc_offset;
12293
12294 void stb__io_init(void)
12295 {
12296 if (!stb__diskio) {
12297 stb__threadmutex_init();
12298 stb_mutex_begin(stb__threadmutex);
12299 stb_barrier();
12300 if (*(stb_thread * volatile *) &stb__diskio == NULL) {
12301 stb__diskio_mutex = stb_mutex_new();
12302 // use many threads so OS can try to schedule seeks
12303 stb__diskio = stb_workq_new_flags(16,STB__MAX_DISK_COMMAND,STB_FALSE,STB_FALSE);
12304 }
12305 stb_mutex_end(stb__threadmutex);
12306 }
12307 }
12308
12309 static void * stb__io_error(stb__disk_command *dc)
12310 {
12311 if (dc->len_output) *dc->len_output = 0;
12312 if (dc->result) *dc->result = NULL;
12313 if (dc->flag) *dc->flag = -1;
12314 return NULL;
12315 }
12316
12317 static void * stb__io_task(void *p)
12318 {
12319 stb__disk_command *dc = (stb__disk_command *) p;
12320 int len;
12321 FILE *f;
12322 stb_uchar *buf;
12323
12324 if (dc->stat_out) {
12325 struct _stati64 s;
12326 if (!_stati64(dc->filename, &s)) {
12327 dc->stat_out->filesize = s.st_size;
12328 dc->stat_out->filetime = s.st_mtime;
12329 dc->stat_out->is_dir = s.st_mode & _S_IFDIR;
12330 dc->stat_out->is_valid = (s.st_mode & _S_IFREG) || dc->stat_out->is_dir;
12331 } else
12332 dc->stat_out->is_valid = 0;
12333 stb_barrier();
12334 dc->stat_out->have_data = 1;
12335 free(dc->filename);
12336 return 0;
12337 }
12338 if (dc->f) {
12339 #ifdef WIN32
12340 f = _fdopen(_dup(_fileno(dc->f)), "rb");
12341 #else
12342 f = fdopen(dup(fileno(dc->f)), "rb");
12343 #endif
12344 if (!f)
12345 return stb__io_error(dc);
12346 } else {
12347 f = fopen(dc->filename, "rb");
12348 free(dc->filename);
12349 if (!f)
12350 return stb__io_error(dc);
12351 }
12352
12353 len = dc->len;
12354 if (len < 0) {
12355 fseek(f, 0, SEEK_END);
12356 len = ftell(f) - dc->offset;
12357 }
12358
12359 if (fseek(f, dc->offset, SEEK_SET)) {
12360 fclose(f);
12361 return stb__io_error(dc);
12362 }
12363
12364 if (dc->output)
12365 buf = dc->output;
12366 else {
12367 buf = (stb_uchar *) malloc(len);
12368 if (buf == NULL) {
12369 fclose(f);
12370 return stb__io_error(dc);
12371 }
12372 }
12373
12374 len = fread(buf, 1, len, f);
12375 fclose(f);
12376 if (dc->len_output) *dc->len_output = len;
12377 if (dc->result) *dc->result = buf;
12378 if (dc->flag) *dc->flag = 1;
12379
12380 return NULL;
12381 }
12382
12383 int stb__io_add(char *fname, FILE *f, int off, int len, stb_uchar *out, stb_uchar **result, int *olen, int *flag, stb_bgstat *stat)
12384 {
12385 int res;
12386 stb__io_init();
12387 // do memory allocation outside of mutex
12388 if (fname) fname = stb_p_strdup(fname);
12389 stb_mutex_begin(stb__diskio_mutex);
12390 {
12391 stb__disk_command *dc = &stb__dc_queue[stb__dc_offset];
12392 dc->filename = fname;
12393 dc->f = f;
12394 dc->offset = off;
12395 dc->len = len;
12396 dc->output = out;
12397 dc->result = result;
12398 dc->len_output = olen;
12399 dc->flag = flag;
12400 dc->stat_out = stat;
12401 res = stb_workq(stb__diskio, stb__io_task, dc, NULL);
12402 if (res)
12403 stb__dc_offset = (stb__dc_offset + 1 == STB__MAX_DISK_COMMAND ? 0 : stb__dc_offset+1);
12404 }
12405 stb_mutex_end(stb__diskio_mutex);
12406 return res;
12407 }
12408
12409 int stb_bgio_read(char *filename, int offset, int len, stb_uchar **result, int *olen)
12410 {
12411 return stb__io_add(filename,NULL,offset,len,NULL,result,olen,NULL,NULL);
12412 }
12413
12414 int stb_bgio_readf(FILE *f, int offset, int len, stb_uchar **result, int *olen)
12415 {
12416 return stb__io_add(NULL,f,offset,len,NULL,result,olen,NULL,NULL);
12417 }
12418
12419 int stb_bgio_read_to(char *filename, int offset, int len, stb_uchar *buffer, int *olen)
12420 {
12421 return stb__io_add(filename,NULL,offset,len,buffer,NULL,olen,NULL,NULL);
12422 }
12423
12424 int stb_bgio_readf_to(FILE *f, int offset, int len, stb_uchar *buffer, int *olen)
12425 {
12426 return stb__io_add(NULL,f,offset,len,buffer,NULL,olen,NULL,NULL);
12427 }
12428
12429 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result)
12430 {
12431 result->have_data = 0;
12432 return stb__io_add(filename,NULL,0,0,0,NULL,0,NULL, result);
12433 }
12434 #endif
12435 #endif
12436
12437
12438
12439 //////////////////////////////////////////////////////////////////////////////
12440 //
12441 // Fast malloc implementation
12442 //
12443 // This is a clone of TCMalloc, but without the thread support.
12444 // 1. large objects are allocated directly, page-aligned
12445 // 2. small objects are allocated in homogeonous heaps, 0 overhead
12446 //
12447 // We keep an allocation table for pages a la TCMalloc. This would
12448 // require 4MB for the entire address space, but we only allocate
12449 // the parts that are in use. The overhead from using homogenous heaps
12450 // everywhere is 3MB. (That is, if you allocate 1 object of each size,
12451 // you'll use 3MB.)
12452
12453 #if defined(STB_DEFINE) && ((defined(_WIN32) && !defined(_M_AMD64)) || defined(STB_FASTMALLOC))
12454
12455 #ifdef _WIN32
12456 #ifndef _WINDOWS_
12457 #ifndef STB__IMPORT
12458 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
12459 #define STB__DW unsigned long
12460 #endif
12461 STB__IMPORT void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
12462 STB__IMPORT int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
12463 #endif
12464 #define stb__alloc_pages_raw(x) (stb_uint32) VirtualAlloc(NULL, (x), 0x3000, 0x04)
12465 #define stb__dealloc_pages_raw(p) VirtualFree((void *) p, 0, 0x8000)
12466 #else
12467 #error "Platform not currently supported"
12468 #endif
12469
12470 typedef struct stb__span
12471 {
12472 int start, len;
12473 struct stb__span *next, *prev;
12474 void *first_free;
12475 unsigned short list; // 1..256 free; 257..511 sizeclass; 0=large block
12476 short allocations; // # outstanding allocations for sizeclass
12477 } stb__span; // 24
12478
12479 static stb__span **stb__span_for_page;
12480 static int stb__firstpage, stb__lastpage;
12481 static void stb__update_page_range(int first, int last)
12482 {
12483 stb__span **sfp;
12484 int i, f,l;
12485 if (first >= stb__firstpage && last <= stb__lastpage) return;
12486 if (stb__span_for_page == NULL) {
12487 f = first;
12488 l = f+stb_max(last-f, 16384);
12489 l = stb_min(l, 1<<20);
12490 } else if (last > stb__lastpage) {
12491 f = stb__firstpage;
12492 l = f + (stb__lastpage - f) * 2;
12493 l = stb_clamp(last, l,1<<20);
12494 } else {
12495 l = stb__lastpage;
12496 f = l - (l - stb__firstpage) * 2;
12497 f = stb_clamp(f, 0,first);
12498 }
12499 sfp = (stb__span **) stb__alloc_pages_raw(sizeof(void *) * (l-f));
12500 for (i=f; i < stb__firstpage; ++i) sfp[i - f] = NULL;
12501 for ( ; i < stb__lastpage ; ++i) sfp[i - f] = stb__span_for_page[i - stb__firstpage];
12502 for ( ; i < l ; ++i) sfp[i - f] = NULL;
12503 if (stb__span_for_page) stb__dealloc_pages_raw(stb__span_for_page);
12504 stb__firstpage = f;
12505 stb__lastpage = l;
12506 stb__span_for_page = sfp;
12507 }
12508
12509 static stb__span *stb__span_free=NULL;
12510 static stb__span *stb__span_first, *stb__span_end;
12511 static stb__span *stb__span_alloc(void)
12512 {
12513 stb__span *s = stb__span_free;
12514 if (s)
12515 stb__span_free = s->next;
12516 else {
12517 if (!stb__span_first) {
12518 stb__span_first = (stb__span *) stb__alloc_pages_raw(65536);
12519 if (stb__span_first == NULL) return NULL;
12520 stb__span_end = stb__span_first + (65536 / sizeof(stb__span));
12521 }
12522 s = stb__span_first++;
12523 if (stb__span_first == stb__span_end) stb__span_first = NULL;
12524 }
12525 return s;
12526 }
12527
12528 static stb__span *stb__spanlist[512];
12529
12530 static void stb__spanlist_unlink(stb__span *s)
12531 {
12532 if (s->prev)
12533 s->prev->next = s->next;
12534 else {
12535 int n = s->list;
12536 assert(stb__spanlist[n] == s);
12537 stb__spanlist[n] = s->next;
12538 }
12539 if (s->next)
12540 s->next->prev = s->prev;
12541 s->next = s->prev = NULL;
12542 s->list = 0;
12543 }
12544
12545 static void stb__spanlist_add(int n, stb__span *s)
12546 {
12547 s->list = n;
12548 s->next = stb__spanlist[n];
12549 s->prev = NULL;
12550 stb__spanlist[n] = s;
12551 if (s->next) s->next->prev = s;
12552 }
12553
12554 #define stb__page_shift 12
12555 #define stb__page_size (1 << stb__page_shift)
12556 #define stb__page_number(x) ((x) >> stb__page_shift)
12557 #define stb__page_address(x) ((x) << stb__page_shift)
12558
12559 static void stb__set_span_for_page(stb__span *s)
12560 {
12561 int i;
12562 for (i=0; i < s->len; ++i)
12563 stb__span_for_page[s->start + i - stb__firstpage] = s;
12564 }
12565
12566 static stb__span *stb__coalesce(stb__span *a, stb__span *b)
12567 {
12568 assert(a->start + a->len == b->start);
12569 if (a->list) stb__spanlist_unlink(a);
12570 if (b->list) stb__spanlist_unlink(b);
12571 a->len += b->len;
12572 b->len = 0;
12573 b->next = stb__span_free;
12574 stb__span_free = b;
12575 stb__set_span_for_page(a);
12576 return a;
12577 }
12578
12579 static void stb__free_span(stb__span *s)
12580 {
12581 stb__span *n = NULL;
12582 if (s->start > stb__firstpage) {
12583 n = stb__span_for_page[s->start-1 - stb__firstpage];
12584 if (n && n->allocations == -2 && n->start + n->len == s->start) s = stb__coalesce(n,s);
12585 }
12586 if (s->start + s->len < stb__lastpage) {
12587 n = stb__span_for_page[s->start + s->len - stb__firstpage];
12588 if (n && n->allocations == -2 && s->start + s->len == n->start) s = stb__coalesce(s,n);
12589 }
12590 s->allocations = -2;
12591 stb__spanlist_add(s->len > 256 ? 256 : s->len, s);
12592 }
12593
12594 static stb__span *stb__alloc_pages(int num)
12595 {
12596 stb__span *s = stb__span_alloc();
12597 int p;
12598 if (!s) return NULL;
12599 p = stb__alloc_pages_raw(num << stb__page_shift);
12600 if (p == 0) { s->next = stb__span_free; stb__span_free = s; return 0; }
12601 assert(stb__page_address(stb__page_number(p)) == p);
12602 p = stb__page_number(p);
12603 stb__update_page_range(p, p+num);
12604 s->start = p;
12605 s->len = num;
12606 s->next = NULL;
12607 s->prev = NULL;
12608 stb__set_span_for_page(s);
12609 return s;
12610 }
12611
12612 static stb__span *stb__alloc_span(int pagecount)
12613 {
12614 int i;
12615 stb__span *p = NULL;
12616 for(i=pagecount; i < 256; ++i)
12617 if (stb__spanlist[i]) {
12618 p = stb__spanlist[i];
12619 break;
12620 }
12621 if (!p) {
12622 p = stb__spanlist[256];
12623 while (p && p->len < pagecount)
12624 p = p->next;
12625 }
12626 if (!p) {
12627 p = stb__alloc_pages(pagecount < 16 ? 16 : pagecount);
12628 if (p == NULL) return 0;
12629 } else
12630 stb__spanlist_unlink(p);
12631
12632 if (p->len > pagecount) {
12633 stb__span *q = stb__span_alloc();
12634 if (q) {
12635 q->start = p->start + pagecount;
12636 q->len = p->len - pagecount;
12637 p->len = pagecount;
12638 for (i=0; i < q->len; ++i)
12639 stb__span_for_page[q->start+i - stb__firstpage] = q;
12640 stb__spanlist_add(q->len > 256 ? 256 : q->len, q);
12641 }
12642 }
12643 return p;
12644 }
12645
12646 #define STB__MAX_SMALL_SIZE 32768
12647 #define STB__MAX_SIZE_CLASSES 256
12648
12649 static unsigned char stb__class_base[32];
12650 static unsigned char stb__class_shift[32];
12651 static unsigned char stb__pages_for_class[STB__MAX_SIZE_CLASSES];
12652 static int stb__size_for_class[STB__MAX_SIZE_CLASSES];
12653
12654 stb__span *stb__get_nonempty_sizeclass(int c)
12655 {
12656 int s = c + 256, i, size, tsize; // remap to span-list index
12657 char *z;
12658 void *q;
12659 stb__span *p = stb__spanlist[s];
12660 if (p) {
12661 if (p->first_free) return p; // fast path: it's in the first one in list
12662 for (p=p->next; p; p=p->next)
12663 if (p->first_free) {
12664 // move to front for future queries
12665 stb__spanlist_unlink(p);
12666 stb__spanlist_add(s, p);
12667 return p;
12668 }
12669 }
12670 // no non-empty ones, so allocate a new one
12671 p = stb__alloc_span(stb__pages_for_class[c]);
12672 if (!p) return NULL;
12673 // create the free list up front
12674 size = stb__size_for_class[c];
12675 tsize = stb__pages_for_class[c] << stb__page_shift;
12676 i = 0;
12677 z = (char *) stb__page_address(p->start);
12678 q = NULL;
12679 while (i + size <= tsize) {
12680 * (void **) z = q; q = z;
12681 z += size;
12682 i += size;
12683 }
12684 p->first_free = q;
12685 p->allocations = 0;
12686 stb__spanlist_add(s,p);
12687 return p;
12688 }
12689
12690 static int stb__sizeclass(size_t sz)
12691 {
12692 int z = stb_log2_floor(sz); // -1 below to group e.g. 13,14,15,16 correctly
12693 return stb__class_base[z] + ((sz-1) >> stb__class_shift[z]);
12694 }
12695
12696 static void stb__init_sizeclass(void)
12697 {
12698 int i, size, overhead;
12699 int align_shift = 2; // allow 4-byte and 12-byte blocks as well, vs. TCMalloc
12700 int next_class = 1;
12701 int last_log = 0;
12702
12703 for (i = 0; i < align_shift; i++) {
12704 stb__class_base [i] = next_class;
12705 stb__class_shift[i] = align_shift;
12706 }
12707
12708 for (size = 1 << align_shift; size <= STB__MAX_SMALL_SIZE; size += 1 << align_shift) {
12709 i = stb_log2_floor(size);
12710 if (i > last_log) {
12711 if (size == 16) ++align_shift; // switch from 4-byte to 8-byte alignment
12712 else if (size >= 128 && align_shift < 8) ++align_shift;
12713 stb__class_base[i] = next_class - ((size-1) >> align_shift);
12714 stb__class_shift[i] = align_shift;
12715 last_log = i;
12716 }
12717 stb__size_for_class[next_class++] = size;
12718 }
12719
12720 for (i=1; i <= STB__MAX_SMALL_SIZE; ++i)
12721 assert(i <= stb__size_for_class[stb__sizeclass(i)]);
12722
12723 overhead = 0;
12724 for (i = 1; i < next_class; i++) {
12725 int s = stb__size_for_class[i];
12726 size = stb__page_size;
12727 while (size % s > size >> 3)
12728 size += stb__page_size;
12729 stb__pages_for_class[i] = (unsigned char) (size >> stb__page_shift);
12730 overhead += size;
12731 }
12732 assert(overhead < (4 << 20)); // make sure it's under 4MB of overhead
12733 }
12734
12735 #ifdef STB_DEBUG
12736 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12737 #elif defined(STB_FASTMALLOC_INIT)
12738 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12739 #else
12740 #define stb__smemset(a,b,c)
12741 #endif
12742 void *stb_smalloc(size_t sz)
12743 {
12744 stb__span *s;
12745 if (sz == 0) return NULL;
12746 if (stb__size_for_class[1] == 0) stb__init_sizeclass();
12747 if (sz > STB__MAX_SMALL_SIZE) {
12748 s = stb__alloc_span((sz + stb__page_size - 1) >> stb__page_shift);
12749 if (s == NULL) return NULL;
12750 s->list = 0;
12751 s->next = s->prev = NULL;
12752 s->allocations = -32767;
12753 stb__smemset(stb__page_address(s->start), 0xcd, (sz+3)&~3);
12754 return (void *) stb__page_address(s->start);
12755 } else {
12756 void *p;
12757 int c = stb__sizeclass(sz);
12758 s = stb__spanlist[256+c];
12759 if (!s || !s->first_free)
12760 s = stb__get_nonempty_sizeclass(c);
12761 if (s == NULL) return NULL;
12762 p = s->first_free;
12763 s->first_free = * (void **) p;
12764 ++s->allocations;
12765 stb__smemset(p,0xcd, sz);
12766 return p;
12767 }
12768 }
12769
12770 int stb_ssize(void *p)
12771 {
12772 stb__span *s;
12773 if (p == NULL) return 0;
12774 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12775 if (s->list >= 256) {
12776 return stb__size_for_class[s->list - 256];
12777 } else {
12778 assert(s->list == 0);
12779 return s->len << stb__page_shift;
12780 }
12781 }
12782
12783 void stb_sfree(void *p)
12784 {
12785 stb__span *s;
12786 if (p == NULL) return;
12787 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12788 if (s->list >= 256) {
12789 stb__smemset(p, 0xfe, stb__size_for_class[s->list-256]);
12790 * (void **) p = s->first_free;
12791 s->first_free = p;
12792 if (--s->allocations == 0) {
12793 stb__spanlist_unlink(s);
12794 stb__free_span(s);
12795 }
12796 } else {
12797 assert(s->list == 0);
12798 stb__smemset(p, 0xfe, stb_ssize(p));
12799 stb__free_span(s);
12800 }
12801 }
12802
12803 void *stb_srealloc(void *p, size_t sz)
12804 {
12805 size_t cur_size;
12806 if (p == NULL) return stb_smalloc(sz);
12807 if (sz == 0) { stb_sfree(p); return NULL; }
12808 cur_size = stb_ssize(p);
12809 if (sz > cur_size || sz <= (cur_size >> 1)) {
12810 void *q;
12811 if (sz > cur_size && sz < (cur_size << 1)) sz = cur_size << 1;
12812 q = stb_smalloc(sz); if (q == NULL) return NULL;
12813 memcpy(q, p, sz < cur_size ? sz : cur_size);
12814 stb_sfree(p);
12815 return q;
12816 }
12817 return p;
12818 }
12819
12820 void *stb_scalloc(size_t n, size_t sz)
12821 {
12822 void *p;
12823 if (n == 0 || sz == 0) return NULL;
12824 if (stb_log2_ceil(n) + stb_log2_ceil(n) >= 32) return NULL;
12825 p = stb_smalloc(n*sz);
12826 if (p) memset(p, 0, n*sz);
12827 return p;
12828 }
12829
12830 char *stb_sstrdup(char *s)
12831 {
12832 int n = strlen(s);
12833 char *p = (char *) stb_smalloc(n+1);
12834 if (p) stb_p_strcpy_s(p,n+1,s);
12835 return p;
12836 }
12837 #endif // STB_DEFINE
12838
12839
12840
12841 //////////////////////////////////////////////////////////////////////////////
12842 //
12843 // Source code constants
12844 //
12845 // This is a trivial system to let you specify constants in source code,
12846 // then while running you can change the constants.
12847 //
12848 // Note that you can't wrap the #defines, because we need to know their
12849 // names. So we provide a pre-wrapped version without 'STB_' for convenience;
12850 // to request it, #define STB_CONVENIENT_H, yielding:
12851 // KI -- integer
12852 // KU -- unsigned integer
12853 // KF -- float
12854 // KD -- double
12855 // KS -- string constant
12856 //
12857 // Defaults to functioning in debug build, not in release builds.
12858 // To force on, define STB_ALWAYS_H
12859
12860 #ifdef STB_CONVENIENT_H
12861 #define KI(x) STB_I(x)
12862 #define KU(x) STB_UI(x)
12863 #define KF(x) STB_F(x)
12864 #define KD(x) STB_D(x)
12865 #define KS(x) STB_S(x)
12866 #endif
12867
12868 STB_EXTERN void stb_source_path(char *str);
12869 #ifdef STB_DEFINE
12870 char *stb__source_path;
12871 void stb_source_path(char *path)
12872 {
12873 stb__source_path = path;
12874 }
12875
12876 char *stb__get_sourcefile_path(char *file)
12877 {
12878 static char filebuf[512];
12879 if (stb__source_path) {
12880 stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "%s/%s", stb__source_path, file);
12881 if (stb_fexists(filebuf)) return filebuf;
12882 }
12883
12884 if (stb_fexists(file)) return file;
12885
12886 stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "../%s", file);
12887 if (!stb_fexists(filebuf)) return filebuf;
12888
12889 return file;
12890 }
12891 #endif
12892
12893 #define STB_F(x) ((float) STB_H(x))
12894 #define STB_UI(x) ((unsigned int) STB_I(x))
12895
12896 #if !defined(STB_DEBUG) && !defined(STB_ALWAYS_H)
12897 #define STB_D(x) ((double) (x))
12898 #define STB_I(x) ((int) (x))
12899 #define STB_S(x) ((char *) (x))
12900 #else
12901 #define STB_D(x) stb__double_constant(__FILE__, __LINE__-1, (x))
12902 #define STB_I(x) stb__int_constant(__FILE__, __LINE__-1, (x))
12903 #define STB_S(x) stb__string_constant(__FILE__, __LINE__-1, (x))
12904
12905 STB_EXTERN double stb__double_constant(char *file, int line, double x);
12906 STB_EXTERN int stb__int_constant(char *file, int line, int x);
12907 STB_EXTERN char * stb__string_constant(char *file, int line, char *str);
12908
12909 #ifdef STB_DEFINE
12910
12911 enum
12912 {
12913 STB__CTYPE_int,
12914 STB__CTYPE_uint,
12915 STB__CTYPE_float,
12916 STB__CTYPE_double,
12917 STB__CTYPE_string,
12918 };
12919
12920 typedef struct
12921 {
12922 int line;
12923 int type;
12924 union {
12925 int ival;
12926 double dval;
12927 char *sval;
12928 };
12929 } stb__Entry;
12930
12931 typedef struct
12932 {
12933 stb__Entry *entries;
12934 char *filename;
12935 time_t timestamp;
12936 char **file_data;
12937 int file_len;
12938 unsigned short *line_index;
12939 } stb__FileEntry;
12940
12941 static void stb__constant_parse(stb__FileEntry *f, int i)
12942 {
12943 char *s;
12944 int n;
12945 if (!stb_arr_valid(f->entries, i)) return;
12946 n = f->entries[i].line;
12947 if (n >= f->file_len) return;
12948 s = f->file_data[n];
12949 switch (f->entries[i].type) {
12950 case STB__CTYPE_float:
12951 while (*s) {
12952 if (!strncmp(s, "STB_D(", 6)) { s+=6; goto matched_float; }
12953 if (!strncmp(s, "STB_F(", 6)) { s+=6; goto matched_float; }
12954 if (!strncmp(s, "KD(", 3)) { s+=3; goto matched_float; }
12955 if (!strncmp(s, "KF(", 3)) { s+=3; goto matched_float; }
12956 ++s;
12957 }
12958 break;
12959 matched_float:
12960 f->entries[i].dval = strtod(s, NULL);
12961 break;
12962 case STB__CTYPE_int:
12963 while (*s) {
12964 if (!strncmp(s, "STB_I(", 6)) { s+=6; goto matched_int; }
12965 if (!strncmp(s, "STB_UI(", 7)) { s+=7; goto matched_int; }
12966 if (!strncmp(s, "KI(", 3)) { s+=3; goto matched_int; }
12967 if (!strncmp(s, "KU(", 3)) { s+=3; goto matched_int; }
12968 ++s;
12969 }
12970 break;
12971 matched_int: {
12972 int neg=0;
12973 s = stb_skipwhite(s);
12974 while (*s == '-') { neg = !neg; s = stb_skipwhite(s+1); } // handle '- - 5', pointlessly
12975 if (s[0] == '0' && tolower(s[1]) == 'x')
12976 f->entries[i].ival = strtol(s, NULL, 16);
12977 else if (s[0] == '0')
12978 f->entries[i].ival = strtol(s, NULL, 8);
12979 else
12980 f->entries[i].ival = strtol(s, NULL, 10);
12981 if (neg) f->entries[i].ival = -f->entries[i].ival;
12982 break;
12983 }
12984 case STB__CTYPE_string:
12985 // @TODO
12986 break;
12987 }
12988 }
12989
12990 static stb_sdict *stb__constant_file_hash;
12991
12992 stb__Entry *stb__constant_get_entry(char *filename, int line, int type)
12993 {
12994 int i;
12995 stb__FileEntry *f;
12996 if (stb__constant_file_hash == NULL)
12997 stb__constant_file_hash = stb_sdict_new(STB_TRUE);
12998 f = (stb__FileEntry*) stb_sdict_get(stb__constant_file_hash, filename);
12999 if (f == NULL) {
13000 char *s = stb__get_sourcefile_path(filename);
13001 if (s == NULL || !stb_fexists(s)) return 0;
13002 f = (stb__FileEntry *) malloc(sizeof(*f));
13003 f->timestamp = stb_ftimestamp(s);
13004 f->file_data = stb_stringfile(s, &f->file_len);
13005 f->filename = stb_p_strdup(s); // cache the full path
13006 f->entries = NULL;
13007 f->line_index = 0;
13008 stb_arr_setlen(f->line_index, f->file_len);
13009 memset(f->line_index, 0xff, stb_arr_storage(f->line_index));
13010 } else {
13011 time_t t = stb_ftimestamp(f->filename);
13012 if (f->timestamp != t) {
13013 f->timestamp = t;
13014 free(f->file_data);
13015 f->file_data = stb_stringfile(f->filename, &f->file_len);
13016 stb_arr_setlen(f->line_index, f->file_len);
13017 for (i=0; i < stb_arr_len(f->entries); ++i)
13018 stb__constant_parse(f, i);
13019 }
13020 }
13021
13022 if (line >= f->file_len) return 0;
13023
13024 if (f->line_index[line] >= stb_arr_len(f->entries)) {
13025 // need a new entry
13026 int n = stb_arr_len(f->entries);
13027 stb__Entry e;
13028 e.line = line;
13029 if (line < f->file_len)
13030 f->line_index[line] = n;
13031 e.type = type;
13032 stb_arr_push(f->entries, e);
13033 stb__constant_parse(f, n);
13034 }
13035 return f->entries + f->line_index[line];
13036 }
13037
13038 double stb__double_constant(char *file, int line, double x)
13039 {
13040 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_float);
13041 if (!e) return x;
13042 return e->dval;
13043 }
13044
13045 int stb__int_constant(char *file, int line, int x)
13046 {
13047 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_int);
13048 if (!e) return x;
13049 return e->ival;
13050 }
13051
13052 char * stb__string_constant(char *file, int line, char *x)
13053 {
13054 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_string);
13055 if (!e) return x;
13056 return e->sval;
13057 }
13058
13059 #endif // STB_DEFINE
13060 #endif // !STB_DEBUG && !STB_ALWAYS_H
13061
13062
13063 #ifdef STB_STUA
13064 #error "STUA is no longer supported"
13065 //////////////////////////////////////////////////////////////////////////
13066 //
13067 // stua: little scripting language
13068 //
13069 // define STB_STUA to compile it
13070 //
13071 // see http://nothings.org/stb/stb_stua.html for documentation
13072 //
13073 // basic parsing model:
13074 //
13075 // lexical analysis
13076 // use stb_lex() to parse tokens; keywords get their own tokens
13077 //
13078 // parsing:
13079 // recursive descent parser. too much of a hassle to make an unambiguous
13080 // LR(1) grammar, and one-pass generation is clumsier (recursive descent
13081 // makes it easier to e.g. compile nested functions). on the other hand,
13082 // dictionary syntax required hackery to get extra lookahead.
13083 //
13084 // codegen:
13085 // output into an evaluation tree, using array indices as 'pointers'
13086 //
13087 // run:
13088 // traverse the tree; support for 'break/continue/return' is tricky
13089 //
13090 // garbage collection:
13091 // stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots
13092
13093 typedef stb_int32 stua_obj;
13094
13095 typedef stb_idict stua_dict;
13096
13097 STB_EXTERN void stua_run_script(char *s);
13098 STB_EXTERN void stua_uninit(void);
13099
13100 extern stua_obj stua_globals;
13101
13102 STB_EXTERN double stua_number(stua_obj z);
13103
13104 STB_EXTERN stua_obj stua_getnil(void);
13105 STB_EXTERN stua_obj stua_getfalse(void);
13106 STB_EXTERN stua_obj stua_gettrue(void);
13107 STB_EXTERN stua_obj stua_string(char *z);
13108 STB_EXTERN stua_obj stua_make_number(double d);
13109 STB_EXTERN stua_obj stua_box(int type, void *data, int size);
13110
13111 enum
13112 {
13113 STUA_op_negate=129,
13114 STUA_op_shl, STUA_op_ge,
13115 STUA_op_shr, STUA_op_le,
13116 STUA_op_shru,
13117 STUA_op_last
13118 };
13119
13120 #define STUA_NO_VALUE 2 // equivalent to a tagged NULL
13121 STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c);
13122
13123 STB_EXTERN stua_obj stua_error(char *err, ...);
13124
13125 STB_EXTERN stua_obj stua_pushroot(stua_obj o);
13126 STB_EXTERN void stua_poproot ( void );
13127
13128
13129 #ifdef STB_DEFINE
13130 // INTERPRETER
13131
13132 // 31-bit floating point implementation
13133 // force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent;
13134 // then shift and set the bottom bit
13135
13136 static stua_obj stu__floatp(float *f)
13137 {
13138 unsigned int n = *(unsigned int *) f;
13139 unsigned int e = n & (0xff << 23);
13140
13141 assert(sizeof(int) == 4 && sizeof(float) == 4);
13142
13143 if (!e) // zero?
13144 n = n; // no change
13145 else if (e < (64 << 23)) // underflow of the packed encoding?
13146 n = (n & 0x80000000); // signed 0
13147 else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN)
13148 n = (n & 0x80000000) + (127 << 23); // new INF encoding
13149 else
13150 n -= 0x20000000;
13151
13152 // now we need to shuffle the bits so that the spare bit is at the bottom
13153 assert((n & 0x40000000) == 0);
13154 return (n & 0x80000000) + (n << 1) + 1;
13155 }
13156
13157 static unsigned char stu__getfloat_addend[256];
13158 static float stu__getfloat(stua_obj v)
13159 {
13160 unsigned int n;
13161 unsigned int e = ((unsigned int) v) >> 24;
13162
13163 n = (int) v >> 1; // preserve high bit
13164 n += stu__getfloat_addend[e] << 24;
13165 return *(float *) &n;
13166 }
13167
13168 stua_obj stua_float(float f)
13169 {
13170 return stu__floatp(&f);
13171 }
13172
13173 static void stu__float_init(void)
13174 {
13175 int i;
13176 stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0
13177 for (i=1; i < 127; ++i)
13178 stu__getfloat_addend[i] = 32; // undo the -0x20000000
13179 stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f)
13180
13181 for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down
13182 stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64;
13183 }
13184
13185 // Tagged data type implementation
13186
13187 // TAGS:
13188 #define stu__int_tag 0 // of 2 bits // 00 int
13189 #define stu__float_tag 1 // of 1 bit // 01 float
13190 #define stu__ptr_tag 2 // of 2 bits // 10 boxed
13191 // 11 float
13192
13193 #define stu__tag(x) ((x) & 3)
13194 #define stu__number(x) (stu__tag(x) != stu__ptr_tag)
13195 #define stu__isint(x) (stu__tag(x) == stu__int_tag)
13196
13197 #define stu__int(x) ((x) >> 2)
13198 #define stu__float(x) (stu__getfloat(x))
13199
13200 #define stu__makeint(v) ((v)*4+stu__int_tag)
13201
13202 // boxed data, and tag support for boxed data
13203
13204 enum
13205 {
13206 STU___float = 1, STU___int = 2,
13207 STU___number = 3, STU___string = 4,
13208 STU___function = 5, STU___dict = 6,
13209 STU___boolean = 7, STU___error = 8,
13210 };
13211
13212 // boxed data
13213 #define STU__BOX short type, stua_gc
13214 typedef struct stu__box { STU__BOX; } stu__box;
13215
13216 stu__box stu__nil = { 0, 1 };
13217 stu__box stu__true = { STU___boolean, 1, };
13218 stu__box stu__false = { STU___boolean, 1, };
13219
13220 #define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag)
13221
13222 #define stua_nil stu__makeptr(&stu__nil)
13223 #define stua_true stu__makeptr(&stu__true)
13224 #define stua_false stu__makeptr(&stu__false)
13225
13226 stua_obj stua_getnil(void) { return stua_nil; }
13227 stua_obj stua_getfalse(void) { return stua_false; }
13228 stua_obj stua_gettrue(void) { return stua_true; }
13229
13230 #define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag))
13231
13232 #define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \
13233 (t) == STU___int ? stu__isint(x) : \
13234 (t) == STU___number ? stu__number(x) : \
13235 stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t))
13236
13237 typedef struct
13238 {
13239 STU__BOX;
13240 void *ptr;
13241 } stu__wrapper;
13242
13243 // implementation of a 'function' or function + closure
13244
13245 typedef struct stu__func
13246 {
13247 STU__BOX;
13248 stua_obj closure_source; // 0 - regular function; 4 - C function
13249 // if closure, pointer to source function
13250 union {
13251 stua_obj closure_data; // partial-application data
13252 void *store; // pointer to free that holds 'code'
13253 stua_obj (*func)(stua_dict *context);
13254 } f;
13255 // closure ends here
13256 short *code;
13257 int num_param;
13258 stua_obj *param; // list of parameter strings
13259 } stu__func;
13260
13261 // apply this to 'short *code' to get at data
13262 #define stu__const(f) ((stua_obj *) (f))
13263
13264 static void stu__free_func(stu__func *f)
13265 {
13266 if (f->closure_source == 0) free(f->f.store);
13267 if ((stb_uint) f->closure_source <= 4) free(f->param);
13268 free(f);
13269 }
13270
13271 #define stu__pd(x) ((stua_dict *) stu__ptr(x))
13272 #define stu__pw(x) ((stu__wrapper *) stu__ptr(x))
13273 #define stu__pf(x) ((stu__func *) stu__ptr(x))
13274
13275
13276 // garbage-collection
13277
13278
13279 static stu__box ** stu__gc_ptrlist;
13280 static stua_obj * stu__gc_root_stack;
13281
13282 stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; }
13283 void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); }
13284
13285 static stb_sdict *stu__strings;
13286 static void stu__mark(stua_obj z)
13287 {
13288 int i;
13289 stu__box *p = stu__ptr(z);
13290 if (p->stua_gc == 1) return; // already marked
13291 assert(p->stua_gc == 0);
13292 p->stua_gc = 1;
13293 switch(p->type) {
13294 case STU___function: {
13295 stu__func *f = (stu__func *) p;
13296 if ((stb_uint) f->closure_source <= 4) {
13297 if (f->closure_source == 0) {
13298 for (i=1; i <= f->code[0]; ++i)
13299 if (!stu__number(((stua_obj *) f->code)[-i]))
13300 stu__mark(((stua_obj *) f->code)[-i]);
13301 }
13302 for (i=0; i < f->num_param; ++i)
13303 stu__mark(f->param[i]);
13304 } else {
13305 stu__mark(f->closure_source);
13306 stu__mark(f->f.closure_data);
13307 }
13308 break;
13309 }
13310 case STU___dict: {
13311 stua_dict *e = (stua_dict *) p;
13312 for (i=0; i < e->limit; ++i)
13313 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) {
13314 if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k);
13315 if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v);
13316 }
13317 break;
13318 }
13319 }
13320 }
13321
13322 static int stu__num_allocs, stu__size_allocs;
13323 static stua_obj stu__flow_val = stua_nil; // used for break & return
13324
13325 static void stua_gc(int force)
13326 {
13327 int i;
13328 if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return;
13329 stu__num_allocs = stu__size_allocs = 0;
13330 //printf("[gc]\n");
13331
13332 // clear marks
13333 for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i)
13334 stu__gc_ptrlist[i]->stua_gc = 0;
13335
13336 // stu__mark everything reachable
13337 stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1;
13338 stu__mark(stua_globals);
13339 if (!stu__number(stu__flow_val))
13340 stu__mark(stu__flow_val);
13341 for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i)
13342 if (!stu__number(stu__gc_root_stack[i]))
13343 stu__mark(stu__gc_root_stack[i]);
13344
13345 // sweep unreachables
13346 for (i=0; i < stb_arr_len(stu__gc_ptrlist);) {
13347 stu__box *z = stu__gc_ptrlist[i];
13348 if (!z->stua_gc) {
13349 switch (z->type) {
13350 case STU___dict: stb_idict_destroy((stua_dict *) z); break;
13351 case STU___error: free(((stu__wrapper *) z)->ptr); break;
13352 case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break;
13353 case STU___function: stu__free_func((stu__func *) z); break;
13354 }
13355 // swap in the last item over this, and repeat
13356 z = stb_arr_pop(stu__gc_ptrlist);
13357 stu__gc_ptrlist[i] = z;
13358 } else
13359 ++i;
13360 }
13361 }
13362
13363 static void stu__consider_gc(stua_obj x)
13364 {
13365 if (stu__size_allocs < 100000) return;
13366 if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return;
13367 stb_arr_push(stu__gc_root_stack, x);
13368 stua_gc(0);
13369 stb_arr_pop(stu__gc_root_stack);
13370 }
13371
13372 static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc)
13373 {
13374 stua_obj x = stu__makeptr(data);
13375 ((stu__box *) data)->type = type;
13376 stb_arr_push(stu__gc_ptrlist, (stu__box *) data);
13377 stu__num_allocs += 1;
13378 stu__size_allocs += size;
13379 if (safe_to_gc) stu__consider_gc(x);
13380 return x;
13381 }
13382
13383 stua_obj stua_box(int type, void *data, int size)
13384 {
13385 stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p));
13386 p->ptr = data;
13387 return stu__makeobj(type, p, size, 0);
13388 }
13389
13390 // a stu string can be directly compared for equality, because
13391 // they go into a hash table
13392 stua_obj stua_string(char *z)
13393 {
13394 stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z);
13395 if (b == NULL) {
13396 int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b));
13397 b = stu__pw(o);
13398 stb_sdict_add(stu__strings, z, b);
13399 stb_sdict_getkey(stu__strings, z, (char **) &b->ptr);
13400 }
13401 return stu__makeptr(b);
13402 }
13403
13404 // stb_obj dictionary is just an stb_idict
13405 static void stu__set(stua_dict *d, stua_obj k, stua_obj v)
13406 { if (stb_idict_set(d, k, v)) stu__size_allocs += 8; }
13407
13408 static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res)
13409 {
13410 stb_idict_get_flag(d, k, &res);
13411 return res;
13412 }
13413
13414 static stua_obj make_string(char *z, int len)
13415 {
13416 stua_obj s;
13417 char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q;
13418 while (len > 0) {
13419 if (*z == '\\') {
13420 if (z[1] == 'n') *p = '\n';
13421 else if (z[1] == 'r') *p = '\r';
13422 else if (z[1] == 't') *p = '\t';
13423 else *p = z[1];
13424 p += 1; z += 2; len -= 2;
13425 } else {
13426 *p++ = *z++; len -= 1;
13427 }
13428 }
13429 *p = 0;
13430 s = stua_string(q);
13431 stb_tempfree(temp, q);
13432 return s;
13433 }
13434
13435 enum token_names
13436 {
13437 T__none=128,
13438 ST_shl = STUA_op_shl, ST_ge = STUA_op_ge,
13439 ST_shr = STUA_op_shr, ST_le = STUA_op_le,
13440 ST_shru = STUA_op_shru, STU__negate = STUA_op_negate,
13441 ST__reset_numbering = STUA_op_last,
13442 ST_white,
13443 ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number,
13444 // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them
13445 ST_if, ST_while, ST_for, ST_eq, ST_nil,
13446 ST_then, ST_do, ST_in, ST_ne, ST_true,
13447 ST_else, ST_break, ST_let, ST_and, ST_false,
13448 ST_elseif, ST_continue, ST_into, ST_or, ST_repeat,
13449 ST_end, ST_as, ST_return, ST_var, ST_func,
13450 ST_catch, ST__frame,
13451 ST__max_terminals,
13452
13453 STU__defaultparm, STU__seq,
13454 };
13455
13456 static stua_dict * stu__globaldict;
13457 stua_obj stua_globals;
13458
13459 static enum
13460 {
13461 FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error,
13462 } stu__flow;
13463
13464 stua_obj stua_error(char *z, ...)
13465 {
13466 stua_obj a;
13467 char temp[4096], *x;
13468 va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v);
13469 x = stb_p_strdup(temp);
13470 a = stua_box(STU___error, x, strlen(x));
13471 stu__flow = FLOW_error;
13472 stu__flow_val = a;
13473 return stua_nil;
13474 }
13475
13476 double stua_number(stua_obj z)
13477 {
13478 return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z);
13479 }
13480
13481 stua_obj stua_make_number(double d)
13482 {
13483 double e = floor(d);
13484 if (e == d && e < (1 << 29) && e >= -(1 << 29))
13485 return stu__makeint((int) e);
13486 else
13487 return stua_float((float) d);
13488 }
13489
13490 stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL;
13491
13492 static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c)
13493 {
13494 stua_obj r = STUA_NO_VALUE;
13495 if (op == '+') {
13496 if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) {
13497 ;// @TODO: string concatenation
13498 } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) {
13499 stu__func *f = (stu__func *) malloc(12);
13500 assert(offsetof(stu__func, code)==12);
13501 f->closure_source = a;
13502 f->f.closure_data = b;
13503 return stu__makeobj(STU___function, f, 16, 1);
13504 }
13505 }
13506 if (stua_overload) r = stua_overload(op,a,b,c);
13507 if (stu__flow != FLOW_error && r == STUA_NO_VALUE)
13508 stua_error("Typecheck for operator %d", op), r=stua_nil;
13509 return r;
13510 }
13511
13512 #define STU__EVAL2(a,b) \
13513 a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \
13514 b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break;
13515
13516 #define STU__FB(op) \
13517 STU__EVAL2(a,b) \
13518 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13519 return ((a) op (b)); \
13520 if (stu__number(a) && stu__number(b)) \
13521 return stua_make_number(stua_number(a) op stua_number(b)); \
13522 return stu__op(stu__f[n], a,b, stua_nil)
13523
13524 #define STU__F(op) \
13525 STU__EVAL2(a,b) \
13526 if (stu__number(a) && stu__number(b)) \
13527 return stua_make_number(stua_number(a) op stua_number(b)); \
13528 return stu__op(stu__f[n], a,b, stua_nil)
13529
13530 #define STU__I(op) \
13531 STU__EVAL2(a,b) \
13532 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13533 return stu__makeint(stu__int(a) op stu__int(b)); \
13534 return stu__op(stu__f[n], a,b, stua_nil)
13535
13536 #define STU__C(op) \
13537 STU__EVAL2(a,b) \
13538 if (stu__number(a) && stu__number(b)) \
13539 return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \
13540 return stu__op(stu__f[n], a,b, stua_nil)
13541
13542 #define STU__CE(op) \
13543 STU__EVAL2(a,b) \
13544 return (a op b) ? stua_true : stua_false
13545
13546 static short *stu__f;
13547 static stua_obj stu__f_obj;
13548 static stua_dict *stu__c;
13549 static stua_obj stu__funceval(stua_obj fo, stua_obj co);
13550
13551 static int stu__cond(stua_obj x)
13552 {
13553 if (stu__flow) return 0;
13554 if (!stu__checkt(STU___boolean, x))
13555 x = stu__op('!', x, stua_nil, stua_nil);
13556 if (x == stua_true ) return 1;
13557 if (x == stua_false) return 0;
13558 stu__flow = FLOW_error;
13559 return 0;
13560 }
13561
13562 // had to manually eliminate tailcall recursion for debugging complex stuff
13563 #define TAILCALL(x) n = (x); goto top;
13564 static stua_obj stu__eval(int n)
13565 {
13566 top:
13567 if (stu__flow >= FLOW_return) return stua_nil; // is this needed?
13568 if (n < 0) return stu__const(stu__f)[n];
13569 assert(n != 0 && n != 1);
13570 switch (stu__f[n]) {
13571 stua_obj a,b,c;
13572 case ST_catch: a = stu__eval(stu__f[n+1]);
13573 if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; }
13574 return a;
13575 case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break;
13576 stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b);
13577 return b;
13578 case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break;
13579 TAILCALL(stu__f[n+2]);
13580 case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil;
13581 TAILCALL(stu__f[n+2]);
13582 case ST_else: a = stu__cond(stu__eval(stu__f[n+1]));
13583 TAILCALL(stu__f[n + 2 + !a]);
13584 #define STU__HANDLE_BREAK \
13585 if (stu__flow >= FLOW_break) { \
13586 if (stu__flow == FLOW_break) { \
13587 a = stu__flow_val; \
13588 stu__flow = FLOW_normal; \
13589 stu__flow_val = stua_nil; \
13590 return a; \
13591 } \
13592 return stua_nil; \
13593 }
13594 case ST_as: stu__eval(stu__f[n+3]);
13595 STU__HANDLE_BREAK
13596 // fallthrough!
13597 case ST_while: a = stua_nil; stua_pushroot(a);
13598 while (stu__cond(stu__eval(stu__f[n+1]))) {
13599 stua_poproot();
13600 a = stu__eval(stu__f[n+2]);
13601 STU__HANDLE_BREAK
13602 stu__flow = FLOW_normal; // clear 'continue' flag
13603 stua_pushroot(a);
13604 if (stu__f[n+3]) stu__eval(stu__f[n+3]);
13605 STU__HANDLE_BREAK
13606 stu__flow = FLOW_normal; // clear 'continue' flag
13607 }
13608 stua_poproot();
13609 return a;
13610 case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break;
13611 case ST_continue:stu__flow = FLOW_continue; break;
13612 case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break;
13613 case ST__frame: return stu__f_obj;
13614 case '[': STU__EVAL2(a,b);
13615 if (stu__checkt(STU___dict, a))
13616 return stu__get(stu__pd(a), b, stua_nil);
13617 return stu__op(stu__f[n], a, b, stua_nil);
13618 case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break;
13619 n = stu__f[n+1];
13620 if (stu__f[n] == ST_id) {
13621 if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13622 if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a))
13623 return stua_error("Assignment to undefined variable");
13624 } else if (stu__f[n] == '[') {
13625 stua_pushroot(a);
13626 b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; }
13627 stua_pushroot(b);
13628 c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot();
13629 if (stu__flow) break;
13630 if (!stu__checkt(STU___dict, b)) return stua_nil;
13631 stu__set(stu__pd(b), c, a);
13632 } else {
13633 return stu__op(stu__f[n], stu__eval(n), a, stua_nil);
13634 }
13635 return a;
13636 case STU__defaultparm:
13637 a = stu__eval(stu__f[n+2]);
13638 stu__flow = FLOW_normal;
13639 if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13640 stu__size_allocs += 8;
13641 return stua_nil;
13642 case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable
13643 return a != STUA_NO_VALUE // else try stu__compile_global_scope variable
13644 ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil);
13645 case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13646 return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil);
13647 case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13648 return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil);
13649 case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13650 a = stu__cond(a); if (stu__flow) break;
13651 return a ? stua_true : stua_false;
13652 case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<);
13653 case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>);
13654 case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<);
13655 case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>);
13656 case '%': STU__I(%); case '^': STU__I(^);
13657 case ST_shru: STU__EVAL2(a,b);
13658 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag)
13659 return stu__makeint((unsigned) stu__int(a) >> stu__int(b));
13660 return stu__op(stu__f[n], a,b, stua_nil);
13661 case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13662 return a ? stu__eval(stu__f[n+2]) : a;
13663 case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13664 return a ? b : stu__eval(stu__f[n+2]);
13665 case'(':case':': STU__EVAL2(a,b);
13666 if (!stu__checkt(STU___function, a))
13667 return stu__op(stu__f[n], a,b, stua_nil);
13668 if (!stu__checkt(STU___dict, b))
13669 return stua_nil;
13670 if (stu__f[n] == ':')
13671 b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0);
13672 a = stu__funceval(a,b);
13673 return a;
13674 case '{' : {
13675 stua_dict *d;
13676 d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16);
13677 if (d == NULL)
13678 return stua_nil; // breakpoint fodder
13679 c = stu__makeobj(STU___dict, d, 32, 1);
13680 stua_pushroot(c);
13681 a = stu__f[n+1];
13682 for (b=0; b < a; ++b) {
13683 stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0]));
13684 stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]);
13685 stua_poproot();
13686 if (stu__flow) { stua_poproot(); return stua_nil; }
13687 stu__set(d, x, y);
13688 }
13689 stua_poproot();
13690 return c;
13691 }
13692 default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]];
13693 assert(0); /* NOTREACHED */ // internal error!
13694 }
13695 return stua_nil;
13696 }
13697
13698 int stb__stua_nesting;
13699 static stua_obj stu__funceval(stua_obj fo, stua_obj co)
13700 {
13701 stu__func *f = stu__pf(fo);
13702 stua_dict *context = stu__pd(co);
13703 int i,j;
13704 stua_obj p;
13705 short *tf = stu__f; // save previous function
13706 stua_dict *tc = stu__c;
13707
13708 if (stu__flow == FLOW_error) return stua_nil;
13709 assert(stu__flow == FLOW_normal);
13710
13711 stua_pushroot(fo);
13712 stua_pushroot(co);
13713 stu__consider_gc(stua_nil);
13714
13715 while ((stb_uint) f->closure_source > 4) {
13716 // add data from closure to context
13717 stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data);
13718 for (i=0; i < e->limit; ++i)
13719 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL)
13720 if (stb_idict_add(context, e->table[i].k, e->table[i].v))
13721 stu__size_allocs += 8;
13722 // use add so if it's already defined, we don't override it; that way
13723 // explicit parameters win over applied ones, and most recent applications
13724 // win over previous ones
13725 f = stu__pf(f->closure_source);
13726 }
13727
13728 for (j=0, i=0; i < f->num_param; ++i)
13729 // if it doesn't already exist, add it from the numbered parameters
13730 if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil)))
13731 ++j;
13732
13733 // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters
13734 // @TODO: ditto too few parameters
13735
13736 if (f->closure_source == 4)
13737 p = f->f.func(context);
13738 else {
13739 stu__f = f->code, stu__c = context;
13740 stu__f_obj = co;
13741 ++stb__stua_nesting;
13742 if (stu__f[1])
13743 p = stu__eval(stu__f[1]);
13744 else
13745 p = stua_nil;
13746 --stb__stua_nesting;
13747 stu__f = tf, stu__c = tc; // restore previous function
13748 if (stu__flow == FLOW_return) {
13749 stu__flow = FLOW_normal;
13750 p = stu__flow_val;
13751 stu__flow_val = stua_nil;
13752 }
13753 }
13754
13755 stua_poproot();
13756 stua_poproot();
13757
13758 return p;
13759 }
13760
13761 // Parser
13762
13763 static int stu__tok;
13764 static stua_obj stu__tokval;
13765
13766 static char *stu__curbuf, *stu__bufstart;
13767
13768 static stb_matcher *stu__lex_matcher;
13769
13770 static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals];
13771
13772 static void stu__nexttoken(void)
13773 {
13774 int len;
13775
13776 retry:
13777 stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len);
13778 if (stu__tok == 0)
13779 return;
13780 switch(stu__tok) {
13781 case ST_white : stu__curbuf += len; goto retry;
13782 case T__none : stu__tok = *stu__curbuf; break;
13783 case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break;
13784 case ST_id : stu__tokval = make_string(stu__curbuf, len); break;
13785 case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break;
13786 case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break;
13787 case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break;
13788 case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2];
13789 if (stu__curbuf[3] == 't') stu__tokval = '\t';
13790 if (stu__curbuf[3] == 'n') stu__tokval = '\n';
13791 if (stu__curbuf[3] == 'r') stu__tokval = '\r';
13792 stu__tokval = stu__makeint(stu__tokval);
13793 stu__tok = ST_number;
13794 break;
13795 }
13796 stu__curbuf += len;
13797 }
13798
13799 static struct { int stu__tok; char *regex; } stu__lexemes[] =
13800 {
13801 ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+",
13802 ST_id , "[_a-zA-Z][_a-zA-Z0-9]*",
13803 ST_hex , "0x[0-9a-fA-F]+",
13804 ST_decimal, "[0-9]+[0-9]*",
13805 ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?",
13806 ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?",
13807 ST_char , "c'(\\\\.|[^\\'])'",
13808 ST_string , "\"(\\\\.|[^\\\"\n\r])*\"",
13809 ST_string , "\'(\\\\.|[^\\\'\n\r])*\'",
13810
13811 #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d,
13812 stua_key4(if,then,else,elseif) stua_key4(while,do,for,in)
13813 stua_key4(func,var,let,break) stua_key4(nil,true,false,end)
13814 stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch)
13815
13816 ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=",
13817 ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=",
13818 ST_shru,">>>", ST_into, "=>",
13819 T__none, ".",
13820 };
13821
13822 typedef struct
13823 {
13824 stua_obj *data; // constants being compiled
13825 short *code; // code being compiled
13826 stua_dict *locals;
13827 short *non_local_refs;
13828 } stu__comp_func;
13829
13830 static stu__comp_func stu__pfunc;
13831 static stu__comp_func *func_stack = NULL;
13832 static void stu__push_func_comp(void)
13833 {
13834 stb_arr_push(func_stack, stu__pfunc);
13835 stu__pfunc.data = NULL;
13836 stu__pfunc.code = NULL;
13837 stu__pfunc.locals = stb_idict_new_size(16);
13838 stu__pfunc.non_local_refs = NULL;
13839 stb_arr_push(stu__pfunc.code, 0); // number of data items
13840 stb_arr_push(stu__pfunc.code, 1); // starting execution address
13841 }
13842
13843 static void stu__pop_func_comp(void)
13844 {
13845 stb_arr_free(stu__pfunc.code);
13846 stb_arr_free(stu__pfunc.data);
13847 stb_idict_destroy(stu__pfunc.locals);
13848 stb_arr_free(stu__pfunc.non_local_refs);
13849 stu__pfunc = stb_arr_pop(func_stack);
13850 }
13851
13852 // if an id is a reference to an outer lexical scope, this
13853 // function returns the "name" of it, and updates the stack
13854 // structures to make sure the names are propagated in.
13855 static int stu__nonlocal_id(stua_obj var_obj)
13856 {
13857 stua_obj dummy, var = var_obj;
13858 int i, n = stb_arr_len(func_stack), j,k;
13859 if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0;
13860 for (i=n-1; i > 1; --i) {
13861 if (stb_idict_get_flag(func_stack[i].locals, var, &dummy))
13862 break;
13863 }
13864 if (i <= 1) return 0; // stu__compile_global_scope
13865 j = i; // need to access variable from j'th frame
13866 for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i)
13867 if (stu__pfunc.non_local_refs[i] == j) return j-n;
13868 stb_arr_push(stu__pfunc.non_local_refs, j-n);
13869 // now make sure all the parents propagate it down
13870 for (k=n-1; k > 1; --k) {
13871 if (j-k >= 0) return j-n; // comes direct from this parent
13872 for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i)
13873 if (func_stack[k].non_local_refs[i] == j-k)
13874 return j-n;
13875 stb_arr_push(func_stack[k].non_local_refs, j-k);
13876 }
13877 assert (k != 1);
13878
13879 return j-n;
13880 }
13881
13882 static int stu__off(void) { return stb_arr_len(stu__pfunc.code); }
13883 static void stu__cc(int a)
13884 {
13885 assert(a >= -2000 && a < 5000);
13886 stb_arr_push(stu__pfunc.code, a);
13887 }
13888 static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; }
13889 static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; }
13890 static int stu__cc3(int a, int b, int c) {
13891 if (a == '=') assert(c != 0);
13892 stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; }
13893 static int stu__cc4(int a, int b, int c, int d) { stu__cc(a); stu__cc(b); stu__cc(c); stu__cc(d); return stu__off()-4; }
13894
13895 static int stu__cdv(stua_obj p)
13896 {
13897 int i;
13898 assert(p != STUA_NO_VALUE);
13899 for (i=0; i < stb_arr_len(stu__pfunc.data); ++i)
13900 if (stu__pfunc.data[i] == p)
13901 break;
13902 if (i == stb_arr_len(stu__pfunc.data))
13903 stb_arr_push(stu__pfunc.data, p);
13904 return ~i;
13905 }
13906
13907 static int stu__cdt(void)
13908 {
13909 int z = stu__cdv(stu__tokval);
13910 stu__nexttoken();
13911 return z;
13912 }
13913
13914 static int stu__seq(int a, int b)
13915 {
13916 return !a ? b : !b ? a : stu__cc3(STU__seq, a,b);
13917 }
13918
13919 static char stu__comp_err_str[1024];
13920 static int stu__comp_err_line;
13921 static int stu__err(char *str, ...)
13922 {
13923 va_list v;
13924 char *s = stu__bufstart;
13925 stu__comp_err_line = 1;
13926 while (s < stu__curbuf) {
13927 if (s[0] == '\n' || s[0] == '\r') {
13928 if (s[0]+s[1] == '\n' + '\r') ++s;
13929 ++stu__comp_err_line;
13930 }
13931 ++s;
13932 }
13933 va_start(v, str);
13934 vsprintf(stu__comp_err_str, str, v);
13935 va_end(v);
13936 return 0;
13937 }
13938
13939 static int stu__accept(int p)
13940 {
13941 if (stu__tok != p) return 0;
13942 stu__nexttoken();
13943 return 1;
13944 }
13945
13946 static int stu__demand(int p)
13947 {
13948 if (stu__accept(p)) return 1;
13949 return stu__err("Didn't find expected stu__tok");
13950 }
13951
13952 static int stu__demandv(int p, stua_obj *val)
13953 {
13954 if (stu__tok == p || p==0) {
13955 *val = stu__tokval;
13956 stu__nexttoken();
13957 return 1;
13958 } else
13959 return 0;
13960 }
13961
13962 static int stu__expr(int p);
13963 int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); }
13964 static int stu__statements(int once, int as);
13965
13966 static int stu__parse_if(void) // parse both ST_if and ST_elseif
13967 {
13968 int b,c,a;
13969 a = stu__nexpr(1); if (!a) return 0;
13970 if (!stu__demand(ST_then)) return stu__err("expecting THEN");
13971 b = stu__statements(0,0); if (!b) return 0;
13972 if (b == 1) b = -1;
13973
13974 if (stu__tok == ST_elseif) {
13975 return stu__parse_if();
13976 } else if (stu__accept(ST_else)) {
13977 c = stu__statements(0,0); if (!c) return 0;
13978 if (!stu__demand(ST_end)) return stu__err("expecting END after else clause");
13979 return stu__cc4(ST_else, a, b, c);
13980 } else {
13981 if (!stu__demand(ST_end)) return stu__err("expecting END in if statement");
13982 return stu__cc3(ST_if, a, b);
13983 }
13984 }
13985
13986 int stu__varinit(int z, int in_globals)
13987 {
13988 int a,b;
13989 stu__nexttoken();
13990 while (stu__demandv(ST_id, &b)) {
13991 if (!stb_idict_add(stu__pfunc.locals, b, 1))
13992 if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr);
13993 if (stu__accept('=')) {
13994 a = stu__expr(1); if (!a) return 0;
13995 } else
13996 a = stu__cdv(stua_nil);
13997 z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a));
13998 if (!stu__accept(',')) break;
13999 }
14000 return z;
14001 }
14002
14003 static int stu__compile_unary(int z, int outparm, int require_inparm)
14004 {
14005 int op = stu__tok, a, b;
14006 stu__nexttoken();
14007 if (outparm) {
14008 if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) {
14009 a = stu__expr(1); if (!a) return 0;
14010 } else
14011 a = stu__cdv(stua_nil);
14012 b = stu__cc2(op, a);
14013 } else
14014 b = stu__cc1(op);
14015 return stu__seq(z,b);
14016 }
14017
14018 static int stu__assign(void)
14019 {
14020 int z;
14021 stu__accept(ST_let);
14022 z = stu__expr(1); if (!z) return 0;
14023 if (stu__accept('=')) {
14024 int y,p = (z >= 0 ? stu__pfunc.code[z] : 0);
14025 if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment");
14026 y = stu__assign(); if (!y) return 0;
14027 z = stu__cc3('=', z, y);
14028 }
14029 return z;
14030 }
14031
14032 static int stu__statements(int once, int stop_while)
14033 {
14034 int a,b, c, z=0;
14035 for(;;) {
14036 switch (stu__tok) {
14037 case ST_if : a = stu__parse_if(); if (!a) return 0;
14038 z = stu__seq(z, a);
14039 break;
14040 case ST_while : if (stop_while) return (z ? z:1);
14041 a = stu__nexpr(1); if (!a) return 0;
14042 if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0;
14043 if (!stu__demand(ST_do)) return stu__err("expecting DO");
14044 b = stu__statements(0,0); if (!b) return 0;
14045 if (!stu__demand(ST_end)) return stu__err("expecting END");
14046 if (b == 1) b = -1;
14047 z = stu__seq(z, stu__cc4(ST_while, a, b, c));
14048 break;
14049 case ST_repeat : stu__nexttoken();
14050 c = stu__statements(0,1); if (!c) return 0;
14051 if (!stu__demand(ST_while)) return stu__err("expecting WHILE");
14052 a = stu__expr(1); if (!a) return 0;
14053 if (!stu__demand(ST_do)) return stu__err("expecting DO");
14054 b = stu__statements(0,0); if (!b) return 0;
14055 if (!stu__demand(ST_end)) return stu__err("expecting END");
14056 if (b == 1) b = -1;
14057 z = stu__seq(z, stu__cc4(ST_as, a, b, c));
14058 break;
14059 case ST_catch : a = stu__nexpr(1); if (!a) return 0;
14060 z = stu__seq(z, stu__cc2(ST_catch, a));
14061 break;
14062 case ST_var : z = stu__varinit(z,0); break;
14063 case ST_return : z = stu__compile_unary(z,1,1); break;
14064 case ST_continue:z = stu__compile_unary(z,0,0); break;
14065 case ST_break : z = stu__compile_unary(z,1,0); break;
14066 case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block");
14067 a = stu__nexpr(99);
14068 b = (a >= 0? stu__pfunc.code[a] : 0);
14069 if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>");
14070 z = stu__cc3('=', a, z);
14071 break;
14072 default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1);
14073 a = stu__assign(); if (!a) return 0;
14074 stu__accept(';');
14075 if (stu__tok && !stu__end[stu__tok]) {
14076 if (a < 0)
14077 return stu__err("Constant has no effect");
14078 if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=')
14079 return stu__err("Expression has no effect");
14080 }
14081 z = stu__seq(z, a);
14082 break;
14083 }
14084 if (!z) return 0;
14085 stu__accept(';');
14086 if (once && stu__tok != ST_into) return z;
14087 }
14088 }
14089
14090 static int stu__postexpr(int z, int p);
14091 static int stu__dictdef(int end, int *count)
14092 {
14093 int z,n=0,i,flags=0;
14094 short *dict=NULL;
14095 stu__nexttoken();
14096 while (stu__tok != end) {
14097 if (stu__tok == ST_id) {
14098 stua_obj id = stu__tokval;
14099 stu__nexttoken();
14100 if (stu__tok == '=') {
14101 flags |= 1;
14102 stb_arr_push(dict, stu__cdv(id));
14103 z = stu__nexpr(1); if (!z) return 0;
14104 } else {
14105 z = stu__cc2(ST_id, stu__cdv(id));
14106 z = stu__postexpr(z,1); if (!z) return 0;
14107 flags |= 2;
14108 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
14109 }
14110 } else {
14111 z = stu__expr(1); if (!z) return 0;
14112 flags |= 2;
14113 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
14114 }
14115 if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;}
14116 stb_arr_push(dict, z);
14117 if (!stu__accept(',')) break;
14118 }
14119 if (!stu__demand(end))
14120 return stu__err(end == ')' ? "Expecting ) at end of function call"
14121 : "Expecting } at end of dictionary definition");
14122 z = stu__cc2('{', stb_arr_len(dict)/2);
14123 for (i=0; i < stb_arr_len(dict); ++i)
14124 stu__cc(dict[i]);
14125 if (count) *count = n;
14126 done:
14127 stb_arr_free(dict);
14128 return z;
14129 }
14130
14131 static int stu__comp_id(void)
14132 {
14133 int z,d;
14134 d = stu__nonlocal_id(stu__tokval);
14135 if (d == 0)
14136 return z = stu__cc2(ST_id, stu__cdt());
14137 // access a non-local frame by naming it with the appropriate int
14138 assert(d < 0);
14139 z = stu__cdv(d); // relative frame # is the 'variable' in our local frame
14140 z = stu__cc2(ST_id, z); // now access that dictionary
14141 return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir
14142 }
14143
14144 static stua_obj stu__funcdef(stua_obj *id, stua_obj *func);
14145 static int stu__expr(int p)
14146 {
14147 int z;
14148 // unary
14149 switch (stu__tok) {
14150 case ST_number: z = stu__cdt(); break;
14151 case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C
14152 case ST_id : z = stu__comp_id(); break;
14153 case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break;
14154 case ST_func : z = stu__funcdef(NULL,NULL); break;
14155 case ST_if : z = stu__parse_if(); break;
14156 case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break;
14157 case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break;
14158 case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break;
14159 case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break;
14160 case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break;
14161 case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break;
14162 case '{' : z = stu__dictdef('}', NULL); break;
14163 default : return stu__err("Unexpected token");
14164 case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )");
14165 }
14166 return stu__postexpr(z,p);
14167 }
14168
14169 static int stu__postexpr(int z, int p)
14170 {
14171 int q;
14172 // postfix
14173 while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') {
14174 if (stu__accept('.')) {
14175 // MUST be followed by a plain identifier! use [] for other stuff
14176 if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead");
14177 z = stu__cc3('[', z, stu__cdv(stu__tokval));
14178 stu__nexttoken();
14179 } else if (stu__accept('[')) {
14180 while (stu__tok != ']') {
14181 int r = stu__expr(1); if (!r) return 0;
14182 z = stu__cc3('[', z, r);
14183 if (!stu__accept(',')) break;
14184 }
14185 if (!stu__demand(']')) return stu__err("Expecting ]");
14186 } else {
14187 int n, p = stu__dictdef(')', &n); if (!p) return 0;
14188 #if 0 // this is incorrect!
14189 if (z > 0 && stu__pfunc.code[z] == ST_id) {
14190 stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil);
14191 if (stu__checkt(STU___function, q))
14192 if ((stu__pf(q))->num_param != n)
14193 return stu__err("Incorrect number of parameters");
14194 }
14195 #endif
14196 z = stu__cc3('(', z, p);
14197 }
14198 }
14199 // binop - this implementation taken from lcc
14200 for (q=stu__prec[stu__tok]; q >= p; --q) {
14201 while (stu__prec[stu__tok] == q) {
14202 int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0;
14203 z = stu__cc3(o,z,y);
14204 }
14205 }
14206 return z;
14207 }
14208
14209 static stua_obj stu__finish_func(stua_obj *param, int start)
14210 {
14211 int n, size;
14212 stu__func *f = (stu__func *) malloc(sizeof(*f));
14213 f->closure_source = 0;
14214 f->num_param = stb_arr_len(param);
14215 f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param));
14216 size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8;
14217 f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data));
14218 f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data));
14219 memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code));
14220 f->code[1] = start;
14221 f->code[0] = stb_arr_len(stu__pfunc.data);
14222 for (n=0; n < f->code[0]; ++n)
14223 ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n];
14224 return stu__makeobj(STU___function, f, size, 0);
14225 }
14226
14227 static int stu__funcdef(stua_obj *id, stua_obj *result)
14228 {
14229 int n,z=0,i,q;
14230 stua_obj *param = NULL;
14231 short *nonlocal;
14232 stua_obj v,f=stua_nil;
14233 assert(stu__tok == ST_func);
14234 stu__nexttoken();
14235 if (id) {
14236 if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name");
14237 } else
14238 stu__accept(ST_id);
14239 if (!stu__demand('(')) return stu__err("Expecting ( for function parameter");
14240 stu__push_func_comp();
14241 while (stu__tok != ')') {
14242 if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; }
14243 stb_idict_add(stu__pfunc.locals, v, 1);
14244 if (stu__tok == '=') {
14245 n = stu__nexpr(1); if (!n) { z=0; goto done; }
14246 z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n));
14247 } else
14248 stb_arr_push(param, v);
14249 if (!stu__accept(',')) break;
14250 }
14251 if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; }
14252 n = stu__statements(0,0); if (!n) { z=0; goto done; }
14253 if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; }
14254 if (n == 1) n = 0;
14255 n = stu__seq(z,n);
14256 f = stu__finish_func(param, n);
14257 if (result) { *result = f; z=1; stu__pop_func_comp(); }
14258 else {
14259 nonlocal = stu__pfunc.non_local_refs;
14260 stu__pfunc.non_local_refs = NULL;
14261 stu__pop_func_comp();
14262 z = stu__cdv(f);
14263 if (nonlocal) { // build a closure with references to the needed frames
14264 short *initcode = NULL;
14265 for (i=0; i < stb_arr_len(nonlocal); ++i) {
14266 int k = nonlocal[i], p;
14267 stb_arr_push(initcode, stu__cdv(k));
14268 if (k == -1) p = stu__cc1(ST__frame);
14269 else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); }
14270 stb_arr_push(initcode, p);
14271 }
14272 q = stu__cc2('{', stb_arr_len(nonlocal));
14273 for (i=0; i < stb_arr_len(initcode); ++i)
14274 stu__cc(initcode[i]);
14275 z = stu__cc3('+', z, q);
14276 stb_arr_free(initcode);
14277 }
14278 stb_arr_free(nonlocal);
14279 }
14280 done:
14281 stb_arr_free(param);
14282 if (!z) stu__pop_func_comp();
14283 return z;
14284 }
14285
14286 static int stu__compile_global_scope(void)
14287 {
14288 stua_obj o;
14289 int z=0;
14290
14291 stu__push_func_comp();
14292 while (stu__tok != 0) {
14293 if (stu__tok == ST_func) {
14294 stua_obj id, f;
14295 if (!stu__funcdef(&id,&f))
14296 goto error;
14297 stu__set(stu__globaldict, id, f);
14298 } else if (stu__tok == ST_var) {
14299 z = stu__varinit(z,1); if (!z) goto error;
14300 } else {
14301 int y = stu__statements(1,0); if (!y) goto error;
14302 z = stu__seq(z,y);
14303 }
14304 stu__accept(';');
14305 }
14306 o = stu__finish_func(NULL, z);
14307 stu__pop_func_comp();
14308
14309 o = stu__funceval(o, stua_globals); // initialize stu__globaldict
14310 if (stu__flow == FLOW_error)
14311 printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr);
14312 return 1;
14313 error:
14314 stu__pop_func_comp();
14315 return 0;
14316 }
14317
14318 stua_obj stu__myprint(stua_dict *context)
14319 {
14320 stua_obj x = stu__get(context, stua_string("x"), stua_nil);
14321 if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x));
14322 else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x));
14323 else {
14324 stu__wrapper *s = stu__pw(x);
14325 if (s->type == STU___string || s->type == STU___error)
14326 printf("%s", s->ptr);
14327 else if (s->type == STU___dict) printf("{{dictionary}}");
14328 else if (s->type == STU___function) printf("[[function]]");
14329 else
14330 printf("[[ERROR:%s]]", s->ptr);
14331 }
14332 return x;
14333 }
14334
14335 void stua_init(void)
14336 {
14337 if (!stu__globaldict) {
14338 int i;
14339 stua_obj s;
14340 stu__func *f;
14341
14342 stu__prec[ST_and] = stu__prec[ST_or] = 1;
14343 stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] =
14344 stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2;
14345 stu__prec[':'] = 3;
14346 stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4;
14347 stu__prec['+'] = stu__prec['-'] = 5;
14348 stu__prec['*'] = stu__prec['/'] = stu__prec['%'] =
14349 stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6;
14350
14351 stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1;
14352 stu__end[ST_do] = stu__end[ST_elseif] = 1;
14353
14354 stu__float_init();
14355 stu__lex_matcher = stb_lex_matcher();
14356 for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i)
14357 stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok);
14358
14359 stu__globaldict = stb_idict_new_size(64);
14360 stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0);
14361 stu__strings = stb_sdict_new(0);
14362
14363 stu__curbuf = stu__bufstart = "func _print(x) end\n"
14364 "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n";
14365 stu__nexttoken();
14366 if (!stu__compile_global_scope())
14367 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14368
14369 s = stu__get(stu__globaldict, stua_string("_print"), stua_nil);
14370 if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) {
14371 f = stu__pf(s);
14372 free(f->f.store);
14373 f->closure_source = 4;
14374 f->f.func = stu__myprint;
14375 f->code = NULL;
14376 }
14377 }
14378 }
14379
14380 void stua_uninit(void)
14381 {
14382 if (stu__globaldict) {
14383 stb_idict_remove_all(stu__globaldict);
14384 stb_arr_setlen(stu__gc_root_stack, 0);
14385 stua_gc(1);
14386 stb_idict_destroy(stu__globaldict);
14387 stb_sdict_delete(stu__strings);
14388 stb_matcher_free(stu__lex_matcher);
14389 stb_arr_free(stu__gc_ptrlist);
14390 stb_arr_free(func_stack);
14391 stb_arr_free(stu__gc_root_stack);
14392 stu__globaldict = NULL;
14393 }
14394 }
14395
14396 void stua_run_script(char *s)
14397 {
14398 stua_init();
14399
14400 stu__curbuf = stu__bufstart = s;
14401 stu__nexttoken();
14402
14403 stu__flow = FLOW_normal;
14404
14405 if (!stu__compile_global_scope())
14406 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14407 stua_gc(1);
14408 }
14409 #endif // STB_DEFINE
14410 #endif // STB_STUA
14411
14412 #undef STB_EXTERN
14413 #endif // STB_INCLUDE_STB_H
14414
14415 /*
14416 ------------------------------------------------------------------------------
14417 This software is available under 2 licenses -- choose whichever you prefer.
14418 ------------------------------------------------------------------------------
14419 ALTERNATIVE A - MIT License
14420 Copyright (c) 2017 Sean Barrett
14421 Permission is hereby granted, free of charge, to any person obtaining a copy of
14422 this software and associated documentation files (the "Software"), to deal in
14423 the Software without restriction, including without limitation the rights to
14424 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14425 of the Software, and to permit persons to whom the Software is furnished to do
14426 so, subject to the following conditions:
14427 The above copyright notice and this permission notice shall be included in all
14428 copies or substantial portions of the Software.
14429 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14430 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14431 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14432 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14433 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14434 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
14435 SOFTWARE.
14436 ------------------------------------------------------------------------------
14437 ALTERNATIVE B - Public Domain (www.unlicense.org)
14438 This is free and unencumbered software released into the public domain.
14439 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
14440 software, either in source code form or as a compiled binary, for any purpose,
14441 commercial or non-commercial, and by any means.
14442 In jurisdictions that recognize copyright laws, the author or authors of this
14443 software dedicate any and all copyright interest in the software to the public
14444 domain. We make this dedication for the benefit of the public at large and to
14445 the detriment of our heirs and successors. We intend this dedication to be an
14446 overt act of relinquishment in perpetuity of all present and future rights to
14447 this software under copyright law.
14448 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14449 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14450 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14451 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
14452 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
14453 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14454 ------------------------------------------------------------------------------
14455 */
14456