1 /* stb.h - v2.34 - 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 ============================================================================
12 You MUST
13
14 #define STB_DEFINE
15
16 in EXACTLY _one_ C or C++ file that includes this header, BEFORE the
17 include, like this:
18
19 #define STB_DEFINE
20 #include "stb.h"
21
22 All other files should just #include "stb.h" without the #define.
23 ============================================================================
24
25
26 Version History
27
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 */
203
204 #include <stdarg.h>
205
206 #ifndef STB__INCLUDE_STB_H
207 #define STB__INCLUDE_STB_H
208
209 #define STB_VERSION 1
210
211 #ifdef STB_INTROSPECT
212 #define STB_DEFINE
213 #endif
214
215 #ifdef STB_DEFINE_THREADS
216 #ifndef STB_DEFINE
217 #define STB_DEFINE
218 #endif
219 #ifndef STB_THREADS
220 #define STB_THREADS
221 #endif
222 #endif
223
224 #if defined(_WIN32) && !defined(__MINGW32__)
225 #ifndef _CRT_SECURE_NO_WARNINGS
226 #define _CRT_SECURE_NO_WARNINGS
227 #endif
228 #ifndef _CRT_NONSTDC_NO_DEPRECATE
229 #define _CRT_NONSTDC_NO_DEPRECATE
230 #endif
231 #ifndef _CRT_NON_CONFORMING_SWPRINTFS
232 #define _CRT_NON_CONFORMING_SWPRINTFS
233 #endif
234 #if !defined(_MSC_VER) || _MSC_VER > 1700
235 #include <intrin.h> // _BitScanReverse
236 #endif
237 #endif
238
239 #include <stdlib.h> // stdlib could have min/max
240 #include <stdio.h> // need FILE
241 #include <string.h> // stb_define_hash needs memcpy/memset
242 #include <time.h> // stb_dirtree
243 #ifdef __MINGW32__
244 #include <fcntl.h> // O_RDWR
245 #endif
246
247 #ifdef STB_PERSONAL
248 typedef int Bool;
249 #define False 0
250 #define True 1
251 #endif
252
253 #ifdef STB_MALLOC_WRAPPER_PAGED
254 #define STB_MALLOC_WRAPPER_DEBUG
255 #endif
256 #ifdef STB_MALLOC_WRAPPER_DEBUG
257 #define STB_MALLOC_WRAPPER
258 #endif
259 #ifdef STB_MALLOC_WRAPPER_FASTMALLOC
260 #define STB_FASTMALLOC
261 #define STB_MALLOC_WRAPPER
262 #endif
263
264 #ifdef STB_FASTMALLOC
265 #ifndef _WIN32
266 #undef STB_FASTMALLOC
267 #endif
268 #endif
269
270 #ifdef STB_DEFINE
271 #include <assert.h>
272 #include <stdarg.h>
273 #include <stddef.h>
274 #include <ctype.h>
275 #include <math.h>
276 #ifndef _WIN32
277 #include <unistd.h>
278 #else
279 #include <io.h> // _mktemp
280 #include <direct.h> // _rmdir
281 #endif
282 #include <sys/types.h> // stat()/_stat()
283 #include <sys/stat.h> // stat()/_stat()
284 #endif
285
286 #define stb_min(a,b) ((a) < (b) ? (a) : (b))
287 #define stb_max(a,b) ((a) > (b) ? (a) : (b))
288
289 #ifndef STB_ONLY
290 #if !defined(__cplusplus) && !defined(min) && !defined(max)
291 #define min(x,y) stb_min(x,y)
292 #define max(x,y) stb_max(x,y)
293 #endif
294
295 #ifndef M_PI
296 #define M_PI 3.14159265358979323846f
297 #endif
298
299 #ifndef TRUE
300 #define TRUE 1
301 #define FALSE 0
302 #endif
303
304 #ifndef deg2rad
305 #define deg2rad(a) ((a)*(M_PI/180))
306 #endif
307 #ifndef rad2deg
308 #define rad2deg(a) ((a)*(180/M_PI))
309 #endif
310
311 #ifndef swap
312 #ifndef __cplusplus
313 #define swap(TYPE,a,b) \
314 do { TYPE stb__t; stb__t = (a); (a) = (b); (b) = stb__t; } while (0)
315 #endif
316 #endif
317
318 typedef unsigned char uint8 ;
319 typedef signed char int8 ;
320 typedef unsigned short uint16;
321 typedef signed short int16;
322 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
323 typedef unsigned long uint32;
324 typedef signed long int32;
325 #else
326 typedef unsigned int uint32;
327 typedef signed int int32;
328 #endif
329
330 typedef unsigned char uchar ;
331 typedef unsigned short ushort;
332 typedef unsigned int uint ;
333 typedef unsigned long ulong ;
334
335 // produce compile errors if the sizes aren't right
336 typedef char stb__testsize16[sizeof(int16)==2];
337 typedef char stb__testsize32[sizeof(int32)==4];
338 #endif
339
340 #ifndef STB_TRUE
341 #define STB_TRUE 1
342 #define STB_FALSE 0
343 #endif
344
345 // if we're STB_ONLY, can't rely on uint32 or even uint, so all the
346 // variables we'll use herein need typenames prefixed with 'stb':
347 typedef unsigned char stb_uchar;
348 typedef unsigned char stb_uint8;
349 typedef unsigned int stb_uint;
350 typedef unsigned short stb_uint16;
351 typedef short stb_int16;
352 typedef signed char stb_int8;
353 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
354 typedef unsigned long stb_uint32;
355 typedef long stb_int32;
356 #else
357 typedef unsigned int stb_uint32;
358 typedef int stb_int32;
359 #endif
360 typedef char stb__testsize2_16[sizeof(stb_uint16)==2 ? 1 : -1];
361 typedef char stb__testsize2_32[sizeof(stb_uint32)==4 ? 1 : -1];
362
363 #ifdef _MSC_VER
364 typedef unsigned __int64 stb_uint64;
365 typedef __int64 stb_int64;
366 #define STB_IMM_UINT64(literalui64) (literalui64##ui64)
367 #define STB_IMM_INT64(literali64) (literali64##i64)
368 #else
369 // ??
370 typedef unsigned long long stb_uint64;
371 typedef long long stb_int64;
372 #define STB_IMM_UINT64(literalui64) (literalui64##ULL)
373 #define STB_IMM_INT64(literali64) (literali64##LL)
374 #endif
375 typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1];
376
377 // add platform-specific ways of checking for sizeof(char*) == 8,
378 // and make those define STB_PTR64
379 #if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) || defined(__LP64__)
380 #define STB_PTR64
381 #endif
382
383 #ifdef STB_PTR64
384 typedef char stb__testsize2_ptr[sizeof(char *) == 8];
385 typedef stb_uint64 stb_uinta;
386 typedef stb_int64 stb_inta;
387 #else
388 typedef char stb__testsize2_ptr[sizeof(char *) == 4];
389 typedef stb_uint32 stb_uinta;
390 typedef stb_int32 stb_inta;
391 #endif
392 typedef char stb__testsize2_uinta[sizeof(stb_uinta)==sizeof(char*) ? 1 : -1];
393
394 // if so, we should define an int type that is the pointer size. until then,
395 // we'll have to make do with this (which is not the same at all!)
396
397 typedef union
398 {
399 unsigned int i;
400 void * p;
401 } stb_uintptr;
402
403
404 #ifdef __cplusplus
405 #define STB_EXTERN extern "C"
406 #else
407 #define STB_EXTERN extern
408 #endif
409
410 // check for well-known debug defines
411 #if defined(DEBUG) || defined(_DEBUG) || defined(DBG)
412 #ifndef NDEBUG
413 #define STB_DEBUG
414 #endif
415 #endif
416
417 #ifdef STB_DEBUG
418 #include <assert.h>
419 #endif
420
421 //////////////////////////////////////////////////////////////////////////////
422 //
423 // C library function platform handling
424 //
425
426 #ifdef STB_DEFINE
427
428 #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
stb_p_fopen(const char * filename,const char * mode)429 static FILE * stb_p_fopen(const char *filename, const char *mode)
430 {
431 FILE *f;
432 if (0 == fopen_s(&f, filename, mode))
433 return f;
434 else
435 return NULL;
436 }
stb_p_wfopen(const wchar_t * filename,const wchar_t * mode)437 static FILE * stb_p_wfopen(const wchar_t *filename, const wchar_t *mode)
438 {
439 FILE *f;
440 if (0 == _wfopen_s(&f, filename, mode))
441 return f;
442 else
443 return NULL;
444 }
stb_p_strcpy_s(char * a,size_t size,const char * b)445 static char *stb_p_strcpy_s(char *a, size_t size, const char *b)
446 {
447 strcpy_s(a,size,b);
448 return a;
449 }
stb_p_strncpy_s(char * a,size_t size,const char * b,size_t count)450 static char *stb_p_strncpy_s(char *a, size_t size, const char *b, size_t count)
451 {
452 strncpy_s(a,size,b,count);
453 return a;
454 }
455 #define stb_p_mktemp(s) (_mktemp_s(s, strlen(s)+1) == 0)
456 #define stb_p_sprintf sprintf_s
457 #define stb_p_size(x) ,(x)
458 #else
459 #define stb_p_fopen fopen
460 #define stb_p_wfopen _wfopen
461 #define stb_p_strcpy_s(a,s,b) strcpy(a,b)
462 #define stb_p_strncpy_s(a,s,b,c) strncpy(a,b,c)
463 #define stb_p_mktemp(s) (mktemp(s) != NULL)
464
465 #define stb_p_sprintf sprintf
466 #define stb_p_size(x)
467 #endif
468
469 #if defined(_WIN32)
470 #define stb_p_vsnprintf _vsnprintf
471 #else
472 #define stb_p_vsnprintf vsnprintf
473 #endif
474
475 #if defined(_WIN32) && (_MSC_VER >= 1300)
476 #define stb_p_stricmp _stricmp
477 #define stb_p_strnicmp _strnicmp
478 #define stb_p_strdup _strdup
479 #else
480 #define stb_p_strdup strdup
481 #define stb_p_stricmp stricmp
482 #define stb_p_strnicmp strnicmp
483 #endif
484
485 #endif // STB_DEFINE
486
487
488 STB_EXTERN void stb_wrapper_malloc(void *newp, size_t sz, char *file, int line);
489 STB_EXTERN void stb_wrapper_free(void *oldp, char *file, int line);
490 STB_EXTERN void stb_wrapper_realloc(void *oldp, void *newp, size_t sz, char *file, int line);
491 STB_EXTERN void stb_wrapper_calloc(size_t num, size_t sz, char *file, int line);
492 STB_EXTERN void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line));
493 STB_EXTERN void stb_wrapper_dump(char *filename);
494 STB_EXTERN size_t stb_wrapper_allocsize(void *oldp);
495 STB_EXTERN void stb_wrapper_check(void *oldp);
496
497 #ifdef STB_DEFINE
498 // this is a special function used inside malloc wrapper
499 // to do allocations that aren't tracked (to avoid
500 // reentrancy). Of course if someone _else_ wraps realloc,
501 // this breaks, but if they're doing that AND the malloc
502 // wrapper they need to explicitly check for reentrancy.
503 //
504 // only define realloc_raw() and we do realloc(NULL,sz)
505 // for malloc() and realloc(p,0) for free().
stb__realloc_raw(void * p,int sz)506 static void * stb__realloc_raw(void *p, int sz)
507 {
508 if (p == NULL) return malloc(sz);
509 if (sz == 0) { free(p); return NULL; }
510 return realloc(p,sz);
511 }
512 #endif
513
514 #ifdef _WIN32
515 STB_EXTERN void * stb_smalloc(size_t sz);
516 STB_EXTERN void stb_sfree(void *p);
517 STB_EXTERN void * stb_srealloc(void *p, size_t sz);
518 STB_EXTERN void * stb_scalloc(size_t n, size_t sz);
519 STB_EXTERN char * stb_sstrdup(char *s);
520 #endif
521
522 #ifdef STB_FASTMALLOC
523 #define malloc stb_smalloc
524 #define free stb_sfree
525 #define realloc stb_srealloc
526 #define strdup stb_sstrdup
527 #define calloc stb_scalloc
528 #endif
529
530 #ifndef STB_MALLOC_ALLCHECK
531 #define stb__check(p) 1
532 #else
533 #ifndef STB_MALLOC_WRAPPER
534 #error STB_MALLOC_ALLCHECK requires STB_MALLOC_WRAPPER
535 #else
536 #define stb__check(p) stb_mcheck(p)
537 #endif
538 #endif
539
540 #ifdef STB_MALLOC_WRAPPER
541 STB_EXTERN void * stb__malloc(size_t, char *, int);
542 STB_EXTERN void * stb__realloc(void *, size_t, char *, int);
543 STB_EXTERN void * stb__calloc(size_t n, size_t s, char *, int);
544 STB_EXTERN void stb__free(void *, char *file, int);
545 STB_EXTERN char * stb__strdup(char *s, char *file, int);
546 STB_EXTERN void stb_malloc_checkall(void);
547 STB_EXTERN void stb_malloc_check_counter(int init_delay, int rep_delay);
548 #ifndef STB_MALLOC_WRAPPER_DEBUG
549 #define stb_mcheck(p) 1
550 #else
551 STB_EXTERN int stb_mcheck(void *);
552 #endif
553
554
555 #ifdef STB_DEFINE
556
557 #ifdef STB_MALLOC_WRAPPER_DEBUG
558 #define STB__PAD 32
559 #define STB__BIAS 16
560 #define STB__SIG 0x51b01234
561 #define STB__FIXSIZE(sz) (((sz+3) & ~3) + STB__PAD)
562 #define STB__ptr(x,y) ((char *) (x) + (y))
563 #else
564 #define STB__ptr(x,y) (x)
565 #define STB__FIXSIZE(sz) (sz)
566 #endif
567
568 #ifdef STB_MALLOC_WRAPPER_DEBUG
stb_mcheck(void * p)569 int stb_mcheck(void *p)
570 {
571 unsigned int sz;
572 if (p == NULL) return 1;
573 p = ((char *) p) - STB__BIAS;
574 sz = * (unsigned int *) p;
575 assert(* (unsigned int *) STB__ptr(p,4) == STB__SIG);
576 assert(* (unsigned int *) STB__ptr(p,8) == STB__SIG);
577 assert(* (unsigned int *) STB__ptr(p,12) == STB__SIG);
578 assert(* (unsigned int *) STB__ptr(p,sz-4) == STB__SIG+1);
579 assert(* (unsigned int *) STB__ptr(p,sz-8) == STB__SIG+1);
580 assert(* (unsigned int *) STB__ptr(p,sz-12) == STB__SIG+1);
581 assert(* (unsigned int *) STB__ptr(p,sz-16) == STB__SIG+1);
582 stb_wrapper_check(STB__ptr(p, STB__BIAS));
583 return 1;
584 }
585
stb__check2(void * p,size_t sz,char * file,int line)586 static void stb__check2(void *p, size_t sz, char *file, int line)
587 {
588 stb_mcheck(p);
589 }
590
stb_malloc_checkall(void)591 void stb_malloc_checkall(void)
592 {
593 stb_wrapper_listall(stb__check2);
594 }
595 #else
stb_malloc_checkall(void)596 void stb_malloc_checkall(void) { }
597 #endif
598
599 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)600 void stb_malloc_check_counter(int init_delay, int rep_delay)
601 {
602 stb__malloc_wait = init_delay;
603 stb__malloc_next_wait = rep_delay;
604 }
605
stb_mcheck_all(void)606 void stb_mcheck_all(void)
607 {
608 #ifdef STB_MALLOC_WRAPPER_DEBUG
609 ++stb__malloc_iter;
610 if (--stb__malloc_wait <= 0) {
611 stb_malloc_checkall();
612 stb__malloc_wait = stb__malloc_next_wait;
613 }
614 #endif
615 }
616
617 #ifdef STB_MALLOC_WRAPPER_PAGED
618 #define STB__WINDOWS_PAGE (1 << 12)
619 #ifndef _WINDOWS_
620 STB_EXTERN __declspec(dllimport) void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
621 STB_EXTERN __declspec(dllimport) int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
622 #endif
623 #endif
624
stb__malloc_final(size_t sz)625 static void *stb__malloc_final(size_t sz)
626 {
627 #ifdef STB_MALLOC_WRAPPER_PAGED
628 size_t aligned = (sz + STB__WINDOWS_PAGE - 1) & ~(STB__WINDOWS_PAGE-1);
629 char *p = VirtualAlloc(NULL, aligned + STB__WINDOWS_PAGE, 0x2000, 0x04); // RESERVE, READWRITE
630 if (p == NULL) return p;
631 VirtualAlloc(p, aligned, 0x1000, 0x04); // COMMIT, READWRITE
632 return p;
633 #else
634 return malloc(sz);
635 #endif
636 }
637
stb__free_final(void * p)638 static void stb__free_final(void *p)
639 {
640 #ifdef STB_MALLOC_WRAPPER_PAGED
641 VirtualFree(p, 0, 0x8000); // RELEASE
642 #else
643 free(p);
644 #endif
645 }
646
647 int stb__malloc_failure;
648 #ifdef STB_MALLOC_WRAPPER_PAGED
stb__realloc_final(void * p,size_t sz,size_t old_sz)649 static void *stb__realloc_final(void *p, size_t sz, size_t old_sz)
650 {
651 void *q = stb__malloc_final(sz);
652 if (q == NULL)
653 return ++stb__malloc_failure, q;
654 // @TODO: deal with p being smaller!
655 memcpy(q, p, sz < old_sz ? sz : old_sz);
656 stb__free_final(p);
657 return q;
658 }
659 #endif
660
stb__free(void * p,char * file,int line)661 void stb__free(void *p, char *file, int line)
662 {
663 stb_mcheck_all();
664 if (!p) return;
665 #ifdef STB_MALLOC_WRAPPER_DEBUG
666 stb_mcheck(p);
667 #endif
668 stb_wrapper_free(p,file,line);
669 #ifdef STB_MALLOC_WRAPPER_DEBUG
670 p = STB__ptr(p,-STB__BIAS);
671 * (unsigned int *) STB__ptr(p,0) = 0xdeadbeef;
672 * (unsigned int *) STB__ptr(p,4) = 0xdeadbeef;
673 * (unsigned int *) STB__ptr(p,8) = 0xdeadbeef;
674 * (unsigned int *) STB__ptr(p,12) = 0xdeadbeef;
675 #endif
676 stb__free_final(p);
677 }
678
stb__malloc(size_t sz,char * file,int line)679 void * stb__malloc(size_t sz, char *file, int line)
680 {
681 void *p;
682 stb_mcheck_all();
683 if (sz == 0) return NULL;
684 p = stb__malloc_final(STB__FIXSIZE(sz));
685 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
686 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
687 if (p == NULL) {
688 ++stb__malloc_failure;
689 #ifdef STB_MALLOC_WRAPPER_DEBUG
690 stb_malloc_checkall();
691 #endif
692 return p;
693 }
694 #ifdef STB_MALLOC_WRAPPER_DEBUG
695 * (int *) STB__ptr(p,0) = STB__FIXSIZE(sz);
696 * (unsigned int *) STB__ptr(p,4) = STB__SIG;
697 * (unsigned int *) STB__ptr(p,8) = STB__SIG;
698 * (unsigned int *) STB__ptr(p,12) = STB__SIG;
699 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-4) = STB__SIG+1;
700 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-8) = STB__SIG+1;
701 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-12) = STB__SIG+1;
702 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-16) = STB__SIG+1;
703 p = STB__ptr(p, STB__BIAS);
704 #endif
705 stb_wrapper_malloc(p,sz,file,line);
706 return p;
707 }
708
stb__realloc(void * p,size_t sz,char * file,int line)709 void * stb__realloc(void *p, size_t sz, char *file, int line)
710 {
711 void *q;
712
713 stb_mcheck_all();
714 if (p == NULL) return stb__malloc(sz,file,line);
715 if (sz == 0 ) { stb__free(p,file,line); return NULL; }
716
717 #ifdef STB_MALLOC_WRAPPER_DEBUG
718 stb_mcheck(p);
719 p = STB__ptr(p,-STB__BIAS);
720 #endif
721 #ifdef STB_MALLOC_WRAPPER_PAGED
722 {
723 size_t n = stb_wrapper_allocsize(STB__ptr(p,STB__BIAS));
724 if (!n)
725 stb_wrapper_check(STB__ptr(p,STB__BIAS));
726 q = stb__realloc_final(p, STB__FIXSIZE(sz), STB__FIXSIZE(n));
727 }
728 #else
729 q = realloc(p, STB__FIXSIZE(sz));
730 #endif
731 if (q == NULL)
732 return ++stb__malloc_failure, q;
733 #ifdef STB_MALLOC_WRAPPER_DEBUG
734 * (int *) STB__ptr(q,0) = STB__FIXSIZE(sz);
735 * (unsigned int *) STB__ptr(q,4) = STB__SIG;
736 * (unsigned int *) STB__ptr(q,8) = STB__SIG;
737 * (unsigned int *) STB__ptr(q,12) = STB__SIG;
738 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-4) = STB__SIG+1;
739 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-8) = STB__SIG+1;
740 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-12) = STB__SIG+1;
741 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-16) = STB__SIG+1;
742
743 q = STB__ptr(q, STB__BIAS);
744 p = STB__ptr(p, STB__BIAS);
745 #endif
746 stb_wrapper_realloc(p,q,sz,file,line);
747 return q;
748 }
749
750 STB_EXTERN int stb_log2_ceil(size_t);
stb__calloc(size_t n,size_t sz,char * file,int line)751 static void *stb__calloc(size_t n, size_t sz, char *file, int line)
752 {
753 void *q;
754 stb_mcheck_all();
755 if (n == 0 || sz == 0) return NULL;
756 if (stb_log2_ceil(n) + stb_log2_ceil(sz) >= 32) return NULL;
757 q = stb__malloc(n*sz, file, line);
758 if (q) memset(q, 0, n*sz);
759 return q;
760 }
761
stb__strdup(char * s,char * file,int line)762 char * stb__strdup(char *s, char *file, int line)
763 {
764 char *p;
765 stb_mcheck_all();
766 p = stb__malloc(strlen(s)+1, file, line);
767 if (!p) return p;
768 stb_p_strcpy_s(p, strlen(s)+1, s);
769 return p;
770 }
771 #endif // STB_DEFINE
772
773 #ifdef STB_FASTMALLOC
774 #undef malloc
775 #undef realloc
776 #undef free
777 #undef strdup
778 #undef calloc
779 #endif
780
781 // include everything that might define these, BEFORE making macros
782 #include <stdlib.h>
783 #include <string.h>
784 #include <malloc.h>
785
786 #define malloc(s) stb__malloc ( s, __FILE__, __LINE__)
787 #define realloc(p,s) stb__realloc(p,s, __FILE__, __LINE__)
788 #define calloc(n,s) stb__calloc (n,s, __FILE__, __LINE__)
789 #define free(p) stb__free (p, __FILE__, __LINE__)
790 #define strdup(p) stb__strdup (p, __FILE__, __LINE__)
791 #endif
792
793 //////////////////////////////////////////////////////////////////////////////
794 //
795 // Windows pretty display
796 //
797
798 STB_EXTERN void stbprint(const char *fmt, ...);
799 STB_EXTERN char *stb_sprintf(const char *fmt, ...);
800 STB_EXTERN char *stb_mprintf(const char *fmt, ...);
801 STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...);
802 STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v);
803
804 #ifdef STB_DEFINE
stb_vsnprintf(char * s,size_t n,const char * fmt,va_list v)805 int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v)
806 {
807 int res;
808 #ifdef _WIN32
809 #ifdef __STDC_WANT_SECURE_LIB__
810 res = _vsnprintf_s(s, n, _TRUNCATE, fmt, v);
811 #else
812 res = stb_p_vsnprintf(s,n,fmt,v);
813 #endif
814 #else
815 res = vsnprintf(s,n,fmt,v);
816 #endif
817 if (n) s[n-1] = 0;
818 // Unix returns length output would require, Windows returns negative when truncated.
819 return (res >= (int) n || res < 0) ? -1 : res;
820 }
821
stb_snprintf(char * s,size_t n,const char * fmt,...)822 int stb_snprintf(char *s, size_t n, const char *fmt, ...)
823 {
824 int res;
825 va_list v;
826 va_start(v,fmt);
827 res = stb_vsnprintf(s, n, fmt, v);
828 va_end(v);
829 return res;
830 }
831
stb_sprintf(const char * fmt,...)832 char *stb_sprintf(const char *fmt, ...)
833 {
834 static char buffer[1024];
835 va_list v;
836 va_start(v,fmt);
837 stb_vsnprintf(buffer,1024,fmt,v);
838 va_end(v);
839 return buffer;
840 }
841
stb_mprintf(const char * fmt,...)842 char *stb_mprintf(const char *fmt, ...)
843 {
844 static char buffer[1024];
845 va_list v;
846 va_start(v,fmt);
847 stb_vsnprintf(buffer,1024,fmt,v);
848 va_end(v);
849 return stb_p_strdup(buffer);
850 }
851
852 #ifdef _WIN32
853
854 #ifndef _WINDOWS_
855 STB_EXTERN __declspec(dllimport) int __stdcall WriteConsoleA(void *, const void *, unsigned int, unsigned int *, void *);
856 STB_EXTERN __declspec(dllimport) void * __stdcall GetStdHandle(unsigned int);
857 STB_EXTERN __declspec(dllimport) int __stdcall SetConsoleTextAttribute(void *, unsigned short);
858 #endif
859
stb__print_one(void * handle,char * s,ptrdiff_t len)860 static void stb__print_one(void *handle, char *s, ptrdiff_t len)
861 {
862 if (len)
863 if (0==WriteConsoleA(handle, s, (unsigned) len, NULL,NULL))
864 // if it fails, maybe redirected, so output normally...
865 // but it's supriously reporting failure now on Win7 and later
866 {}//fwrite(s, 1, (unsigned) len, stdout);
867 }
868
stb__print(char * s)869 static void stb__print(char *s)
870 {
871 void *handle = GetStdHandle((unsigned int) -11); // STD_OUTPUT_HANDLE
872 int pad=0; // number of padding characters to add
873
874 char *t = s;
875 while (*s) {
876 int lpad;
877 while (*s && *s != '{') {
878 if (pad) {
879 if (*s == '\r' || *s == '\n')
880 pad = 0;
881 else if (s[0] == ' ' && s[1] == ' ') {
882 stb__print_one(handle, t, s-t);
883 t = s;
884 while (pad) {
885 stb__print_one(handle, t, 1);
886 --pad;
887 }
888 }
889 }
890 ++s;
891 }
892 if (!*s) break;
893 stb__print_one(handle, t, s-t);
894 if (s[1] == '{') {
895 ++s;
896 continue;
897 }
898
899 if (s[1] == '#') {
900 t = s+3;
901 if (isxdigit(s[2]))
902 if (isdigit(s[2]))
903 SetConsoleTextAttribute(handle, s[2] - '0');
904 else
905 SetConsoleTextAttribute(handle, tolower(s[2]) - 'a' + 10);
906 else {
907 SetConsoleTextAttribute(handle, 0x0f);
908 t=s+2;
909 }
910 } else if (s[1] == '!') {
911 SetConsoleTextAttribute(handle, 0x0c);
912 t = s+2;
913 } else if (s[1] == '@') {
914 SetConsoleTextAttribute(handle, 0x09);
915 t = s+2;
916 } else if (s[1] == '$') {
917 SetConsoleTextAttribute(handle, 0x0a);
918 t = s+2;
919 } else {
920 SetConsoleTextAttribute(handle, 0x08); // 0,7,8,15 => shades of grey
921 t = s+1;
922 }
923
924 lpad = (int) (t-s);
925 s = t;
926 while (*s && *s != '}') ++s;
927 if (!*s) break;
928 stb__print_one(handle, t, s-t);
929 if (s[1] == '}') {
930 t = s+2;
931 } else {
932 pad += 1+lpad;
933 t = s+1;
934 }
935 s=t;
936 SetConsoleTextAttribute(handle, 0x07);
937 }
938 stb__print_one(handle, t, s-t);
939 SetConsoleTextAttribute(handle, 0x07);
940 }
941
stbprint(const char * fmt,...)942 void stbprint(const char *fmt, ...)
943 {
944 int res;
945 char buffer[1024];
946 char *tbuf = buffer;
947 va_list v;
948
949 va_start(v,fmt);
950 res = stb_vsnprintf(buffer, sizeof(buffer), fmt, v);
951 va_end(v);
952
953 if (res < 0) {
954 tbuf = (char *) malloc(16384);
955 va_start(v,fmt);
956 res = stb_vsnprintf(tbuf,16384, fmt, v);
957 va_end(v);
958 tbuf[16383] = 0;
959 }
960
961 stb__print(tbuf);
962
963 if (tbuf != buffer)
964 free(tbuf);
965 }
966
967 #else // _WIN32
stbprint(const char * fmt,...)968 void stbprint(const char *fmt, ...)
969 {
970 va_list v;
971 va_start(v,fmt);
972 vprintf(fmt,v);
973 va_end(v);
974 }
975 #endif // _WIN32
976 #endif // STB_DEFINE
977
978
979
980 //////////////////////////////////////////////////////////////////////////////
981 //
982 // Windows UTF8 filename handling
983 //
984 // Windows stupidly treats 8-bit filenames as some dopey code page,
985 // rather than utf-8. If we want to use utf8 filenames, we have to
986 // convert them to WCHAR explicitly and call WCHAR versions of the
987 // file functions. So, ok, we do.
988
989
990 #ifdef _WIN32
991 #define stb__fopen(x,y) stb_p_wfopen((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
992 #define stb__windows(x,y) x
993 #else
994 #define stb__fopen(x,y) stb_p_fopen(x,y)
995 #define stb__windows(x,y) y
996 #endif
997
998
999 typedef unsigned short stb__wchar;
1000
1001 STB_EXTERN stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *str, int n);
1002 STB_EXTERN char * stb_to_utf8 (char *buffer, const stb__wchar *str, int n);
1003
1004 STB_EXTERN stb__wchar *stb__from_utf8(const char *str);
1005 STB_EXTERN stb__wchar *stb__from_utf8_alt(const char *str);
1006 STB_EXTERN char *stb__to_utf8(const stb__wchar *str);
1007
1008
1009 #ifdef STB_DEFINE
stb_from_utf8(stb__wchar * buffer,const char * ostr,int n)1010 stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *ostr, int n)
1011 {
1012 unsigned char *str = (unsigned char *) ostr;
1013 stb_uint32 c;
1014 int i=0;
1015 --n;
1016 while (*str) {
1017 if (i >= n)
1018 return NULL;
1019 if (!(*str & 0x80))
1020 buffer[i++] = *str++;
1021 else if ((*str & 0xe0) == 0xc0) {
1022 if (*str < 0xc2) return NULL;
1023 c = (*str++ & 0x1f) << 6;
1024 if ((*str & 0xc0) != 0x80) return NULL;
1025 buffer[i++] = c + (*str++ & 0x3f);
1026 } else if ((*str & 0xf0) == 0xe0) {
1027 if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return NULL;
1028 if (*str == 0xed && str[1] > 0x9f) return NULL; // str[1] < 0x80 is checked below
1029 c = (*str++ & 0x0f) << 12;
1030 if ((*str & 0xc0) != 0x80) return NULL;
1031 c += (*str++ & 0x3f) << 6;
1032 if ((*str & 0xc0) != 0x80) return NULL;
1033 buffer[i++] = c + (*str++ & 0x3f);
1034 } else if ((*str & 0xf8) == 0xf0) {
1035 if (*str > 0xf4) return NULL;
1036 if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return NULL;
1037 if (*str == 0xf4 && str[1] > 0x8f) return NULL; // str[1] < 0x80 is checked below
1038 c = (*str++ & 0x07) << 18;
1039 if ((*str & 0xc0) != 0x80) return NULL;
1040 c += (*str++ & 0x3f) << 12;
1041 if ((*str & 0xc0) != 0x80) return NULL;
1042 c += (*str++ & 0x3f) << 6;
1043 if ((*str & 0xc0) != 0x80) return NULL;
1044 c += (*str++ & 0x3f);
1045 // utf-8 encodings of values used in surrogate pairs are invalid
1046 if ((c & 0xFFFFF800) == 0xD800) return NULL;
1047 if (c >= 0x10000) {
1048 c -= 0x10000;
1049 if (i + 2 > n) return NULL;
1050 buffer[i++] = 0xD800 | (0x3ff & (c >> 10));
1051 buffer[i++] = 0xDC00 | (0x3ff & (c ));
1052 }
1053 } else
1054 return NULL;
1055 }
1056 buffer[i] = 0;
1057 return buffer;
1058 }
1059
stb_to_utf8(char * buffer,const stb__wchar * str,int n)1060 char * stb_to_utf8(char *buffer, const stb__wchar *str, int n)
1061 {
1062 int i=0;
1063 --n;
1064 while (*str) {
1065 if (*str < 0x80) {
1066 if (i+1 > n) return NULL;
1067 buffer[i++] = (char) *str++;
1068 } else if (*str < 0x800) {
1069 if (i+2 > n) return NULL;
1070 buffer[i++] = 0xc0 + (*str >> 6);
1071 buffer[i++] = 0x80 + (*str & 0x3f);
1072 str += 1;
1073 } else if (*str >= 0xd800 && *str < 0xdc00) {
1074 stb_uint32 c;
1075 if (i+4 > n) return NULL;
1076 c = ((str[0] - 0xd800) << 10) + ((str[1]) - 0xdc00) + 0x10000;
1077 buffer[i++] = 0xf0 + (c >> 18);
1078 buffer[i++] = 0x80 + ((c >> 12) & 0x3f);
1079 buffer[i++] = 0x80 + ((c >> 6) & 0x3f);
1080 buffer[i++] = 0x80 + ((c ) & 0x3f);
1081 str += 2;
1082 } else if (*str >= 0xdc00 && *str < 0xe000) {
1083 return NULL;
1084 } else {
1085 if (i+3 > n) return NULL;
1086 buffer[i++] = 0xe0 + (*str >> 12);
1087 buffer[i++] = 0x80 + ((*str >> 6) & 0x3f);
1088 buffer[i++] = 0x80 + ((*str ) & 0x3f);
1089 str += 1;
1090 }
1091 }
1092 buffer[i] = 0;
1093 return buffer;
1094 }
1095
stb__from_utf8(const char * str)1096 stb__wchar *stb__from_utf8(const char *str)
1097 {
1098 static stb__wchar buffer[4096];
1099 return stb_from_utf8(buffer, str, 4096);
1100 }
1101
stb__from_utf8_alt(const char * str)1102 stb__wchar *stb__from_utf8_alt(const char *str)
1103 {
1104 static stb__wchar buffer[4096];
1105 return stb_from_utf8(buffer, str, 4096);
1106 }
1107
stb__to_utf8(const stb__wchar * str)1108 char *stb__to_utf8(const stb__wchar *str)
1109 {
1110 static char buffer[4096];
1111 return stb_to_utf8(buffer, str, 4096);
1112 }
1113
1114 #endif
1115
1116 //////////////////////////////////////////////////////////////////////////////
1117 //
1118 // Miscellany
1119 //
1120
1121 STB_EXTERN void stb_fatal(const char *fmt, ...);
1122 STB_EXTERN void stb_(char *fmt, ...);
1123 STB_EXTERN void stb_append_to_file(char *file, char *fmt, ...);
1124 STB_EXTERN void stb_log(int active);
1125 STB_EXTERN void stb_log_fileline(int active);
1126 STB_EXTERN void stb_log_name(char *filename);
1127
1128 STB_EXTERN void stb_swap(void *p, void *q, size_t sz);
1129 STB_EXTERN void *stb_copy(void *p, size_t sz);
1130 STB_EXTERN void stb_pointer_array_free(void *p, int len);
1131 STB_EXTERN void **stb_array_block_alloc(int count, int blocksize);
1132
1133 #define stb_arrcount(x) (sizeof(x)/sizeof((x)[0]))
1134
1135
1136 STB_EXTERN int stb__record_fileline(const char *f, int n);
1137
1138 #ifdef STB_DEFINE
1139
1140 static char *stb__file;
1141 static int stb__line;
1142
stb__record_fileline(const char * f,int n)1143 int stb__record_fileline(const char *f, int n)
1144 {
1145 stb__file = (char*) f;
1146 stb__line = n;
1147 return 0;
1148 }
1149
stb_fatal(const char * s,...)1150 void stb_fatal(const char *s, ...)
1151 {
1152 va_list a;
1153 if (stb__file)
1154 fprintf(stderr, "[%s:%d] ", stb__file, stb__line);
1155 va_start(a,s);
1156 fputs("Fatal error: ", stderr);
1157 vfprintf(stderr, s, a);
1158 va_end(a);
1159 fputs("\n", stderr);
1160 #ifdef STB_DEBUG
1161 #ifdef _MSC_VER
1162 #ifndef STB_PTR64
1163 __asm int 3; // trap to debugger!
1164 #else
1165 __debugbreak();
1166 #endif
1167 #else
1168 __builtin_trap();
1169 #endif
1170 #endif
1171 exit(1);
1172 }
1173
1174 static int stb__log_active=1, stb__log_fileline=1;
1175
stb_log(int active)1176 void stb_log(int active)
1177 {
1178 stb__log_active = active;
1179 }
1180
stb_log_fileline(int active)1181 void stb_log_fileline(int active)
1182 {
1183 stb__log_fileline = active;
1184 }
1185
1186 #ifdef STB_NO_STB_STRINGS
1187 const char *stb__log_filename = "temp.log";
1188 #else
1189 const char *stb__log_filename = "stb.log";
1190 #endif
1191
stb_log_name(char * s)1192 void stb_log_name(char *s)
1193 {
1194 stb__log_filename = s;
1195 }
1196
stb_(char * s,...)1197 void stb_(char *s, ...)
1198 {
1199 if (stb__log_active) {
1200 FILE *f = stb_p_fopen(stb__log_filename, "a");
1201 if (f) {
1202 va_list a;
1203 if (stb__log_fileline && stb__file)
1204 fprintf(f, "[%s:%4d] ", stb__file, stb__line);
1205 va_start(a,s);
1206 vfprintf(f, s, a);
1207 va_end(a);
1208 fputs("\n", f);
1209 fclose(f);
1210 }
1211 }
1212 }
1213
stb_append_to_file(char * filename,char * s,...)1214 void stb_append_to_file(char *filename, char *s, ...)
1215 {
1216 FILE *f = stb_p_fopen(filename, "a");
1217 if (f) {
1218 va_list a;
1219 va_start(a,s);
1220 vfprintf(f, s, a);
1221 va_end(a);
1222 fputs("\n", f);
1223 fclose(f);
1224 }
1225 }
1226
1227
1228 typedef struct { char d[4]; } stb__4;
1229 typedef struct { char d[8]; } stb__8;
1230
1231 // optimize the small cases, though you shouldn't be calling this for those!
stb_swap(void * p,void * q,size_t sz)1232 void stb_swap(void *p, void *q, size_t sz)
1233 {
1234 char buffer[256];
1235 if (p == q) return;
1236 if (sz == 4) {
1237 stb__4 temp = * ( stb__4 *) p;
1238 * (stb__4 *) p = * ( stb__4 *) q;
1239 * (stb__4 *) q = temp;
1240 return;
1241 } else if (sz == 8) {
1242 stb__8 temp = * ( stb__8 *) p;
1243 * (stb__8 *) p = * ( stb__8 *) q;
1244 * (stb__8 *) q = temp;
1245 return;
1246 }
1247
1248 while (sz > sizeof(buffer)) {
1249 stb_swap(p, q, sizeof(buffer));
1250 p = (char *) p + sizeof(buffer);
1251 q = (char *) q + sizeof(buffer);
1252 sz -= sizeof(buffer);
1253 }
1254
1255 memcpy(buffer, p , sz);
1256 memcpy(p , q , sz);
1257 memcpy(q , buffer, sz);
1258 }
1259
stb_copy(void * p,size_t sz)1260 void *stb_copy(void *p, size_t sz)
1261 {
1262 void *q = malloc(sz);
1263 memcpy(q, p, sz);
1264 return q;
1265 }
1266
stb_pointer_array_free(void * q,int len)1267 void stb_pointer_array_free(void *q, int len)
1268 {
1269 void **p = (void **) q;
1270 int i;
1271 for (i=0; i < len; ++i)
1272 free(p[i]);
1273 }
1274
stb_array_block_alloc(int count,int blocksize)1275 void **stb_array_block_alloc(int count, int blocksize)
1276 {
1277 int i;
1278 char *p = (char *) malloc(sizeof(void *) * count + count * blocksize);
1279 void **q;
1280 if (p == NULL) return NULL;
1281 q = (void **) p;
1282 p += sizeof(void *) * count;
1283 for (i=0; i < count; ++i)
1284 q[i] = p + i * blocksize;
1285 return q;
1286 }
1287 #endif
1288
1289 #ifdef STB_DEBUG
1290 // tricky hack to allow recording FILE,LINE even in varargs functions
1291 #define STB__RECORD_FILE(x) (stb__record_fileline(__FILE__, __LINE__),(x))
1292 #define stb_log STB__RECORD_FILE(stb_log)
1293 #define stb_ STB__RECORD_FILE(stb_)
1294 #ifndef STB_FATAL_CLEAN
1295 #define stb_fatal STB__RECORD_FILE(stb_fatal)
1296 #endif
1297 #define STB__DEBUG(x) x
1298 #else
1299 #define STB__DEBUG(x)
1300 #endif
1301
1302 //////////////////////////////////////////////////////////////////////////////
1303 //
1304 // stb_temp
1305 //
1306
1307 #define stb_temp(block, sz) stb__temp(block, sizeof(block), (sz))
1308
1309 STB_EXTERN void * stb__temp(void *b, int b_sz, int want_sz);
1310 STB_EXTERN void stb_tempfree(void *block, void *ptr);
1311
1312 #ifdef STB_DEFINE
1313
stb__temp(void * b,int b_sz,int want_sz)1314 void * stb__temp(void *b, int b_sz, int want_sz)
1315 {
1316 if (b_sz >= want_sz)
1317 return b;
1318 else
1319 return malloc(want_sz);
1320 }
1321
stb_tempfree(void * b,void * p)1322 void stb_tempfree(void *b, void *p)
1323 {
1324 if (p != b)
1325 free(p);
1326 }
1327 #endif
1328
1329
1330 //////////////////////////////////////////////////////////////////////////////
1331 //
1332 // math/sampling operations
1333 //
1334
1335
1336 #define stb_lerp(t,a,b) ( (a) + (t) * (float) ((b)-(a)) )
1337 #define stb_unlerp(t,a,b) ( ((t) - (a)) / (float) ((b) - (a)) )
1338
1339 #define stb_clamp(x,xmin,xmax) ((x) < (xmin) ? (xmin) : (x) > (xmax) ? (xmax) : (x))
1340
1341 STB_EXTERN void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize);
1342 STB_EXTERN int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis);
1343 STB_EXTERN void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt);
1344
1345 STB_EXTERN int stb_float_eq(float x, float y, float delta, int max_ulps);
1346 STB_EXTERN int stb_is_prime(unsigned int m);
1347 STB_EXTERN unsigned int stb_power_of_two_nearest_prime(int n);
1348
1349 STB_EXTERN float stb_smoothstep(float t);
1350 STB_EXTERN float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3);
1351
1352 STB_EXTERN double stb_linear_remap(double x, double a, double b,
1353 double c, double d);
1354
1355 #ifdef STB_DEFINE
stb_smoothstep(float t)1356 float stb_smoothstep(float t)
1357 {
1358 return (3 - 2*t)*(t*t);
1359 }
1360
stb_cubic_bezier_1d(float t,float p0,float p1,float p2,float p3)1361 float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3)
1362 {
1363 float it = 1-t;
1364 return it*it*it*p0 + 3*it*it*t*p1 + 3*it*t*t*p2 + t*t*t*p3;
1365 }
1366
stb_newell_normal(float * normal,int num_vert,float ** vert,int normalize)1367 void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize)
1368 {
1369 int i,j;
1370 float p;
1371 normal[0] = normal[1] = normal[2] = 0;
1372 for (i=num_vert-1,j=0; j < num_vert; i=j++) {
1373 float *u = vert[i];
1374 float *v = vert[j];
1375 normal[0] += (u[1] - v[1]) * (u[2] + v[2]);
1376 normal[1] += (u[2] - v[2]) * (u[0] + v[0]);
1377 normal[2] += (u[0] - v[0]) * (u[1] + v[1]);
1378 }
1379 if (normalize) {
1380 p = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
1381 p = (float) (1.0 / sqrt(p));
1382 normal[0] *= p;
1383 normal[1] *= p;
1384 normal[2] *= p;
1385 }
1386 }
1387
stb_box_face_vertex_axis_side(int face_number,int vertex_number,int axis)1388 int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis)
1389 {
1390 static int box_vertices[6][4][3] =
1391 {
1392 { { 1,1,1 }, { 1,0,1 }, { 1,0,0 }, { 1,1,0 } },
1393 { { 0,0,0 }, { 0,0,1 }, { 0,1,1 }, { 0,1,0 } },
1394 { { 0,0,0 }, { 0,1,0 }, { 1,1,0 }, { 1,0,0 } },
1395 { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 } },
1396 { { 1,1,1 }, { 0,1,1 }, { 0,0,1 }, { 1,0,1 } },
1397 { { 1,1,1 }, { 1,1,0 }, { 0,1,0 }, { 0,1,1 } },
1398 };
1399 assert(face_number >= 0 && face_number < 6);
1400 assert(vertex_number >= 0 && vertex_number < 4);
1401 assert(axis >= 0 && axis < 3);
1402 return box_vertices[face_number][vertex_number][axis];
1403 }
1404
stb_linear_controller(float * curpos,float target_pos,float acc,float deacc,float dt)1405 void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt)
1406 {
1407 float sign = 1, p, cp = *curpos;
1408 if (cp == target_pos) return;
1409 if (target_pos < cp) {
1410 target_pos = -target_pos;
1411 cp = -cp;
1412 sign = -1;
1413 }
1414 // first decelerate
1415 if (cp < 0) {
1416 p = cp + deacc * dt;
1417 if (p > 0) {
1418 p = 0;
1419 dt = dt - cp / deacc;
1420 if (dt < 0) dt = 0;
1421 } else {
1422 dt = 0;
1423 }
1424 cp = p;
1425 }
1426 // now accelerate
1427 p = cp + acc*dt;
1428 if (p > target_pos) p = target_pos;
1429 *curpos = p * sign;
1430 // @TODO: testing
1431 }
1432
stb_quadratic_controller(float target_pos,float curpos,float maxvel,float maxacc,float dt,float * curvel)1433 float stb_quadratic_controller(float target_pos, float curpos, float maxvel, float maxacc, float dt, float *curvel)
1434 {
1435 return 0; // @TODO
1436 }
1437
stb_float_eq(float x,float y,float delta,int max_ulps)1438 int stb_float_eq(float x, float y, float delta, int max_ulps)
1439 {
1440 if (fabs(x-y) <= delta) return 1;
1441 if (abs(*(int *)&x - *(int *)&y) <= max_ulps) return 1;
1442 return 0;
1443 }
1444
stb_is_prime(unsigned int m)1445 int stb_is_prime(unsigned int m)
1446 {
1447 unsigned int i,j;
1448 if (m < 2) return 0;
1449 if (m == 2) return 1;
1450 if (!(m & 1)) return 0;
1451 if (m % 3 == 0) return (m == 3);
1452 for (i=5; (j=i*i), j <= m && j > i; i += 6) {
1453 if (m % i == 0) return 0;
1454 if (m % (i+2) == 0) return 0;
1455 }
1456 return 1;
1457 }
1458
stb_power_of_two_nearest_prime(int n)1459 unsigned int stb_power_of_two_nearest_prime(int n)
1460 {
1461 static signed char tab[32] = { 0,0,0,0,1,0,-1,0,1,-1,-1,3,-1,0,-1,2,1,
1462 0,2,0,-1,-4,-1,5,-1,18,-2,15,2,-1,2,0 };
1463 if (!tab[0]) {
1464 int i;
1465 for (i=0; i < 32; ++i)
1466 tab[i] = (1 << i) + 2*tab[i] - 1;
1467 tab[1] = 2;
1468 tab[0] = 1;
1469 }
1470 if (n >= 32) return 0xfffffffb;
1471 return tab[n];
1472 }
1473
stb_linear_remap(double x,double x_min,double x_max,double out_min,double out_max)1474 double stb_linear_remap(double x, double x_min, double x_max,
1475 double out_min, double out_max)
1476 {
1477 return stb_lerp(stb_unlerp(x,x_min,x_max),out_min,out_max);
1478 }
1479 #endif
1480
1481 // create a macro so it's faster, but you can get at the function pointer
1482 #define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d)
1483
1484
1485 //////////////////////////////////////////////////////////////////////////////
1486 //
1487 // bit operations
1488 //
1489
1490 #define stb_big32(c) (((c)[0]<<24) + (c)[1]*65536 + (c)[2]*256 + (c)[3])
1491 #define stb_little32(c) (((c)[3]<<24) + (c)[2]*65536 + (c)[1]*256 + (c)[0])
1492 #define stb_big16(c) ((c)[0]*256 + (c)[1])
1493 #define stb_little16(c) ((c)[1]*256 + (c)[0])
1494
1495 STB_EXTERN int stb_bitcount(unsigned int a);
1496 STB_EXTERN unsigned int stb_bitreverse8(unsigned char n);
1497 STB_EXTERN unsigned int stb_bitreverse(unsigned int n);
1498
1499 STB_EXTERN int stb_is_pow2(size_t);
1500 STB_EXTERN int stb_log2_ceil(size_t);
1501 STB_EXTERN int stb_log2_floor(size_t);
1502
1503 STB_EXTERN int stb_lowbit8(unsigned int n);
1504 STB_EXTERN int stb_highbit8(unsigned int n);
1505
1506 #ifdef STB_DEFINE
stb_bitcount(unsigned int a)1507 int stb_bitcount(unsigned int a)
1508 {
1509 a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
1510 a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
1511 a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
1512 a = (a + (a >> 8)); // max 16 per 8 bits
1513 a = (a + (a >> 16)); // max 32 per 8 bits
1514 return a & 0xff;
1515 }
1516
stb_bitreverse8(unsigned char n)1517 unsigned int stb_bitreverse8(unsigned char n)
1518 {
1519 n = ((n & 0xAA) >> 1) + ((n & 0x55) << 1);
1520 n = ((n & 0xCC) >> 2) + ((n & 0x33) << 2);
1521 return (unsigned char) ((n >> 4) + (n << 4));
1522 }
1523
stb_bitreverse(unsigned int n)1524 unsigned int stb_bitreverse(unsigned int n)
1525 {
1526 n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
1527 n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
1528 n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
1529 n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
1530 return (n >> 16) | (n << 16);
1531 }
1532
stb_is_pow2(size_t n)1533 int stb_is_pow2(size_t n)
1534 {
1535 return (n & (n-1)) == 0;
1536 }
1537
1538 // tricky use of 4-bit table to identify 5 bit positions (note the '-1')
1539 // 3-bit table would require another tree level; 5-bit table wouldn't save one
1540 #if defined(_WIN32) && !defined(__MINGW32__)
1541 #pragma warning(push)
1542 #pragma warning(disable: 4035) // disable warning about no return value
stb_log2_floor(size_t n)1543 int stb_log2_floor(size_t n)
1544 {
1545 #if _MSC_VER > 1700
1546 unsigned long i;
1547 #ifdef STB_PTR64
1548 _BitScanReverse64(&i, n);
1549 #else
1550 _BitScanReverse(&i, n);
1551 #endif
1552 return i != 0 ? i : -1;
1553 #else
1554 __asm {
1555 bsr eax,n
1556 jnz done
1557 mov eax,-1
1558 }
1559 done:;
1560 #endif
1561 }
1562 #pragma warning(pop)
1563 #else
stb_log2_floor(size_t n)1564 int stb_log2_floor(size_t n)
1565 {
1566 static signed char log2_4[16] = { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3 };
1567
1568 #ifdef STB_PTR64
1569 if (n >= ((size_t) 1u << 32))
1570 return stb_log2_floor(n >> 32);
1571 #endif
1572
1573 // 2 compares if n < 16, 3 compares otherwise
1574 if (n < (1U << 14))
1575 if (n < (1U << 4)) return 0 + log2_4[n ];
1576 else if (n < (1U << 9)) return 5 + log2_4[n >> 5];
1577 else return 10 + log2_4[n >> 10];
1578 else if (n < (1U << 24))
1579 if (n < (1U << 19)) return 15 + log2_4[n >> 15];
1580 else return 20 + log2_4[n >> 20];
1581 else if (n < (1U << 29)) return 25 + log2_4[n >> 25];
1582 else return 30 + log2_4[n >> 30];
1583 }
1584 #endif
1585
1586 // define ceil from floor
stb_log2_ceil(size_t n)1587 int stb_log2_ceil(size_t n)
1588 {
1589 if (stb_is_pow2(n)) return stb_log2_floor(n);
1590 else return 1 + stb_log2_floor(n);
1591 }
1592
stb_highbit8(unsigned int n)1593 int stb_highbit8(unsigned int n)
1594 {
1595 return stb_log2_ceil(n&255);
1596 }
1597
stb_lowbit8(unsigned int n)1598 int stb_lowbit8(unsigned int n)
1599 {
1600 static signed char lowbit4[16] = { -1,0,1,0, 2,0,1,0, 3,0,1,0, 2,0,1,0 };
1601 int k = lowbit4[n & 15];
1602 if (k >= 0) return k;
1603 k = lowbit4[(n >> 4) & 15];
1604 if (k >= 0) return k+4;
1605 return k;
1606 }
1607 #endif
1608
1609
1610
1611 //////////////////////////////////////////////////////////////////////////////
1612 //
1613 // qsort Compare Routines
1614 //
1615
1616 #ifdef _WIN32
1617 #define stb_stricmp(a,b) stb_p_stricmp(a,b)
1618 #define stb_strnicmp(a,b,n) stb_p_strnicmp(a,b,n)
1619 #else
1620 #define stb_stricmp(a,b) strcasecmp(a,b)
1621 #define stb_strnicmp(a,b,n) strncasecmp(a,b,n)
1622 #endif
1623
1624
1625 STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b);
1626 STB_EXTERN int (*stb_intcmprev(int offset))(const void *a, const void *b);
1627 STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b);
1628 STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b);
1629 STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b);
1630 STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b);
1631 STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b);
1632
1633 #ifdef STB_DEFINE
1634 static int stb__intcmpoffset, stb__ucharcmpoffset, stb__strcmpoffset;
1635 static int stb__floatcmpoffset, stb__doublecmpoffset;
1636 static int stb__memcmpoffset, stb__memcmpsize;
1637
stb__intcmp(const void * a,const void * b)1638 int stb__intcmp(const void *a, const void *b)
1639 {
1640 const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
1641 const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
1642 return p < q ? -1 : p > q;
1643 }
1644
stb__intcmprev(const void * a,const void * b)1645 int stb__intcmprev(const void *a, const void *b)
1646 {
1647 const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
1648 const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
1649 return q < p ? -1 : q > p;
1650 }
1651
stb__ucharcmp(const void * a,const void * b)1652 int stb__ucharcmp(const void *a, const void *b)
1653 {
1654 const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset);
1655 const int q = *(const unsigned char *) ((const char *) b + stb__ucharcmpoffset);
1656 return p < q ? -1 : p > q;
1657 }
1658
stb__floatcmp(const void * a,const void * b)1659 int stb__floatcmp(const void *a, const void *b)
1660 {
1661 const float p = *(const float *) ((const char *) a + stb__floatcmpoffset);
1662 const float q = *(const float *) ((const char *) b + stb__floatcmpoffset);
1663 return p < q ? -1 : p > q;
1664 }
1665
stb__doublecmp(const void * a,const void * b)1666 int stb__doublecmp(const void *a, const void *b)
1667 {
1668 const double p = *(const double *) ((const char *) a + stb__doublecmpoffset);
1669 const double q = *(const double *) ((const char *) b + stb__doublecmpoffset);
1670 return p < q ? -1 : p > q;
1671 }
1672
stb__qsort_strcmp(const void * a,const void * b)1673 int stb__qsort_strcmp(const void *a, const void *b)
1674 {
1675 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1676 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1677 return strcmp(p,q);
1678 }
1679
stb__qsort_stricmp(const void * a,const void * b)1680 int stb__qsort_stricmp(const void *a, const void *b)
1681 {
1682 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1683 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1684 return stb_stricmp(p,q);
1685 }
1686
stb__memcmp(const void * a,const void * b)1687 int stb__memcmp(const void *a, const void *b)
1688 {
1689 return memcmp((char *) a + stb__memcmpoffset, (char *) b + stb__memcmpoffset, stb__memcmpsize);
1690 }
1691
stb_intcmp(int offset)1692 int (*stb_intcmp(int offset))(const void *, const void *)
1693 {
1694 stb__intcmpoffset = offset;
1695 return &stb__intcmp;
1696 }
1697
stb_intcmprev(int offset)1698 int (*stb_intcmprev(int offset))(const void *, const void *)
1699 {
1700 stb__intcmpoffset = offset;
1701 return &stb__intcmprev;
1702 }
1703
stb_ucharcmp(int offset)1704 int (*stb_ucharcmp(int offset))(const void *, const void *)
1705 {
1706 stb__ucharcmpoffset = offset;
1707 return &stb__ucharcmp;
1708 }
1709
stb_qsort_strcmp(int offset)1710 int (*stb_qsort_strcmp(int offset))(const void *, const void *)
1711 {
1712 stb__strcmpoffset = offset;
1713 return &stb__qsort_strcmp;
1714 }
1715
stb_qsort_stricmp(int offset)1716 int (*stb_qsort_stricmp(int offset))(const void *, const void *)
1717 {
1718 stb__strcmpoffset = offset;
1719 return &stb__qsort_stricmp;
1720 }
1721
stb_floatcmp(int offset)1722 int (*stb_floatcmp(int offset))(const void *, const void *)
1723 {
1724 stb__floatcmpoffset = offset;
1725 return &stb__floatcmp;
1726 }
1727
stb_doublecmp(int offset)1728 int (*stb_doublecmp(int offset))(const void *, const void *)
1729 {
1730 stb__doublecmpoffset = offset;
1731 return &stb__doublecmp;
1732 }
1733
stb_memcmp(int offset,int size)1734 int (*stb_memcmp(int offset, int size))(const void *, const void *)
1735 {
1736 stb__memcmpoffset = offset;
1737 stb__memcmpsize = size;
1738 return &stb__memcmp;
1739 }
1740 #endif
1741
1742 //////////////////////////////////////////////////////////////////////////////
1743 //
1744 // Binary Search Toolkit
1745 //
1746
1747 typedef struct
1748 {
1749 int minval, maxval, guess;
1750 int mode, step;
1751 } stb_search;
1752
1753 STB_EXTERN int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest);
1754 STB_EXTERN int stb_search_open(stb_search *s, int minv, int find_smallest);
1755 STB_EXTERN int stb_probe(stb_search *s, int compare, int *result); // return 0 when done
1756
1757 #ifdef STB_DEFINE
1758 enum
1759 {
1760 STB_probe_binary_smallest,
1761 STB_probe_binary_largest,
1762 STB_probe_open_smallest,
1763 STB_probe_open_largest,
1764 };
1765
stb_probe_guess(stb_search * s,int * result)1766 static int stb_probe_guess(stb_search *s, int *result)
1767 {
1768 switch(s->mode) {
1769 case STB_probe_binary_largest:
1770 if (s->minval == s->maxval) {
1771 *result = s->minval;
1772 return 0;
1773 }
1774 assert(s->minval < s->maxval);
1775 // if a < b, then a < p <= b
1776 s->guess = s->minval + (((unsigned) s->maxval - s->minval + 1) >> 1);
1777 break;
1778
1779 case STB_probe_binary_smallest:
1780 if (s->minval == s->maxval) {
1781 *result = s->minval;
1782 return 0;
1783 }
1784 assert(s->minval < s->maxval);
1785 // if a < b, then a <= p < b
1786 s->guess = s->minval + (((unsigned) s->maxval - s->minval) >> 1);
1787 break;
1788 case STB_probe_open_smallest:
1789 case STB_probe_open_largest:
1790 s->guess = s->maxval; // guess the current maxval
1791 break;
1792 }
1793 *result = s->guess;
1794 return 1;
1795 }
1796
stb_probe(stb_search * s,int compare,int * result)1797 int stb_probe(stb_search *s, int compare, int *result)
1798 {
1799 switch(s->mode) {
1800 case STB_probe_open_smallest:
1801 case STB_probe_open_largest: {
1802 if (compare <= 0) {
1803 // then it lies within minval & maxval
1804 if (s->mode == STB_probe_open_smallest)
1805 s->mode = STB_probe_binary_smallest;
1806 else
1807 s->mode = STB_probe_binary_largest;
1808 } else {
1809 // otherwise, we need to probe larger
1810 s->minval = s->maxval + 1;
1811 s->maxval = s->minval + s->step;
1812 s->step += s->step;
1813 }
1814 break;
1815 }
1816 case STB_probe_binary_smallest: {
1817 // if compare < 0, then s->minval <= a < p
1818 // if compare = 0, then s->minval <= a <= p
1819 // if compare > 0, then p < a <= s->maxval
1820 if (compare <= 0)
1821 s->maxval = s->guess;
1822 else
1823 s->minval = s->guess+1;
1824 break;
1825 }
1826 case STB_probe_binary_largest: {
1827 // if compare < 0, then s->minval <= a < p
1828 // if compare = 0, then p <= a <= s->maxval
1829 // if compare > 0, then p < a <= s->maxval
1830 if (compare < 0)
1831 s->maxval = s->guess-1;
1832 else
1833 s->minval = s->guess;
1834 break;
1835 }
1836 }
1837 return stb_probe_guess(s, result);
1838 }
1839
stb_search_binary(stb_search * s,int minv,int maxv,int find_smallest)1840 int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest)
1841 {
1842 int r;
1843 if (maxv < minv) return minv-1;
1844 s->minval = minv;
1845 s->maxval = maxv;
1846 s->mode = find_smallest ? STB_probe_binary_smallest : STB_probe_binary_largest;
1847 stb_probe_guess(s, &r);
1848 return r;
1849 }
1850
stb_search_open(stb_search * s,int minv,int find_smallest)1851 int stb_search_open(stb_search *s, int minv, int find_smallest)
1852 {
1853 int r;
1854 s->step = 4;
1855 s->minval = minv;
1856 s->maxval = minv+s->step;
1857 s->mode = find_smallest ? STB_probe_open_smallest : STB_probe_open_largest;
1858 stb_probe_guess(s, &r);
1859 return r;
1860 }
1861 #endif
1862
1863 //////////////////////////////////////////////////////////////////////////////
1864 //
1865 // String Processing
1866 //
1867
1868 #define stb_prefixi(s,t) (0==stb_strnicmp((s),(t),strlen(t)))
1869
1870 enum stb_splitpath_flag
1871 {
1872 STB_PATH = 1,
1873 STB_FILE = 2,
1874 STB_EXT = 4,
1875 STB_PATH_FILE = STB_PATH + STB_FILE,
1876 STB_FILE_EXT = STB_FILE + STB_EXT,
1877 STB_EXT_NO_PERIOD = 8,
1878 };
1879
1880 STB_EXTERN char * stb_skipwhite(char *s);
1881 STB_EXTERN char * stb_trimwhite(char *s);
1882 STB_EXTERN char * stb_skipnewline(char *s);
1883 STB_EXTERN char * stb_strncpy(char *s, char *t, int n);
1884 STB_EXTERN char * stb_substr(char *t, int n);
1885 STB_EXTERN char * stb_duplower(char *s);
1886 STB_EXTERN void stb_tolower (char *s);
1887 STB_EXTERN char * stb_strchr2 (char *s, char p1, char p2);
1888 STB_EXTERN char * stb_strrchr2(char *s, char p1, char p2);
1889 STB_EXTERN char * stb_strtok(char *output, char *src, char *delimit);
1890 STB_EXTERN char * stb_strtok_keep(char *output, char *src, char *delimit);
1891 STB_EXTERN char * stb_strtok_invert(char *output, char *src, char *allowed);
1892 STB_EXTERN char * stb_dupreplace(char *s, char *find, char *replace);
1893 STB_EXTERN void stb_replaceinplace(char *s, char *find, char *replace);
1894 STB_EXTERN char * stb_splitpath(char *output, char *src, int flag);
1895 STB_EXTERN char * stb_splitpathdup(char *src, int flag);
1896 STB_EXTERN char * stb_replacedir(char *output, char *src, char *dir);
1897 STB_EXTERN char * stb_replaceext(char *output, char *src, char *ext);
1898 STB_EXTERN void stb_fixpath(char *path);
1899 STB_EXTERN char * stb_shorten_path_readable(char *path, int max_len);
1900 STB_EXTERN int stb_suffix (char *s, char *t);
1901 STB_EXTERN int stb_suffixi(char *s, char *t);
1902 STB_EXTERN int stb_prefix (char *s, char *t);
1903 STB_EXTERN char * stb_strichr(char *s, char t);
1904 STB_EXTERN char * stb_stristr(char *s, char *t);
1905 STB_EXTERN int stb_prefix_count(char *s, char *t);
1906 STB_EXTERN const char * stb_plural(int n); // "s" or ""
1907 STB_EXTERN size_t stb_strscpy(char *d, const char *s, size_t n);
1908
1909 STB_EXTERN char **stb_tokens(char *src, char *delimit, int *count);
1910 STB_EXTERN char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1911 STB_EXTERN char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1912 STB_EXTERN char **stb_tokens_allowempty(char *src, char *delimit, int *count);
1913 STB_EXTERN char **stb_tokens_stripwhite(char *src, char *delimit, int *count);
1914 STB_EXTERN char **stb_tokens_withdelim(char *src, char *delimit, int *count);
1915 STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count);
1916 // with 'quoted', allow delimiters to appear inside quotation marks, and don't
1917 // strip whitespace inside them (and we delete the quotation marks unless they
1918 // appear back to back, in which case they're considered escaped)
1919
1920 #ifdef STB_DEFINE
1921
stb_strscpy(char * d,const char * s,size_t n)1922 size_t stb_strscpy(char *d, const char *s, size_t n)
1923 {
1924 size_t len = strlen(s);
1925 if (len >= n) {
1926 if (n) d[0] = 0;
1927 return 0;
1928 }
1929 stb_p_strcpy_s(d,n+1,s);
1930 return len + 1;
1931 }
1932
stb_plural(int n)1933 const char *stb_plural(int n)
1934 {
1935 return n == 1 ? "" : "s";
1936 }
1937
stb_prefix(char * s,char * t)1938 int stb_prefix(char *s, char *t)
1939 {
1940 while (*t)
1941 if (*s++ != *t++)
1942 return STB_FALSE;
1943 return STB_TRUE;
1944 }
1945
stb_prefix_count(char * s,char * t)1946 int stb_prefix_count(char *s, char *t)
1947 {
1948 int c=0;
1949 while (*t) {
1950 if (*s++ != *t++)
1951 break;
1952 ++c;
1953 }
1954 return c;
1955 }
1956
stb_suffix(char * s,char * t)1957 int stb_suffix(char *s, char *t)
1958 {
1959 size_t n = strlen(s);
1960 size_t m = strlen(t);
1961 if (m <= n)
1962 return 0 == strcmp(s+n-m, t);
1963 else
1964 return 0;
1965 }
1966
stb_suffixi(char * s,char * t)1967 int stb_suffixi(char *s, char *t)
1968 {
1969 size_t n = strlen(s);
1970 size_t m = strlen(t);
1971 if (m <= n)
1972 return 0 == stb_stricmp(s+n-m, t);
1973 else
1974 return 0;
1975 }
1976
1977 // originally I was using this table so that I could create known sentinel
1978 // values--e.g. change whitetable[0] to be true if I was scanning for whitespace,
1979 // and false if I was scanning for nonwhite. I don't appear to be using that
1980 // functionality anymore (I do for tokentable, though), so just replace it
1981 // with isspace()
stb_skipwhite(char * s)1982 char *stb_skipwhite(char *s)
1983 {
1984 while (isspace((unsigned char) *s)) ++s;
1985 return s;
1986 }
1987
stb_skipnewline(char * s)1988 char *stb_skipnewline(char *s)
1989 {
1990 if (s[0] == '\r' || s[0] == '\n') {
1991 if (s[0]+s[1] == '\r' + '\n') ++s;
1992 ++s;
1993 }
1994 return s;
1995 }
1996
stb_trimwhite(char * s)1997 char *stb_trimwhite(char *s)
1998 {
1999 int i,n;
2000 s = stb_skipwhite(s);
2001 n = (int) strlen(s);
2002 for (i=n-1; i >= 0; --i)
2003 if (!isspace(s[i]))
2004 break;
2005 s[i+1] = 0;
2006 return s;
2007 }
2008
stb_strncpy(char * s,char * t,int n)2009 char *stb_strncpy(char *s, char *t, int n)
2010 {
2011 stb_p_strncpy_s(s,n+1,t,n);
2012 s[n-1] = 0;
2013 return s;
2014 }
2015
stb_substr(char * t,int n)2016 char *stb_substr(char *t, int n)
2017 {
2018 char *a;
2019 int z = (int) strlen(t);
2020 if (z < n) n = z;
2021 a = (char *) malloc(n+1);
2022 stb_p_strncpy_s(a,n+1,t,n);
2023 a[n] = 0;
2024 return a;
2025 }
2026
stb_duplower(char * s)2027 char *stb_duplower(char *s)
2028 {
2029 char *p = stb_p_strdup(s), *q = p;
2030 while (*q) {
2031 *q = tolower(*q);
2032 ++q;
2033 }
2034 return p;
2035 }
2036
stb_tolower(char * s)2037 void stb_tolower(char *s)
2038 {
2039 while (*s) {
2040 *s = tolower(*s);
2041 ++s;
2042 }
2043 }
2044
stb_strchr2(char * s,char x,char y)2045 char *stb_strchr2(char *s, char x, char y)
2046 {
2047 for(; *s; ++s)
2048 if (*s == x || *s == y)
2049 return s;
2050 return NULL;
2051 }
2052
stb_strrchr2(char * s,char x,char y)2053 char *stb_strrchr2(char *s, char x, char y)
2054 {
2055 char *r = NULL;
2056 for(; *s; ++s)
2057 if (*s == x || *s == y)
2058 r = s;
2059 return r;
2060 }
2061
stb_strichr(char * s,char t)2062 char *stb_strichr(char *s, char t)
2063 {
2064 if (tolower(t) == toupper(t))
2065 return strchr(s,t);
2066 return stb_strchr2(s, (char) tolower(t), (char) toupper(t));
2067 }
2068
stb_stristr(char * s,char * t)2069 char *stb_stristr(char *s, char *t)
2070 {
2071 size_t n = strlen(t);
2072 char *z;
2073 if (n==0) return s;
2074 while ((z = stb_strichr(s, *t)) != NULL) {
2075 if (0==stb_strnicmp(z, t, n))
2076 return z;
2077 s = z+1;
2078 }
2079 return NULL;
2080 }
2081
stb_strtok_raw(char * output,char * src,char * delimit,int keep,int invert)2082 static char *stb_strtok_raw(char *output, char *src, char *delimit, int keep, int invert)
2083 {
2084 if (invert) {
2085 while (*src && strchr(delimit, *src) != NULL) {
2086 *output++ = *src++;
2087 }
2088 } else {
2089 while (*src && strchr(delimit, *src) == NULL) {
2090 *output++ = *src++;
2091 }
2092 }
2093 *output = 0;
2094 if (keep)
2095 return src;
2096 else
2097 return *src ? src+1 : src;
2098 }
2099
stb_strtok(char * output,char * src,char * delimit)2100 char *stb_strtok(char *output, char *src, char *delimit)
2101 {
2102 return stb_strtok_raw(output, src, delimit, 0, 0);
2103 }
2104
stb_strtok_keep(char * output,char * src,char * delimit)2105 char *stb_strtok_keep(char *output, char *src, char *delimit)
2106 {
2107 return stb_strtok_raw(output, src, delimit, 1, 0);
2108 }
2109
stb_strtok_invert(char * output,char * src,char * delimit)2110 char *stb_strtok_invert(char *output, char *src, char *delimit)
2111 {
2112 return stb_strtok_raw(output, src, delimit, 1,1);
2113 }
2114
stb_tokens_raw(char * src_,char * delimit,int * count,int stripwhite,int allow_empty,char * start,char * end)2115 static char **stb_tokens_raw(char *src_, char *delimit, int *count,
2116 int stripwhite, int allow_empty, char *start, char *end)
2117 {
2118 int nested = 0;
2119 unsigned char *src = (unsigned char *) src_;
2120 static char stb_tokentable[256]; // rely on static initializion to 0
2121 static char stable[256],etable[256];
2122 char *out;
2123 char **result;
2124 int num=0;
2125 unsigned char *s;
2126
2127 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 1;
2128 if (start) {
2129 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2130 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2131 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2132 }
2133 stable[0] = 1;
2134
2135 // two passes through: the first time, counting how many
2136 s = (unsigned char *) src;
2137 while (*s) {
2138 // state: just found delimiter
2139 // skip further delimiters
2140 if (!allow_empty) {
2141 stb_tokentable[0] = 0;
2142 while (stb_tokentable[*s])
2143 ++s;
2144 if (!*s) break;
2145 }
2146 ++num;
2147 // skip further non-delimiters
2148 stb_tokentable[0] = 1;
2149 if (stripwhite == 2) { // quoted strings
2150 while (!stb_tokentable[*s]) {
2151 if (*s != '"')
2152 ++s;
2153 else {
2154 ++s;
2155 if (*s == '"')
2156 ++s; // "" -> ", not start a string
2157 else {
2158 // begin a string
2159 while (*s) {
2160 if (s[0] == '"') {
2161 if (s[1] == '"') s += 2; // "" -> "
2162 else { ++s; break; } // terminating "
2163 } else
2164 ++s;
2165 }
2166 }
2167 }
2168 }
2169 } else
2170 while (nested || !stb_tokentable[*s]) {
2171 if (stable[*s]) {
2172 if (!*s) break;
2173 if (end ? etable[*s] : nested)
2174 --nested;
2175 else
2176 ++nested;
2177 }
2178 ++s;
2179 }
2180 if (allow_empty) {
2181 if (*s) ++s;
2182 }
2183 }
2184 // now num has the actual count... malloc our output structure
2185 // need space for all the strings: strings won't be any longer than
2186 // original input, since for every '\0' there's at least one delimiter
2187 result = (char **) malloc(sizeof(*result) * (num+1) + (s-src+1));
2188 if (result == NULL) return result;
2189 out = (char *) (result + (num+1));
2190 // second pass: copy out the data
2191 s = (unsigned char *) src;
2192 num = 0;
2193 nested = 0;
2194 while (*s) {
2195 char *last_nonwhite;
2196 // state: just found delimiter
2197 // skip further delimiters
2198 if (!allow_empty) {
2199 stb_tokentable[0] = 0;
2200 if (stripwhite)
2201 while (stb_tokentable[*s] || isspace(*s))
2202 ++s;
2203 else
2204 while (stb_tokentable[*s])
2205 ++s;
2206 } else if (stripwhite) {
2207 while (isspace(*s)) ++s;
2208 }
2209 if (!*s) break;
2210 // we're past any leading delimiters and whitespace
2211 result[num] = out;
2212 ++num;
2213 // copy non-delimiters
2214 stb_tokentable[0] = 1;
2215 last_nonwhite = out-1;
2216 if (stripwhite == 2) {
2217 while (!stb_tokentable[*s]) {
2218 if (*s != '"') {
2219 if (!isspace(*s)) last_nonwhite = out;
2220 *out++ = *s++;
2221 } else {
2222 ++s;
2223 if (*s == '"') {
2224 if (!isspace(*s)) last_nonwhite = out;
2225 *out++ = *s++; // "" -> ", not start string
2226 } else {
2227 // begin a quoted string
2228 while (*s) {
2229 if (s[0] == '"') {
2230 if (s[1] == '"') { *out++ = *s; s += 2; }
2231 else { ++s; break; } // terminating "
2232 } else
2233 *out++ = *s++;
2234 }
2235 last_nonwhite = out-1; // all in quotes counts as non-white
2236 }
2237 }
2238 }
2239 } else {
2240 while (nested || !stb_tokentable[*s]) {
2241 if (!isspace(*s)) last_nonwhite = out;
2242 if (stable[*s]) {
2243 if (!*s) break;
2244 if (end ? etable[*s] : nested)
2245 --nested;
2246 else
2247 ++nested;
2248 }
2249 *out++ = *s++;
2250 }
2251 }
2252
2253 if (stripwhite) // rewind to last non-whitespace char
2254 out = last_nonwhite+1;
2255 *out++ = '\0';
2256
2257 if (*s) ++s; // skip delimiter
2258 }
2259 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 0;
2260 if (start) {
2261 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2262 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2263 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2264 }
2265 if (count != NULL) *count = num;
2266 result[num] = 0;
2267 return result;
2268 }
2269
stb_tokens(char * src,char * delimit,int * count)2270 char **stb_tokens(char *src, char *delimit, int *count)
2271 {
2272 return stb_tokens_raw(src,delimit,count,0,0,0,0);
2273 }
2274
stb_tokens_nested(char * src,char * delimit,int * count,char * nest_in,char * nest_out)2275 char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2276 {
2277 return stb_tokens_raw(src,delimit,count,0,0,nest_in,nest_out);
2278 }
2279
stb_tokens_nested_empty(char * src,char * delimit,int * count,char * nest_in,char * nest_out)2280 char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2281 {
2282 return stb_tokens_raw(src,delimit,count,0,1,nest_in,nest_out);
2283 }
2284
stb_tokens_allowempty(char * src,char * delimit,int * count)2285 char **stb_tokens_allowempty(char *src, char *delimit, int *count)
2286 {
2287 return stb_tokens_raw(src,delimit,count,0,1,0,0);
2288 }
2289
stb_tokens_stripwhite(char * src,char * delimit,int * count)2290 char **stb_tokens_stripwhite(char *src, char *delimit, int *count)
2291 {
2292 return stb_tokens_raw(src,delimit,count,1,1,0,0);
2293 }
2294
stb_tokens_quoted(char * src,char * delimit,int * count)2295 char **stb_tokens_quoted(char *src, char *delimit, int *count)
2296 {
2297 return stb_tokens_raw(src,delimit,count,2,1,0,0);
2298 }
2299
stb_dupreplace(char * src,char * find,char * replace)2300 char *stb_dupreplace(char *src, char *find, char *replace)
2301 {
2302 size_t len_find = strlen(find);
2303 size_t len_replace = strlen(replace);
2304 int count = 0;
2305
2306 char *s,*p,*q;
2307
2308 s = strstr(src, find);
2309 if (s == NULL) return stb_p_strdup(src);
2310 do {
2311 ++count;
2312 s = strstr(s + len_find, find);
2313 } while (s != NULL);
2314
2315 p = (char *) malloc(strlen(src) + count * (len_replace - len_find) + 1);
2316 if (p == NULL) return p;
2317 q = p;
2318 s = src;
2319 for (;;) {
2320 char *t = strstr(s, find);
2321 if (t == NULL) {
2322 stb_p_strcpy_s(q,strlen(src)+count*(len_replace-len_find)+1,s);
2323 assert(strlen(p) == strlen(src) + count*(len_replace-len_find));
2324 return p;
2325 }
2326 memcpy(q, s, t-s);
2327 q += t-s;
2328 memcpy(q, replace, len_replace);
2329 q += len_replace;
2330 s = t + len_find;
2331 }
2332 }
2333
stb_replaceinplace(char * src,char * find,char * replace)2334 void stb_replaceinplace(char *src, char *find, char *replace)
2335 {
2336 size_t len_find = strlen(find);
2337 size_t len_replace = strlen(replace);
2338 int delta;
2339
2340 char *s,*p,*q;
2341
2342 delta = (int) (len_replace - len_find);
2343 assert(delta <= 0);
2344 if (delta > 0) return;
2345
2346 p = strstr(src, find);
2347 if (p == NULL) return;
2348
2349 s = q = p;
2350 while (*s) {
2351 memcpy(q, replace, len_replace);
2352 p += len_find;
2353 q += len_replace;
2354 s = strstr(p, find);
2355 if (s == NULL) s = p + strlen(p);
2356 memmove(q, p, s-p);
2357 q += s-p;
2358 p = s;
2359 }
2360 *q = 0;
2361 }
2362
stb_fixpath(char * path)2363 void stb_fixpath(char *path)
2364 {
2365 for(; *path; ++path)
2366 if (*path == '\\')
2367 *path = '/';
2368 }
2369
stb__add_section(char * buffer,char * data,ptrdiff_t curlen,ptrdiff_t newlen)2370 void stb__add_section(char *buffer, char *data, ptrdiff_t curlen, ptrdiff_t newlen)
2371 {
2372 if (newlen < curlen) {
2373 ptrdiff_t z1 = newlen >> 1, z2 = newlen-z1;
2374 memcpy(buffer, data, z1-1);
2375 buffer[z1-1] = '.';
2376 buffer[z1-0] = '.';
2377 memcpy(buffer+z1+1, data+curlen-z2+1, z2-1);
2378 } else
2379 memcpy(buffer, data, curlen);
2380 }
2381
stb_shorten_path_readable(char * path,int len)2382 char * stb_shorten_path_readable(char *path, int len)
2383 {
2384 static char buffer[1024];
2385 ptrdiff_t n = strlen(path),n1,n2,r1,r2;
2386 char *s;
2387 if (n <= len) return path;
2388 if (len > 1024) return path;
2389 s = stb_strrchr2(path, '/', '\\');
2390 if (s) {
2391 n1 = s - path + 1;
2392 n2 = n - n1;
2393 ++s;
2394 } else {
2395 n1 = 0;
2396 n2 = n;
2397 s = path;
2398 }
2399 // now we need to reduce r1 and r2 so that they fit in len
2400 if (n1 < len>>1) {
2401 r1 = n1;
2402 r2 = len - r1;
2403 } else if (n2 < len >> 1) {
2404 r2 = n2;
2405 r1 = len - r2;
2406 } else {
2407 r1 = n1 * len / n;
2408 r2 = n2 * len / n;
2409 if (r1 < len>>2) r1 = len>>2, r2 = len-r1;
2410 if (r2 < len>>2) r2 = len>>2, r1 = len-r2;
2411 }
2412 assert(r1 <= n1 && r2 <= n2);
2413 if (n1)
2414 stb__add_section(buffer, path, n1, r1);
2415 stb__add_section(buffer+r1, s, n2, r2);
2416 buffer[len] = 0;
2417 return buffer;
2418 }
2419
stb__splitpath_raw(char * buffer,char * path,int flag)2420 static char *stb__splitpath_raw(char *buffer, char *path, int flag)
2421 {
2422 ptrdiff_t len=0,x,y, n = (int) strlen(path), f1,f2;
2423 char *s = stb_strrchr2(path, '/', '\\');
2424 char *t = strrchr(path, '.');
2425 if (s && t && t < s) t = NULL;
2426 if (s) ++s;
2427
2428 if (flag == STB_EXT_NO_PERIOD)
2429 flag |= STB_EXT;
2430
2431 if (!(flag & (STB_PATH | STB_FILE | STB_EXT))) return NULL;
2432
2433 f1 = s == NULL ? 0 : s-path; // start of filename
2434 f2 = t == NULL ? n : t-path; // just past end of filename
2435
2436 if (flag & STB_PATH) {
2437 x = 0; if (f1 == 0 && flag == STB_PATH) len=2;
2438 } else if (flag & STB_FILE) {
2439 x = f1;
2440 } else {
2441 x = f2;
2442 if (flag & STB_EXT_NO_PERIOD)
2443 if (buffer[x] == '.')
2444 ++x;
2445 }
2446
2447 if (flag & STB_EXT)
2448 y = n;
2449 else if (flag & STB_FILE)
2450 y = f2;
2451 else
2452 y = f1;
2453
2454 if (buffer == NULL) {
2455 buffer = (char *) malloc(y-x + len + 1);
2456 if (!buffer) return NULL;
2457 }
2458
2459 if (len) { stb_p_strcpy_s(buffer, sizeof(buffer), "./"); return buffer; }
2460 stb_p_strncpy_s(buffer, sizeof(buffer),path+x, y-x);
2461 buffer[y-x] = 0;
2462 return buffer;
2463 }
2464
stb_splitpath(char * output,char * src,int flag)2465 char *stb_splitpath(char *output, char *src, int flag)
2466 {
2467 return stb__splitpath_raw(output, src, flag);
2468 }
2469
stb_splitpathdup(char * src,int flag)2470 char *stb_splitpathdup(char *src, int flag)
2471 {
2472 return stb__splitpath_raw(NULL, src, flag);
2473 }
2474
stb_replacedir(char * output,char * src,char * dir)2475 char *stb_replacedir(char *output, char *src, char *dir)
2476 {
2477 char buffer[4096];
2478 stb_splitpath(buffer, src, STB_FILE | STB_EXT);
2479 if (dir)
2480 stb_p_sprintf(output stb_p_size(9999), "%s/%s", dir, buffer);
2481 else
2482 stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
2483 return output;
2484 }
2485
stb_replaceext(char * output,char * src,char * ext)2486 char *stb_replaceext(char *output, char *src, char *ext)
2487 {
2488 char buffer[4096];
2489 stb_splitpath(buffer, src, STB_PATH | STB_FILE);
2490 if (ext)
2491 stb_p_sprintf(output stb_p_size(9999), "%s.%s", buffer, ext[0] == '.' ? ext+1 : ext);
2492 else
2493 stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
2494 return output;
2495 }
2496 #endif
2497
2498 //////////////////////////////////////////////////////////////////////////////
2499 //
2500 // stb_alloc - hierarchical allocator
2501 //
2502 // inspired by http://swapped.cc/halloc
2503 //
2504 //
2505 // When you alloc a given block through stb_alloc, you have these choices:
2506 //
2507 // 1. does it have a parent?
2508 // 2. can it have children?
2509 // 3. can it be freed directly?
2510 // 4. is it transferrable?
2511 // 5. what is its alignment?
2512 //
2513 // Here are interesting combinations of those:
2514 //
2515 // children free transfer alignment
2516 // arena Y Y N n/a
2517 // no-overhead, chunked N N N normal
2518 // string pool alloc N N N 1
2519 // parent-ptr, chunked Y N N normal
2520 // low-overhead, unchunked N Y Y normal
2521 // general purpose alloc Y Y Y normal
2522 //
2523 // Unchunked allocations will probably return 16-aligned pointers. If
2524 // we 16-align the results, we have room for 4 pointers. For smaller
2525 // allocations that allow finer alignment, we can reduce the pointers.
2526 //
2527 // The strategy is that given a pointer, assuming it has a header (only
2528 // the no-overhead allocations have no header), we can determine the
2529 // type of the header fields, and the number of them, by stepping backwards
2530 // through memory and looking at the tags in the bottom bits.
2531 //
2532 // Implementation strategy:
2533 // chunked allocations come from the middle of chunks, and can't
2534 // be freed. thefore they do not need to be on a sibling chain.
2535 // they may need child pointers if they have children.
2536 //
2537 // chunked, with-children
2538 // void *parent;
2539 //
2540 // unchunked, no-children -- reduced storage
2541 // void *next_sibling;
2542 // void *prev_sibling_nextp;
2543 //
2544 // unchunked, general
2545 // void *first_child;
2546 // void *next_sibling;
2547 // void *prev_sibling_nextp;
2548 // void *chunks;
2549 //
2550 // so, if we code each of these fields with different bit patterns
2551 // (actually same one for next/prev/child), then we can identify which
2552 // each one is from the last field.
2553
2554 STB_EXTERN void stb_free(void *p);
2555 STB_EXTERN void *stb_malloc_global(size_t size);
2556 STB_EXTERN void *stb_malloc(void *context, size_t size);
2557 STB_EXTERN void *stb_malloc_nofree(void *context, size_t size);
2558 STB_EXTERN void *stb_malloc_leaf(void *context, size_t size);
2559 STB_EXTERN void *stb_malloc_raw(void *context, size_t size);
2560 STB_EXTERN void *stb_realloc(void *ptr, size_t newsize);
2561
2562 STB_EXTERN void stb_reassign(void *new_context, void *ptr);
2563 STB_EXTERN void stb_malloc_validate(void *p, void *parent);
2564
2565 extern int stb_alloc_chunk_size ;
2566 extern int stb_alloc_count_free ;
2567 extern int stb_alloc_count_alloc;
2568 extern int stb_alloc_alignment ;
2569
2570 #ifdef STB_DEFINE
2571
2572 int stb_alloc_chunk_size = 65536;
2573 int stb_alloc_count_free = 0;
2574 int stb_alloc_count_alloc = 0;
2575 int stb_alloc_alignment = -16;
2576
2577 typedef struct stb__chunk
2578 {
2579 struct stb__chunk *next;
2580 int data_left;
2581 int alloc;
2582 } stb__chunk;
2583
2584 typedef struct
2585 {
2586 void * next;
2587 void ** prevn;
2588 } stb__nochildren;
2589
2590 typedef struct
2591 {
2592 void ** prevn;
2593 void * child;
2594 void * next;
2595 stb__chunk *chunks;
2596 } stb__alloc;
2597
2598 typedef struct
2599 {
2600 stb__alloc *parent;
2601 } stb__chunked;
2602
2603 #define STB__PARENT 1
2604 #define STB__CHUNKS 2
2605
2606 typedef enum
2607 {
2608 STB__nochildren = 0,
2609 STB__chunked = STB__PARENT,
2610 STB__alloc = STB__CHUNKS,
2611
2612 STB__chunk_raw = 4,
2613 } stb__alloc_type;
2614
2615 // these functions set the bottom bits of a pointer efficiently
2616 #define STB__DECODE(x,v) ((void *) ((char *) (x) - (v)))
2617 #define STB__ENCODE(x,v) ((void *) ((char *) (x) + (v)))
2618
2619 #define stb__parent(z) (stb__alloc *) STB__DECODE((z)->parent, STB__PARENT)
2620 #define stb__chunks(z) (stb__chunk *) STB__DECODE((z)->chunks, STB__CHUNKS)
2621
2622 #define stb__setparent(z,p) (z)->parent = (stb__alloc *) STB__ENCODE((p), STB__PARENT)
2623 #define stb__setchunks(z,c) (z)->chunks = (stb__chunk *) STB__ENCODE((c), STB__CHUNKS)
2624
2625 static stb__alloc stb__alloc_global =
2626 {
2627 NULL,
2628 NULL,
2629 NULL,
2630 (stb__chunk *) STB__ENCODE(NULL, STB__CHUNKS)
2631 };
2632
stb__identify(void * p)2633 static stb__alloc_type stb__identify(void *p)
2634 {
2635 void **q = (void **) p;
2636 return (stb__alloc_type) ((stb_uinta) q[-1] & 3);
2637 }
2638
stb__prevn(void * p)2639 static void *** stb__prevn(void *p)
2640 {
2641 if (stb__identify(p) == STB__alloc) {
2642 stb__alloc *s = (stb__alloc *) p - 1;
2643 return &s->prevn;
2644 } else {
2645 stb__nochildren *s = (stb__nochildren *) p - 1;
2646 return &s->prevn;
2647 }
2648 }
2649
stb_free(void * p)2650 void stb_free(void *p)
2651 {
2652 if (p == NULL) return;
2653
2654 // count frees so that unit tests can see what's happening
2655 ++stb_alloc_count_free;
2656
2657 switch(stb__identify(p)) {
2658 case STB__chunked:
2659 // freeing a chunked-block with children does nothing;
2660 // they only get freed when the parent does
2661 // surely this is wrong, and it should free them immediately?
2662 // otherwise how are they getting put on the right chain?
2663 return;
2664 case STB__nochildren: {
2665 stb__nochildren *s = (stb__nochildren *) p - 1;
2666 // unlink from sibling chain
2667 *(s->prevn) = s->next;
2668 if (s->next)
2669 *stb__prevn(s->next) = s->prevn;
2670 free(s);
2671 return;
2672 }
2673 case STB__alloc: {
2674 stb__alloc *s = (stb__alloc *) p - 1;
2675 stb__chunk *c, *n;
2676 void *q;
2677
2678 // unlink from sibling chain, if any
2679 *(s->prevn) = s->next;
2680 if (s->next)
2681 *stb__prevn(s->next) = s->prevn;
2682
2683 // first free chunks
2684 c = (stb__chunk *) stb__chunks(s);
2685 while (c != NULL) {
2686 n = c->next;
2687 stb_alloc_count_free += c->alloc;
2688 free(c);
2689 c = n;
2690 }
2691
2692 // validating
2693 stb__setchunks(s,NULL);
2694 s->prevn = NULL;
2695 s->next = NULL;
2696
2697 // now free children
2698 while ((q = s->child) != NULL) {
2699 stb_free(q);
2700 }
2701
2702 // now free self
2703 free(s);
2704 return;
2705 }
2706 default:
2707 assert(0); /* NOTREACHED */
2708 }
2709 }
2710
stb_malloc_validate(void * p,void * parent)2711 void stb_malloc_validate(void *p, void *parent)
2712 {
2713 if (p == NULL) return;
2714
2715 switch(stb__identify(p)) {
2716 case STB__chunked:
2717 return;
2718 case STB__nochildren: {
2719 stb__nochildren *n = (stb__nochildren *) p - 1;
2720 if (n->prevn)
2721 assert(*n->prevn == p);
2722 if (n->next) {
2723 assert(*stb__prevn(n->next) == &n->next);
2724 stb_malloc_validate(n, parent);
2725 }
2726 return;
2727 }
2728 case STB__alloc: {
2729 stb__alloc *s = (stb__alloc *) p - 1;
2730
2731 if (s->prevn)
2732 assert(*s->prevn == p);
2733
2734 if (s->child) {
2735 assert(*stb__prevn(s->child) == &s->child);
2736 stb_malloc_validate(s->child, p);
2737 }
2738
2739 if (s->next) {
2740 assert(*stb__prevn(s->next) == &s->next);
2741 stb_malloc_validate(s->next, parent);
2742 }
2743 return;
2744 }
2745 default:
2746 assert(0); /* NOTREACHED */
2747 }
2748 }
2749
stb__try_chunk(stb__chunk * c,int size,int align,int pre_align)2750 static void * stb__try_chunk(stb__chunk *c, int size, int align, int pre_align)
2751 {
2752 char *memblock = (char *) (c+1), *q;
2753 stb_inta iq;
2754 int start_offset;
2755
2756 // we going to allocate at the end of the chunk, not the start. confusing,
2757 // but it means we don't need both a 'limit' and a 'cur', just a 'cur'.
2758 // the block ends at: p + c->data_left
2759 // then we move back by size
2760 start_offset = c->data_left - size;
2761
2762 // now we need to check the alignment of that
2763 q = memblock + start_offset;
2764 iq = (stb_inta) q;
2765 assert(sizeof(q) == sizeof(iq));
2766
2767 // suppose align = 2
2768 // then we need to retreat iq far enough that (iq & (2-1)) == 0
2769 // to get (iq & (align-1)) = 0 requires subtracting (iq & (align-1))
2770
2771 start_offset -= iq & (align-1);
2772 assert(((stb_uinta) (memblock+start_offset) & (align-1)) == 0);
2773
2774 // now, if that + pre_align works, go for it!
2775 start_offset -= pre_align;
2776
2777 if (start_offset >= 0) {
2778 c->data_left = start_offset;
2779 return memblock + start_offset;
2780 }
2781
2782 return NULL;
2783 }
2784
stb__sort_chunks(stb__alloc * src)2785 static void stb__sort_chunks(stb__alloc *src)
2786 {
2787 // of the first two chunks, put the chunk with more data left in it first
2788 stb__chunk *c = stb__chunks(src), *d;
2789 if (c == NULL) return;
2790 d = c->next;
2791 if (d == NULL) return;
2792 if (c->data_left > d->data_left) return;
2793
2794 c->next = d->next;
2795 d->next = c;
2796 stb__setchunks(src, d);
2797 }
2798
stb__alloc_chunk(stb__alloc * src,int size,int align,int pre_align)2799 static void * stb__alloc_chunk(stb__alloc *src, int size, int align, int pre_align)
2800 {
2801 void *p;
2802 stb__chunk *c = stb__chunks(src);
2803
2804 if (c && size <= stb_alloc_chunk_size) {
2805
2806 p = stb__try_chunk(c, size, align, pre_align);
2807 if (p) { ++c->alloc; return p; }
2808
2809 // try a second chunk to reduce wastage
2810 if (c->next) {
2811 p = stb__try_chunk(c->next, size, align, pre_align);
2812 if (p) { ++c->alloc; return p; }
2813
2814 // put the bigger chunk first, since the second will get buried
2815 // the upshot of this is that, until it gets allocated from, chunk #2
2816 // is always the largest remaining chunk. (could formalize
2817 // this with a heap!)
2818 stb__sort_chunks(src);
2819 c = stb__chunks(src);
2820 }
2821 }
2822
2823 // allocate a new chunk
2824 {
2825 stb__chunk *n;
2826
2827 int chunk_size = stb_alloc_chunk_size;
2828 // we're going to allocate a new chunk to put this in
2829 if (size > chunk_size)
2830 chunk_size = size;
2831
2832 assert(sizeof(*n) + pre_align <= 16);
2833
2834 // loop trying to allocate a large enough chunk
2835 // the loop is because the alignment may cause problems if it's big...
2836 // and we don't know what our chunk alignment is going to be
2837 while (1) {
2838 n = (stb__chunk *) malloc(16 + chunk_size);
2839 if (n == NULL) return NULL;
2840
2841 n->data_left = chunk_size - sizeof(*n);
2842
2843 p = stb__try_chunk(n, size, align, pre_align);
2844 if (p != NULL) {
2845 n->next = c;
2846 stb__setchunks(src, n);
2847
2848 // if we just used up the whole block immediately,
2849 // move the following chunk up
2850 n->alloc = 1;
2851 if (size == chunk_size)
2852 stb__sort_chunks(src);
2853
2854 return p;
2855 }
2856
2857 free(n);
2858 chunk_size += 16+align;
2859 }
2860 }
2861 }
2862
stb__get_context(void * context)2863 static stb__alloc * stb__get_context(void *context)
2864 {
2865 if (context == NULL) {
2866 return &stb__alloc_global;
2867 } else {
2868 int u = stb__identify(context);
2869 // if context is chunked, grab parent
2870 if (u == STB__chunked) {
2871 stb__chunked *s = (stb__chunked *) context - 1;
2872 return stb__parent(s);
2873 } else {
2874 return (stb__alloc *) context - 1;
2875 }
2876 }
2877 }
2878
stb__insert_alloc(stb__alloc * src,stb__alloc * s)2879 static void stb__insert_alloc(stb__alloc *src, stb__alloc *s)
2880 {
2881 s->prevn = &src->child;
2882 s->next = src->child;
2883 src->child = s+1;
2884 if (s->next)
2885 *stb__prevn(s->next) = &s->next;
2886 }
2887
stb__insert_nochild(stb__alloc * src,stb__nochildren * s)2888 static void stb__insert_nochild(stb__alloc *src, stb__nochildren *s)
2889 {
2890 s->prevn = &src->child;
2891 s->next = src->child;
2892 src->child = s+1;
2893 if (s->next)
2894 *stb__prevn(s->next) = &s->next;
2895 }
2896
malloc_base(void * context,size_t size,stb__alloc_type t,int align)2897 static void * malloc_base(void *context, size_t size, stb__alloc_type t, int align)
2898 {
2899 void *p;
2900
2901 stb__alloc *src = stb__get_context(context);
2902
2903 if (align <= 0) {
2904 // compute worst-case C packed alignment
2905 // e.g. a 24-byte struct is 8-aligned
2906 int align_proposed = 1 << stb_lowbit8((unsigned int) size);
2907
2908 if (align_proposed < 0)
2909 align_proposed = 4;
2910
2911 if (align_proposed == 0) {
2912 if (size == 0)
2913 align_proposed = 1;
2914 else
2915 align_proposed = 256;
2916 }
2917
2918 // a negative alignment means 'don't align any larger
2919 // than this'; so -16 means we align 1,2,4,8, or 16
2920
2921 if (align < 0) {
2922 if (align_proposed > -align)
2923 align_proposed = -align;
2924 }
2925
2926 align = align_proposed;
2927 }
2928
2929 assert(stb_is_pow2(align));
2930
2931 // don't cause misalignment when allocating nochildren
2932 if (t == STB__nochildren && align > 8)
2933 t = STB__alloc;
2934
2935 switch (t) {
2936 case STB__alloc: {
2937 stb__alloc *s = (stb__alloc *) malloc(size + sizeof(*s));
2938 if (s == NULL) return NULL;
2939 p = s+1;
2940 s->child = NULL;
2941 stb__insert_alloc(src, s);
2942
2943 stb__setchunks(s,NULL);
2944 break;
2945 }
2946
2947 case STB__nochildren: {
2948 stb__nochildren *s = (stb__nochildren *) malloc(size + sizeof(*s));
2949 if (s == NULL) return NULL;
2950 p = s+1;
2951 stb__insert_nochild(src, s);
2952 break;
2953 }
2954
2955 case STB__chunk_raw: {
2956 p = stb__alloc_chunk(src, (int) size, align, 0);
2957 if (p == NULL) return NULL;
2958 break;
2959 }
2960
2961 case STB__chunked: {
2962 stb__chunked *s;
2963 if (align < sizeof(stb_uintptr)) align = sizeof(stb_uintptr);
2964 s = (stb__chunked *) stb__alloc_chunk(src, (int) size, align, sizeof(*s));
2965 if (s == NULL) return NULL;
2966 stb__setparent(s, src);
2967 p = s+1;
2968 break;
2969 }
2970
2971 default: p = NULL; assert(0); /* NOTREACHED */
2972 }
2973
2974 ++stb_alloc_count_alloc;
2975 return p;
2976 }
2977
stb_malloc_global(size_t size)2978 void *stb_malloc_global(size_t size)
2979 {
2980 return malloc_base(NULL, size, STB__alloc, stb_alloc_alignment);
2981 }
2982
stb_malloc(void * context,size_t size)2983 void *stb_malloc(void *context, size_t size)
2984 {
2985 return malloc_base(context, size, STB__alloc, stb_alloc_alignment);
2986 }
2987
stb_malloc_nofree(void * context,size_t size)2988 void *stb_malloc_nofree(void *context, size_t size)
2989 {
2990 return malloc_base(context, size, STB__chunked, stb_alloc_alignment);
2991 }
2992
stb_malloc_leaf(void * context,size_t size)2993 void *stb_malloc_leaf(void *context, size_t size)
2994 {
2995 return malloc_base(context, size, STB__nochildren, stb_alloc_alignment);
2996 }
2997
stb_malloc_raw(void * context,size_t size)2998 void *stb_malloc_raw(void *context, size_t size)
2999 {
3000 return malloc_base(context, size, STB__chunk_raw, stb_alloc_alignment);
3001 }
3002
stb_malloc_string(void * context,size_t size)3003 char *stb_malloc_string(void *context, size_t size)
3004 {
3005 return (char *) malloc_base(context, size, STB__chunk_raw, 1);
3006 }
3007
stb_realloc(void * ptr,size_t newsize)3008 void *stb_realloc(void *ptr, size_t newsize)
3009 {
3010 stb__alloc_type t;
3011
3012 if (ptr == NULL) return stb_malloc(NULL, newsize);
3013 if (newsize == 0) { stb_free(ptr); return NULL; }
3014
3015 t = stb__identify(ptr);
3016 assert(t == STB__alloc || t == STB__nochildren);
3017
3018 if (t == STB__alloc) {
3019 stb__alloc *s = (stb__alloc *) ptr - 1;
3020
3021 s = (stb__alloc *) realloc(s, newsize + sizeof(*s));
3022 if (s == NULL) return NULL;
3023
3024 ptr = s+1;
3025
3026 // update pointers
3027 (*s->prevn) = ptr;
3028 if (s->next)
3029 *stb__prevn(s->next) = &s->next;
3030
3031 if (s->child)
3032 *stb__prevn(s->child) = &s->child;
3033
3034 return ptr;
3035 } else {
3036 stb__nochildren *s = (stb__nochildren *) ptr - 1;
3037
3038 s = (stb__nochildren *) realloc(ptr, newsize + sizeof(s));
3039 if (s == NULL) return NULL;
3040
3041 // update pointers
3042 (*s->prevn) = s+1;
3043 if (s->next)
3044 *stb__prevn(s->next) = &s->next;
3045
3046 return s+1;
3047 }
3048 }
3049
stb_realloc_c(void * context,void * ptr,size_t newsize)3050 void *stb_realloc_c(void *context, void *ptr, size_t newsize)
3051 {
3052 if (ptr == NULL) return stb_malloc(context, newsize);
3053 if (newsize == 0) { stb_free(ptr); return NULL; }
3054 // @TODO: verify you haven't changed contexts
3055 return stb_realloc(ptr, newsize);
3056 }
3057
stb_reassign(void * new_context,void * ptr)3058 void stb_reassign(void *new_context, void *ptr)
3059 {
3060 stb__alloc *src = stb__get_context(new_context);
3061
3062 stb__alloc_type t = stb__identify(ptr);
3063 assert(t == STB__alloc || t == STB__nochildren);
3064
3065 if (t == STB__alloc) {
3066 stb__alloc *s = (stb__alloc *) ptr - 1;
3067
3068 // unlink from old
3069 *(s->prevn) = s->next;
3070 if (s->next)
3071 *stb__prevn(s->next) = s->prevn;
3072
3073 stb__insert_alloc(src, s);
3074 } else {
3075 stb__nochildren *s = (stb__nochildren *) ptr - 1;
3076
3077 // unlink from old
3078 *(s->prevn) = s->next;
3079 if (s->next)
3080 *stb__prevn(s->next) = s->prevn;
3081
3082 stb__insert_nochild(src, s);
3083 }
3084 }
3085
3086 #endif
3087
3088
3089 //////////////////////////////////////////////////////////////////////////////
3090 //
3091 // stb_arr
3092 //
3093 // An stb_arr is directly useable as a pointer (use the actual type in your
3094 // definition), but when it resizes, it returns a new pointer and you can't
3095 // use the old one, so you have to be careful to copy-in-out as necessary.
3096 //
3097 // Use a NULL pointer as a 0-length array.
3098 //
3099 // float *my_array = NULL, *temp;
3100 //
3101 // // add elements on the end one at a time
3102 // stb_arr_push(my_array, 0.0f);
3103 // stb_arr_push(my_array, 1.0f);
3104 // stb_arr_push(my_array, 2.0f);
3105 //
3106 // assert(my_array[1] == 2.0f);
3107 //
3108 // // add an uninitialized element at the end, then assign it
3109 // *stb_arr_add(my_array) = 3.0f;
3110 //
3111 // // add three uninitialized elements at the end
3112 // temp = stb_arr_addn(my_array,3);
3113 // temp[0] = 4.0f;
3114 // temp[1] = 5.0f;
3115 // temp[2] = 6.0f;
3116 //
3117 // assert(my_array[5] == 5.0f);
3118 //
3119 // // remove the last one
3120 // stb_arr_pop(my_array);
3121 //
3122 // assert(stb_arr_len(my_array) == 6);
3123
3124
3125 #ifdef STB_MALLOC_WRAPPER
3126 #define STB__PARAMS , char *file, int line
3127 #define STB__ARGS , file, line
3128 #else
3129 #define STB__PARAMS
3130 #define STB__ARGS
3131 #endif
3132
3133 // calling this function allocates an empty stb_arr attached to p
3134 // (whereas NULL isn't attached to anything)
3135 STB_EXTERN void stb_arr_malloc(void **target, void *context);
3136
3137 // call this function with a non-NULL value to have all successive
3138 // stbs that are created be attached to the associated parent. Note
3139 // that once a given stb_arr is non-empty, it stays attached to its
3140 // current parent, even if you call this function again.
3141 // it turns the previous value, so you can restore it
3142 STB_EXTERN void* stb_arr_malloc_parent(void *p);
3143
3144 // simple functions written on top of other functions
3145 #define stb_arr_empty(a) ( stb_arr_len(a) == 0 )
3146 #define stb_arr_add(a) ( stb_arr_addn((a),1) )
3147 #define stb_arr_push(a,v) ( *stb_arr_add(a)=(v) )
3148
3149 typedef struct
3150 {
3151 int len, limit;
3152 int stb_malloc;
3153 unsigned int signature;
3154 } stb__arr;
3155
3156 #define stb_arr_signature 0x51bada7b // ends with 0123 in decimal
3157
3158 // access the header block stored before the data
3159 #define stb_arrhead(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3160 #define stb_arrhead2(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3161
3162 #ifdef STB_DEBUG
3163 #define stb_arr_check(a) assert(!a || stb_arrhead(a)->signature == stb_arr_signature)
3164 #define stb_arr_check2(a) assert(!a || stb_arrhead2(a)->signature == stb_arr_signature)
3165 #else
3166 #define stb_arr_check(a) ((void) 0)
3167 #define stb_arr_check2(a) ((void) 0)
3168 #endif
3169
3170 // ARRAY LENGTH
3171
3172 // get the array length; special case if pointer is NULL
3173 #define stb_arr_len(a) (a ? stb_arrhead(a)->len : 0)
3174 #define stb_arr_len2(a) ((stb__arr *) (a) ? stb_arrhead2(a)->len : 0)
3175 #define stb_arr_lastn(a) (stb_arr_len(a)-1)
3176
3177 // check whether a given index is valid -- tests 0 <= i < stb_arr_len(a)
3178 #define stb_arr_valid(a,i) (a ? (int) (i) < stb_arrhead(a)->len : 0)
3179
3180 // change the array length so is is exactly N entries long, creating
3181 // uninitialized entries as needed
3182 #define stb_arr_setlen(a,n) \
3183 (stb__arr_setlen((void **) &(a), sizeof(a[0]), (n)))
3184
3185 // change the array length so that N is a valid index (that is, so
3186 // it is at least N entries long), creating uninitialized entries as needed
3187 #define stb_arr_makevalid(a,n) \
3188 (stb_arr_len(a) < (n)+1 ? stb_arr_setlen(a,(n)+1),(a) : (a))
3189
3190 // remove the last element of the array, returning it
3191 #define stb_arr_pop(a) ((stb_arr_check(a), (a))[--stb_arrhead(a)->len])
3192
3193 // access the last element in the array
3194 #define stb_arr_last(a) ((stb_arr_check(a), (a))[stb_arr_len(a)-1])
3195
3196 // is iterator at end of list?
3197 #define stb_arr_end(a,i) ((i) >= &(a)[stb_arr_len(a)])
3198
3199 // (internal) change the allocated length of the array
3200 #define stb_arr__grow(a,n) (stb_arr_check(a), stb_arrhead(a)->len += (n))
3201
3202 // add N new uninitialized elements to the end of the array
3203 #define stb_arr__addn(a,n) /*lint --e(826)*/ \
3204 ((stb_arr_len(a)+(n) > stb_arrcurmax(a)) \
3205 ? (stb__arr_addlen((void **) &(a),sizeof(*a),(n)),0) \
3206 : ((stb_arr__grow(a,n), 0)))
3207
3208 // add N new uninitialized elements to the end of the array, and return
3209 // a pointer to the first new one
3210 #define stb_arr_addn(a,n) (stb_arr__addn((a),n),(a)+stb_arr_len(a)-(n))
3211
3212 // add N new uninitialized elements starting at index 'i'
3213 #define stb_arr_insertn(a,i,n) (stb__arr_insertn((void **) &(a), sizeof(*a), i, n))
3214
3215 // insert an element at i
3216 #define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), i, 1), ((a)[i] = v))
3217
3218 // delete N elements from the middle starting at index 'i'
3219 #define stb_arr_deleten(a,i,n) (stb__arr_deleten((void **) &(a), sizeof(*a), i, n))
3220
3221 // delete the i'th element
3222 #define stb_arr_delete(a,i) stb_arr_deleten(a,i,1)
3223
3224 // delete the i'th element, swapping down from the end
3225 #define stb_arr_fastdelete(a,i) \
3226 (stb_swap(&a[i], &a[stb_arrhead(a)->len-1], sizeof(*a)), stb_arr_pop(a))
3227
3228
3229 // ARRAY STORAGE
3230
3231 // get the array maximum storage; special case if NULL
3232 #define stb_arrcurmax(a) (a ? stb_arrhead(a)->limit : 0)
3233 #define stb_arrcurmax2(a) (a ? stb_arrhead2(a)->limit : 0)
3234
3235 // set the maxlength of the array to n in anticipation of further growth
3236 #define stb_arr_setsize(a,n) (stb_arr_check(a), stb__arr_setsize((void **) &(a),sizeof((a)[0]),n))
3237
3238 // make sure maxlength is large enough for at least N new allocations
3239 #define stb_arr_atleast(a,n) (stb_arr_len(a)+(n) > stb_arrcurmax(a) \
3240 ? stb_arr_setsize((a), (n)) : 0)
3241
3242 // make a copy of a given array (copies contents via 'memcpy'!)
3243 #define stb_arr_copy(a) stb__arr_copy(a, sizeof((a)[0]))
3244
3245 // compute the storage needed to store all the elements of the array
3246 #define stb_arr_storage(a) (stb_arr_len(a) * sizeof((a)[0]))
3247
3248 #define stb_arr_for(v,arr) for((v)=(arr); (v) < (arr)+stb_arr_len(arr); ++(v))
3249
3250 // IMPLEMENTATION
3251
3252 STB_EXTERN void stb_arr_free_(void **p);
3253 STB_EXTERN void *stb__arr_copy_(void *p, int elem_size);
3254 STB_EXTERN void stb__arr_setsize_(void **p, int size, int limit STB__PARAMS);
3255 STB_EXTERN void stb__arr_setlen_(void **p, int size, int newlen STB__PARAMS);
3256 STB_EXTERN void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS);
3257 STB_EXTERN void stb__arr_deleten_(void **p, int size, int loc, int n STB__PARAMS);
3258 STB_EXTERN void stb__arr_insertn_(void **p, int size, int loc, int n STB__PARAMS);
3259
3260 #define stb_arr_free(p) stb_arr_free_((void **) &(p))
3261 #define stb__arr_copy stb__arr_copy_
3262
3263 #ifndef STB_MALLOC_WRAPPER
3264 #define stb__arr_setsize stb__arr_setsize_
3265 #define stb__arr_setlen stb__arr_setlen_
3266 #define stb__arr_addlen stb__arr_addlen_
3267 #define stb__arr_deleten stb__arr_deleten_
3268 #define stb__arr_insertn stb__arr_insertn_
3269 #else
3270 #define stb__arr_addlen(p,s,n) stb__arr_addlen_(p,s,n,__FILE__,__LINE__)
3271 #define stb__arr_setlen(p,s,n) stb__arr_setlen_(p,s,n,__FILE__,__LINE__)
3272 #define stb__arr_setsize(p,s,n) stb__arr_setsize_(p,s,n,__FILE__,__LINE__)
3273 #define stb__arr_deleten(p,s,i,n) stb__arr_deleten_(p,s,i,n,__FILE__,__LINE__)
3274 #define stb__arr_insertn(p,s,i,n) stb__arr_insertn_(p,s,i,n,__FILE__,__LINE__)
3275 #endif
3276
3277 #ifdef STB_DEFINE
3278 static void *stb__arr_context;
3279
stb_arr_malloc_parent(void * p)3280 void *stb_arr_malloc_parent(void *p)
3281 {
3282 void *q = stb__arr_context;
3283 stb__arr_context = p;
3284 return q;
3285 }
3286
stb_arr_malloc(void ** target,void * context)3287 void stb_arr_malloc(void **target, void *context)
3288 {
3289 stb__arr *q = (stb__arr *) stb_malloc(context, sizeof(*q));
3290 q->len = q->limit = 0;
3291 q->stb_malloc = 1;
3292 q->signature = stb_arr_signature;
3293 *target = (void *) (q+1);
3294 }
3295
stb__arr_malloc(int size)3296 static void * stb__arr_malloc(int size)
3297 {
3298 if (stb__arr_context)
3299 return stb_malloc(stb__arr_context, size);
3300 return malloc(size);
3301 }
3302
stb__arr_copy_(void * p,int elem_size)3303 void * stb__arr_copy_(void *p, int elem_size)
3304 {
3305 stb__arr *q;
3306 if (p == NULL) return p;
3307 q = (stb__arr *) stb__arr_malloc(sizeof(*q) + elem_size * stb_arrhead2(p)->limit);
3308 stb_arr_check2(p);
3309 memcpy(q, stb_arrhead2(p), sizeof(*q) + elem_size * stb_arrhead2(p)->len);
3310 q->stb_malloc = !!stb__arr_context;
3311 return q+1;
3312 }
3313
stb_arr_free_(void ** pp)3314 void stb_arr_free_(void **pp)
3315 {
3316 void *p = *pp;
3317 stb_arr_check2(p);
3318 if (p) {
3319 stb__arr *q = stb_arrhead2(p);
3320 if (q->stb_malloc)
3321 stb_free(q);
3322 else
3323 free(q);
3324 }
3325 *pp = NULL;
3326 }
3327
stb__arrsize_(void ** pp,int size,int limit,int len STB__PARAMS)3328 static void stb__arrsize_(void **pp, int size, int limit, int len STB__PARAMS)
3329 {
3330 void *p = *pp;
3331 stb__arr *a;
3332 stb_arr_check2(p);
3333 if (p == NULL) {
3334 if (len == 0 && size == 0) return;
3335 a = (stb__arr *) stb__arr_malloc(sizeof(*a) + size*limit);
3336 a->limit = limit;
3337 a->len = len;
3338 a->stb_malloc = !!stb__arr_context;
3339 a->signature = stb_arr_signature;
3340 } else {
3341 a = stb_arrhead2(p);
3342 a->len = len;
3343 if (a->limit < limit) {
3344 void *p;
3345 if (a->limit >= 4 && limit < a->limit * 2)
3346 limit = a->limit * 2;
3347 if (a->stb_malloc)
3348 p = stb_realloc(a, sizeof(*a) + limit*size);
3349 else
3350 #ifdef STB_MALLOC_WRAPPER
3351 p = stb__realloc(a, sizeof(*a) + limit*size, file, line);
3352 #else
3353 p = realloc(a, sizeof(*a) + limit*size);
3354 #endif
3355 if (p) {
3356 a = (stb__arr *) p;
3357 a->limit = limit;
3358 } else {
3359 // throw an error!
3360 }
3361 }
3362 }
3363 a->len = stb_min(a->len, a->limit);
3364 *pp = a+1;
3365 }
3366
stb__arr_setsize_(void ** pp,int size,int limit STB__PARAMS)3367 void stb__arr_setsize_(void **pp, int size, int limit STB__PARAMS)
3368 {
3369 void *p = *pp;
3370 stb_arr_check2(p);
3371 stb__arrsize_(pp, size, limit, stb_arr_len2(p) STB__ARGS);
3372 }
3373
stb__arr_setlen_(void ** pp,int size,int newlen STB__PARAMS)3374 void stb__arr_setlen_(void **pp, int size, int newlen STB__PARAMS)
3375 {
3376 void *p = *pp;
3377 stb_arr_check2(p);
3378 if (stb_arrcurmax2(p) < newlen || p == NULL) {
3379 stb__arrsize_(pp, size, newlen, newlen STB__ARGS);
3380 } else {
3381 stb_arrhead2(p)->len = newlen;
3382 }
3383 }
3384
stb__arr_addlen_(void ** p,int size,int addlen STB__PARAMS)3385 void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS)
3386 {
3387 stb__arr_setlen_(p, size, stb_arr_len2(*p) + addlen STB__ARGS);
3388 }
3389
stb__arr_insertn_(void ** pp,int size,int i,int n STB__PARAMS)3390 void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS)
3391 {
3392 void *p = *pp;
3393 if (n) {
3394 int z;
3395
3396 if (p == NULL) {
3397 stb__arr_addlen_(pp, size, n STB__ARGS);
3398 return;
3399 }
3400
3401 z = stb_arr_len2(p);
3402 stb__arr_addlen_(&p, size, n STB__ARGS);
3403 memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i));
3404 }
3405 *pp = p;
3406 }
3407
stb__arr_deleten_(void ** pp,int size,int i,int n STB__PARAMS)3408 void stb__arr_deleten_(void **pp, int size, int i, int n STB__PARAMS)
3409 {
3410 void *p = *pp;
3411 if (n) {
3412 memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n)));
3413 stb_arrhead2(p)->len -= n;
3414 }
3415 *pp = p;
3416 }
3417
3418 #endif
3419
3420 //////////////////////////////////////////////////////////////////////////////
3421 //
3422 // Hashing
3423 //
3424 // typical use for this is to make a power-of-two hash table.
3425 //
3426 // let N = size of table (2^n)
3427 // let H = stb_hash(str)
3428 // let S = stb_rehash(H) | 1
3429 //
3430 // then hash probe sequence P(i) for i=0..N-1
3431 // P(i) = (H + S*i) & (N-1)
3432 //
3433 // the idea is that H has 32 bits of hash information, but the
3434 // table has only, say, 2^20 entries so only uses 20 of the bits.
3435 // then by rehashing the original H we get 2^12 different probe
3436 // sequences for a given initial probe location. (So it's optimal
3437 // for 64K tables and its optimality decreases past that.)
3438 //
3439 // ok, so I've added something that generates _two separate_
3440 // 32-bit hashes simultaneously which should scale better to
3441 // very large tables.
3442
3443
3444 STB_EXTERN unsigned int stb_hash(char *str);
3445 STB_EXTERN unsigned int stb_hashptr(void *p);
3446 STB_EXTERN unsigned int stb_hashlen(char *str, int len);
3447 STB_EXTERN unsigned int stb_rehash_improved(unsigned int v);
3448 STB_EXTERN unsigned int stb_hash_fast(void *p, int len);
3449 STB_EXTERN unsigned int stb_hash2(char *str, unsigned int *hash2_ptr);
3450 STB_EXTERN unsigned int stb_hash_number(unsigned int hash);
3451
3452 #define stb_rehash(x) ((x) + ((x) >> 6) + ((x) >> 19))
3453
3454 #ifdef STB_DEFINE
stb_hash(char * str)3455 unsigned int stb_hash(char *str)
3456 {
3457 unsigned int hash = 0;
3458 while (*str)
3459 hash = (hash << 7) + (hash >> 25) + *str++;
3460 return hash + (hash >> 16);
3461 }
3462
stb_hashlen(char * str,int len)3463 unsigned int stb_hashlen(char *str, int len)
3464 {
3465 unsigned int hash = 0;
3466 while (len-- > 0 && *str)
3467 hash = (hash << 7) + (hash >> 25) + *str++;
3468 return hash + (hash >> 16);
3469 }
3470
stb_hashptr(void * p)3471 unsigned int stb_hashptr(void *p)
3472 {
3473 unsigned int x = (unsigned int)(size_t) p;
3474
3475 // typically lacking in low bits and high bits
3476 x = stb_rehash(x);
3477 x += x << 16;
3478
3479 // pearson's shuffle
3480 x ^= x << 3;
3481 x += x >> 5;
3482 x ^= x << 2;
3483 x += x >> 15;
3484 x ^= x << 10;
3485 return stb_rehash(x);
3486 }
3487
stb_rehash_improved(unsigned int v)3488 unsigned int stb_rehash_improved(unsigned int v)
3489 {
3490 return stb_hashptr((void *)(size_t) v);
3491 }
3492
stb_hash2(char * str,unsigned int * hash2_ptr)3493 unsigned int stb_hash2(char *str, unsigned int *hash2_ptr)
3494 {
3495 unsigned int hash1 = 0x3141592c;
3496 unsigned int hash2 = 0x77f044ed;
3497 while (*str) {
3498 hash1 = (hash1 << 7) + (hash1 >> 25) + *str;
3499 hash2 = (hash2 << 11) + (hash2 >> 21) + *str;
3500 ++str;
3501 }
3502 *hash2_ptr = hash2 + (hash1 >> 16);
3503 return hash1 + (hash2 >> 16);
3504 }
3505
3506 // Paul Hsieh hash
3507 #define stb__get16(p) ((p)[0] | ((p)[1] << 8))
3508
stb_hash_fast(void * p,int len)3509 unsigned int stb_hash_fast(void *p, int len)
3510 {
3511 unsigned char *q = (unsigned char *) p;
3512 unsigned int hash = len;
3513
3514 if (len <= 0 || q == NULL) return 0;
3515
3516 /* Main loop */
3517 for (;len > 3; len -= 4) {
3518 unsigned int val;
3519 hash += stb__get16(q);
3520 val = (stb__get16(q+2) << 11);
3521 hash = (hash << 16) ^ hash ^ val;
3522 q += 4;
3523 hash += hash >> 11;
3524 }
3525
3526 /* Handle end cases */
3527 switch (len) {
3528 case 3: hash += stb__get16(q);
3529 hash ^= hash << 16;
3530 hash ^= q[2] << 18;
3531 hash += hash >> 11;
3532 break;
3533 case 2: hash += stb__get16(q);
3534 hash ^= hash << 11;
3535 hash += hash >> 17;
3536 break;
3537 case 1: hash += q[0];
3538 hash ^= hash << 10;
3539 hash += hash >> 1;
3540 break;
3541 case 0: break;
3542 }
3543
3544 /* Force "avalanching" of final 127 bits */
3545 hash ^= hash << 3;
3546 hash += hash >> 5;
3547 hash ^= hash << 4;
3548 hash += hash >> 17;
3549 hash ^= hash << 25;
3550 hash += hash >> 6;
3551
3552 return hash;
3553 }
3554
stb_hash_number(unsigned int hash)3555 unsigned int stb_hash_number(unsigned int hash)
3556 {
3557 hash ^= hash << 3;
3558 hash += hash >> 5;
3559 hash ^= hash << 4;
3560 hash += hash >> 17;
3561 hash ^= hash << 25;
3562 hash += hash >> 6;
3563 return hash;
3564 }
3565
3566 #endif
3567
3568 //////////////////////////////////////////////////////////////////////////////
3569 //
3570 // Perfect hashing for ints/pointers
3571 //
3572 // This is mainly useful for making faster pointer-indexed tables
3573 // that don't change frequently. E.g. for stb_ischar().
3574 //
3575
3576 typedef struct
3577 {
3578 stb_uint32 addend;
3579 stb_uint multiplicand;
3580 stb_uint b_mask;
3581 stb_uint8 small_bmap[16];
3582 stb_uint16 *large_bmap;
3583
3584 stb_uint table_mask;
3585 stb_uint32 *table;
3586 } stb_perfect;
3587
3588 STB_EXTERN int stb_perfect_create(stb_perfect *,unsigned int*,int n);
3589 STB_EXTERN void stb_perfect_destroy(stb_perfect *);
3590 STB_EXTERN int stb_perfect_hash(stb_perfect *, unsigned int x);
3591 extern int stb_perfect_hash_max_failures;
3592
3593 #ifdef STB_DEFINE
3594
3595 int stb_perfect_hash_max_failures;
3596
stb_perfect_hash(stb_perfect * p,unsigned int x)3597 int stb_perfect_hash(stb_perfect *p, unsigned int x)
3598 {
3599 stb_uint m = x * p->multiplicand;
3600 stb_uint y = x >> 16;
3601 stb_uint bv = (m >> 24) + y;
3602 stb_uint av = (m + y) >> 12;
3603 if (p->table == NULL) return -1; // uninitialized table fails
3604 bv &= p->b_mask;
3605 av &= p->table_mask;
3606 if (p->large_bmap)
3607 av ^= p->large_bmap[bv];
3608 else
3609 av ^= p->small_bmap[bv];
3610 return p->table[av] == x ? av : -1;
3611 }
3612
stb__perfect_prehash(stb_perfect * p,stb_uint x,stb_uint16 * a,stb_uint16 * b)3613 static void stb__perfect_prehash(stb_perfect *p, stb_uint x, stb_uint16 *a, stb_uint16 *b)
3614 {
3615 stb_uint m = x * p->multiplicand;
3616 stb_uint y = x >> 16;
3617 stb_uint bv = (m >> 24) + y;
3618 stb_uint av = (m + y) >> 12;
3619 bv &= p->b_mask;
3620 av &= p->table_mask;
3621 *b = bv;
3622 *a = av;
3623 }
3624
stb__perfect_rand(void)3625 static unsigned long stb__perfect_rand(void)
3626 {
3627 static unsigned long stb__rand;
3628 stb__rand = stb__rand * 2147001325 + 715136305;
3629 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16));
3630 }
3631
3632 typedef struct {
3633 unsigned short count;
3634 unsigned short b;
3635 unsigned short map;
3636 unsigned short *entries;
3637 } stb__slot;
3638
stb__slot_compare(const void * p,const void * q)3639 static int stb__slot_compare(const void *p, const void *q)
3640 {
3641 stb__slot *a = (stb__slot *) p;
3642 stb__slot *b = (stb__slot *) q;
3643 return a->count > b->count ? -1 : a->count < b->count; // sort large to small
3644 }
3645
stb_perfect_create(stb_perfect * p,unsigned int * v,int n)3646 int stb_perfect_create(stb_perfect *p, unsigned int *v, int n)
3647 {
3648 unsigned int buffer1[64], buffer2[64], buffer3[64], buffer4[64], buffer5[32];
3649 unsigned short *as = (unsigned short *) stb_temp(buffer1, sizeof(*v)*n);
3650 unsigned short *bs = (unsigned short *) stb_temp(buffer2, sizeof(*v)*n);
3651 unsigned short *entries = (unsigned short *) stb_temp(buffer4, sizeof(*entries) * n);
3652 int size = 1 << stb_log2_ceil(n), bsize=8;
3653 int failure = 0,i,j,k;
3654
3655 assert(n <= 32768);
3656 p->large_bmap = NULL;
3657
3658 for(;;) {
3659 stb__slot *bcount = (stb__slot *) stb_temp(buffer3, sizeof(*bcount) * bsize);
3660 unsigned short *bloc = (unsigned short *) stb_temp(buffer5, sizeof(*bloc) * bsize);
3661 unsigned short *e;
3662 int bad=0;
3663
3664 p->addend = stb__perfect_rand();
3665 p->multiplicand = stb__perfect_rand() | 1;
3666 p->table_mask = size-1;
3667 p->b_mask = bsize-1;
3668 p->table = (stb_uint32 *) malloc(size * sizeof(*p->table));
3669
3670 for (i=0; i < bsize; ++i) {
3671 bcount[i].b = i;
3672 bcount[i].count = 0;
3673 bcount[i].map = 0;
3674 }
3675 for (i=0; i < n; ++i) {
3676 stb__perfect_prehash(p, v[i], as+i, bs+i);
3677 ++bcount[bs[i]].count;
3678 }
3679 qsort(bcount, bsize, sizeof(*bcount), stb__slot_compare);
3680 e = entries; // now setup up their entries index
3681 for (i=0; i < bsize; ++i) {
3682 bcount[i].entries = e;
3683 e += bcount[i].count;
3684 bcount[i].count = 0;
3685 bloc[bcount[i].b] = i;
3686 }
3687 // now fill them out
3688 for (i=0; i < n; ++i) {
3689 int b = bs[i];
3690 int w = bloc[b];
3691 bcount[w].entries[bcount[w].count++] = i;
3692 }
3693 stb_tempfree(buffer5,bloc);
3694 // verify
3695 for (i=0; i < bsize; ++i)
3696 for (j=0; j < bcount[i].count; ++j)
3697 assert(bs[bcount[i].entries[j]] == bcount[i].b);
3698 memset(p->table, 0, size*sizeof(*p->table));
3699
3700 // check if any b has duplicate a
3701 for (i=0; i < bsize; ++i) {
3702 if (bcount[i].count > 1) {
3703 for (j=0; j < bcount[i].count; ++j) {
3704 if (p->table[as[bcount[i].entries[j]]])
3705 bad = 1;
3706 p->table[as[bcount[i].entries[j]]] = 1;
3707 }
3708 for (j=0; j < bcount[i].count; ++j) {
3709 p->table[as[bcount[i].entries[j]]] = 0;
3710 }
3711 if (bad) break;
3712 }
3713 }
3714
3715 if (!bad) {
3716 // go through the bs and populate the table, first fit
3717 for (i=0; i < bsize; ++i) {
3718 if (bcount[i].count) {
3719 // go through the candidate table[b] values
3720 for (j=0; j < size; ++j) {
3721 // go through the a values and see if they fit
3722 for (k=0; k < bcount[i].count; ++k) {
3723 int a = as[bcount[i].entries[k]];
3724 if (p->table[(a^j)&p->table_mask]) {
3725 break; // fails
3726 }
3727 }
3728 // if succeeded, accept
3729 if (k == bcount[i].count) {
3730 bcount[i].map = j;
3731 for (k=0; k < bcount[i].count; ++k) {
3732 int a = as[bcount[i].entries[k]];
3733 p->table[(a^j)&p->table_mask] = 1;
3734 }
3735 break;
3736 }
3737 }
3738 if (j == size)
3739 break; // no match for i'th entry, so break out in failure
3740 }
3741 }
3742 if (i == bsize) {
3743 // success... fill out map
3744 if (bsize <= 16 && size <= 256) {
3745 p->large_bmap = NULL;
3746 for (i=0; i < bsize; ++i)
3747 p->small_bmap[bcount[i].b] = (stb_uint8) bcount[i].map;
3748 } else {
3749 p->large_bmap = (unsigned short *) malloc(sizeof(*p->large_bmap) * bsize);
3750 for (i=0; i < bsize; ++i)
3751 p->large_bmap[bcount[i].b] = bcount[i].map;
3752 }
3753
3754 // initialize table to v[0], so empty slots will fail
3755 for (i=0; i < size; ++i)
3756 p->table[i] = v[0];
3757
3758 for (i=0; i < n; ++i)
3759 if (p->large_bmap)
3760 p->table[as[i] ^ p->large_bmap[bs[i]]] = v[i];
3761 else
3762 p->table[as[i] ^ p->small_bmap[bs[i]]] = v[i];
3763
3764 // and now validate that none of them collided
3765 for (i=0; i < n; ++i)
3766 assert(stb_perfect_hash(p, v[i]) >= 0);
3767
3768 stb_tempfree(buffer3, bcount);
3769 break;
3770 }
3771 }
3772 free(p->table);
3773 p->table = NULL;
3774 stb_tempfree(buffer3, bcount);
3775
3776 ++failure;
3777 if (failure >= 4 && bsize < size) bsize *= 2;
3778 if (failure >= 8 && (failure & 3) == 0 && size < 4*n) {
3779 size *= 2;
3780 bsize *= 2;
3781 }
3782 if (failure == 6) {
3783 // make sure the input data is unique, so we don't infinite loop
3784 unsigned int *data = (unsigned int *) stb_temp(buffer3, n * sizeof(*data));
3785 memcpy(data, v, sizeof(*data) * n);
3786 qsort(data, n, sizeof(*data), stb_intcmp(0));
3787 for (i=1; i < n; ++i) {
3788 if (data[i] == data[i-1])
3789 size = 0; // size is return value, so 0 it
3790 }
3791 stb_tempfree(buffer3, data);
3792 if (!size) break;
3793 }
3794 }
3795
3796 if (failure > stb_perfect_hash_max_failures)
3797 stb_perfect_hash_max_failures = failure;
3798
3799 stb_tempfree(buffer1, as);
3800 stb_tempfree(buffer2, bs);
3801 stb_tempfree(buffer4, entries);
3802
3803 return size;
3804 }
3805
stb_perfect_destroy(stb_perfect * p)3806 void stb_perfect_destroy(stb_perfect *p)
3807 {
3808 if (p->large_bmap) free(p->large_bmap);
3809 if (p->table ) free(p->table);
3810 p->large_bmap = NULL;
3811 p->table = NULL;
3812 p->b_mask = 0;
3813 p->table_mask = 0;
3814 }
3815 #endif
3816
3817 //////////////////////////////////////////////////////////////////////////////
3818 //
3819 // Perfect hash clients
3820
3821 STB_EXTERN int stb_ischar(char s, char *set);
3822
3823 #ifdef STB_DEFINE
3824
stb_ischar(char c,char * set)3825 int stb_ischar(char c, char *set)
3826 {
3827 static unsigned char bit[8] = { 1,2,4,8,16,32,64,128 };
3828 static stb_perfect p;
3829 static unsigned char (*tables)[256];
3830 static char ** sets = NULL;
3831
3832 int z = stb_perfect_hash(&p, (int)(size_t) set);
3833 if (z < 0) {
3834 int i,k,n,j,f;
3835 // special code that means free all existing data
3836 if (set == NULL) {
3837 stb_arr_free(sets);
3838 free(tables);
3839 tables = NULL;
3840 stb_perfect_destroy(&p);
3841 return 0;
3842 }
3843 stb_arr_push(sets, set);
3844 stb_perfect_destroy(&p);
3845 n = stb_perfect_create(&p, (unsigned int *) (char **) sets, stb_arr_len(sets));
3846 assert(n != 0);
3847 k = (n+7) >> 3;
3848 tables = (unsigned char (*)[256]) realloc(tables, sizeof(*tables) * k);
3849 memset(tables, 0, sizeof(*tables) * k);
3850 for (i=0; i < stb_arr_len(sets); ++i) {
3851 k = stb_perfect_hash(&p, (int)(size_t) sets[i]);
3852 assert(k >= 0);
3853 n = k >> 3;
3854 f = bit[k&7];
3855 for (j=0; !j || sets[i][j]; ++j) {
3856 tables[n][(unsigned char) sets[i][j]] |= f;
3857 }
3858 }
3859 z = stb_perfect_hash(&p, (int)(size_t) set);
3860 }
3861 return tables[z >> 3][(unsigned char) c] & bit[z & 7];
3862 }
3863
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 goes down this path?!?
7155 if (has_slash)
7156 swprintf(full_path, L"%s*", stb__from_utf8(path));
7157 else
7158 swprintf(full_path, L"%s/*", stb__from_utf8(path));
7159 #else
7160 if (has_slash)
7161 swprintf((wchar_t *) full_path, (size_t) 1024, L"%s*", (wchar_t *) stb__from_utf8(path));
7162 else
7163 swprintf((wchar_t *) full_path, (size_t) 1024, L"%s/*", (wchar_t *) stb__from_utf8(path));
7164 #endif
7165
7166 // it's possible this directory is already present: that means it was in the
7167 // cache, but its parent wasn't... in that case, we're done with it
7168 if (stb__showfile) printf("C[%d]", stb_arr_len(active->dirs));
7169 for (n=0; n < stb_arr_len(active->dirs); ++n)
7170 if (0 == stb_stricmp(active->dirs[n].path, path)) {
7171 if (stb__showfile) printf("D");
7172 return;
7173 }
7174 if (stb__showfile) printf("E");
7175
7176 // otherwise, we need to add it
7177 stb__dirtree_add_dir(path, last_time, active);
7178 n = stb_arr_lastn(active->dirs);
7179
7180 if (stb__showfile) printf("[");
7181 if( (hFile = (long) _wfindfirsti64( (wchar_t *) full_path, &c_file )) != -1L ) {
7182 do {
7183 if (stb__showfile) printf(")");
7184 if (c_file.attrib & _A_SUBDIR) {
7185 // ignore subdirectories starting with '.', e.g. "." and ".."
7186 if (c_file.name[0] != '.') {
7187 char *new_path = (char *) full_path;
7188 char *temp = stb__to_utf8((stb__wchar *) c_file.name);
7189
7190 if (has_slash)
7191 stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s%s", path, temp);
7192 else
7193 stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s/%s", path, temp);
7194
7195 if (stb__dircount_mask) {
7196 ++stb__dircount;
7197 if (!(stb__dircount & stb__dircount_mask)) {
7198 char dummy_path[128], *pad;
7199 stb_strncpy(dummy_path, new_path, sizeof(dummy_path)-1);
7200 if (strlen(dummy_path) > 96) {
7201 stb_p_strcpy_s(dummy_path+96/2-1,128, "...");
7202 stb_p_strcpy_s(dummy_path+96/2+2,128, new_path + strlen(new_path)-96/2+2);
7203 }
7204 pad = dummy_path + strlen(dummy_path);
7205 while (pad < dummy_path+98)
7206 *pad++ = ' ';
7207 *pad = 0;
7208 printf("%s\r", dummy_path);
7209 #if 0
7210 if (hlog == 0) {
7211 hlog = stb_p_fopen("c:/x/temp.log", "w");
7212 fprintf(hlog, "%s\n", dummy_path);
7213 }
7214 #endif
7215 }
7216 }
7217
7218 stb__dirtree_scandir(new_path, c_file.time_write, active);
7219 }
7220 } else {
7221 char *temp = stb__to_utf8((stb__wchar *) c_file.name);
7222 stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active);
7223 }
7224 if (stb__showfile) printf("(");
7225 } while( _wfindnexti64( hFile, &c_file ) == 0 );
7226 if (stb__showfile) printf("]");
7227 _findclose( hFile );
7228 }
7229 if (stb__showfile) printf(">\n");
7230 }
7231
7232 // scan the database and see if it's all valid
7233 static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active)
7234 {
7235 int changes_detected = STB_FALSE;
7236 int i;
7237 int *remap;
7238 int *rescan=NULL;
7239 remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(db->dirs));
7240 memset(remap, 0, sizeof(remap[0]) * stb_arr_len(db->dirs));
7241 rescan = NULL;
7242
7243 for (i=0; i < stb_arr_len(db->dirs); ++i) {
7244 struct _stat info;
7245 if (stb__dircount_mask) {
7246 ++stb__dircount;
7247 if (!(stb__dircount & stb__dircount_mask)) {
7248 printf(".");
7249 }
7250 }
7251 if (0 == _stat(db->dirs[i].path, &info)) {
7252 if (info.st_mode & _S_IFDIR) {
7253 // it's still a directory, as expected
7254 int n = abs((int) (info.st_mtime - db->dirs[i].last_modified));
7255 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
7256 // it's changed! force a rescan
7257 // we don't want to scan it until we've stat()d its
7258 // subdirs, though, so we queue it
7259 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);
7260 stb_arr_push(rescan, i);
7261 // update the last_mod time
7262 db->dirs[i].last_modified = info.st_mtime;
7263 // ignore existing files in this dir
7264 remap[i] = -1;
7265 changes_detected = STB_TRUE;
7266 } else {
7267 // it hasn't changed, just copy it through unchanged
7268 stb__dirtree_add_dir(db->dirs[i].path, db->dirs[i].last_modified, active);
7269 remap[i] = stb_arr_lastn(active->dirs);
7270 }
7271 } else {
7272 // this path used to refer to a directory, but now it's a file!
7273 // assume that the parent directory is going to be forced to rescan anyway
7274 goto delete_entry;
7275 }
7276 } else {
7277 delete_entry:
7278 // directory no longer exists, so don't copy it
7279 // we don't free it because it's in the string pool now
7280 db->dirs[i].path = NULL;
7281 remap[i] = -1;
7282 changes_detected = STB_TRUE;
7283 }
7284 }
7285
7286 // at this point, we have:
7287 //
7288 // <rescan> holds a list of directory indices that need to be scanned due to being out of date
7289 // <remap> holds the directory index in <active> for each dir in <db>, if it exists; -1 if not
7290 // directories in <rescan> are not in <active> yet
7291
7292 // so we can go ahead and remap all the known files right now
7293 for (i=0; i < stb_arr_len(db->files); ++i) {
7294 int dir = db->files[i].dir;
7295 if (remap[dir] >= 0) {
7296 stb__dirtree_add_file(db->files[i].name, remap[dir], db->files[i].size, db->files[i].last_modified, active);
7297 }
7298 }
7299
7300 // at this point we're done with db->files, and done with remap
7301 free(remap);
7302
7303 // now scan those directories using the standard scan
7304 for (i=0; i < stb_arr_len(rescan); ++i) {
7305 int z = rescan[i];
7306 stb__dirtree_scandir(db->dirs[z].path, db->dirs[z].last_modified, active);
7307 }
7308 stb_arr_free(rescan);
7309
7310 return changes_detected;
7311 }
7312
7313 static void stb__dirtree_free_raw(stb_dirtree *d)
7314 {
7315 stb_free(d->string_pool);
7316 stb_arr_free(d->dirs);
7317 stb_arr_free(d->files);
7318 }
7319
7320 stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file)
7321 {
7322 stb_dirtree *output = (stb_dirtree *) malloc(sizeof(*output));
7323 stb_dirtree db,active;
7324 int prev_dir_count, cache_mismatch;
7325
7326 char *stripped_dir; // store the directory name without a trailing '/' or '\\'
7327
7328 // load the database of last-known state on disk
7329 db.string_pool = NULL;
7330 db.files = NULL;
7331 db.dirs = NULL;
7332
7333 stripped_dir = stb_strip_final_slash(stb_p_strdup(dir));
7334
7335 if (cache_file != NULL)
7336 stb__dirtree_load_db(cache_file, &db, stripped_dir);
7337 else if (stb__showfile)
7338 printf("No cache file\n");
7339
7340 active.files = NULL;
7341 active.dirs = NULL;
7342 active.string_pool = stb_malloc(0,1); // @TODO: share string pools between both?
7343
7344 // check all the directories in the database; make note if
7345 // anything we scanned had changed, and rescan those things
7346 cache_mismatch = stb__dirtree_update_db(&db, &active);
7347
7348 // check the root tree
7349 prev_dir_count = stb_arr_len(active.dirs); // record how many directories we've seen
7350
7351 stb__dirtree_scandir(stripped_dir, 0, &active); // no last_modified time available for root
7352
7353 if (stb__dircount_mask)
7354 printf(" \r");
7355
7356 // done with the DB; write it back out if any changes, i.e. either
7357 // 1. any inconsistency found between cached information and actual disk
7358 // or 2. if scanning the root found any new directories--which we detect because
7359 // more than one directory got added to the active db during that scan
7360 if (cache_mismatch || stb_arr_len(active.dirs) > prev_dir_count+1)
7361 stb__dirtree_save_db(cache_file, &active, stripped_dir);
7362
7363 free(stripped_dir);
7364
7365 stb__dirtree_free_raw(&db);
7366
7367 *output = active;
7368 return output;
7369 }
7370
7371 stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir)
7372 {
7373 int i;
7374 stb_uint8 sha[20];
7375 char dir_lower[1024];
7376 char cache_file[1024],*s;
7377 if (cache_dir == NULL)
7378 return stb_dirtree_get_with_file(dir, NULL);
7379 stb_p_strcpy_s(dir_lower, sizeof(dir_lower), dir);
7380 stb_tolower(dir_lower);
7381 stb_sha1(sha, (unsigned char *) dir_lower, (unsigned int) strlen(dir_lower));
7382 stb_p_strcpy_s(cache_file, sizeof(cache_file), cache_dir);
7383 s = cache_file + strlen(cache_file);
7384 if (s[-1] != '/' && s[-1] != '\\') *s++ = '/';
7385 stb_p_strcpy_s(s, sizeof(cache_file), "dirtree_");
7386 s += strlen(s);
7387 for (i=0; i < 8; ++i) {
7388 char *hex = (char*)"0123456789abcdef";
7389 stb_uint z = sha[i];
7390 *s++ = hex[z >> 4];
7391 *s++ = hex[z & 15];
7392 }
7393 stb_p_strcpy_s(s, sizeof(cache_file), ".bin");
7394 return stb_dirtree_get_with_file(dir, cache_file);
7395 }
7396
7397 stb_dirtree *stb_dirtree_get(char *dir)
7398 {
7399 char cache_dir[256];
7400 stb_p_strcpy_s(cache_dir, sizeof(cache_dir), "c:/bindata");
7401 #ifdef STB_HAS_REGISTRY
7402 {
7403 void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
7404 if (reg) {
7405 stb_reg_read(reg, "dirtree", cache_dir, sizeof(cache_dir));
7406 stb_reg_close(reg);
7407 }
7408 }
7409 #endif
7410 return stb_dirtree_get_dir(dir, cache_dir);
7411 }
7412
7413 void stb_dirtree_free(stb_dirtree *d)
7414 {
7415 stb__dirtree_free_raw(d);
7416 free(d);
7417 }
7418
7419 void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last)
7420 {
7421 stb__dirtree_add_dir(path, last, active);
7422 }
7423
7424 void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last)
7425 {
7426 stb__dirtree_add_file(name, dir, size, last, active);
7427 }
7428
7429 void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir)
7430 {
7431 char *s = stb_strip_final_slash(stb_p_strdup(dir));
7432 target->dirs = 0;
7433 target->files = 0;
7434 target->string_pool = 0;
7435 stb__dirtree_load_db(filename, target, s);
7436 free(s);
7437 }
7438
7439 void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir)
7440 {
7441 stb__dirtree_save_db(filename, target, 0); // don't strip out any directories
7442 }
7443
7444 #endif // STB_DEFINE
7445
7446 #endif // _WIN32
7447 #endif // STB_NO_STB_STRINGS
7448
7449 //////////////////////////////////////////////////////////////////////////////
7450 //
7451 // STB_MALLOC_WRAPPER
7452 //
7453 // you can use the wrapper functions with your own malloc wrapper,
7454 // or define STB_MALLOC_WRAPPER project-wide to have
7455 // malloc/free/realloc/strdup all get vectored to it
7456
7457 // this has too many very specific error messages you could google for and find in stb.h,
7458 // so don't use it if they don't want any stb.h-identifiable strings
7459 #if defined(STB_DEFINE) && !defined(STB_NO_STB_STRINGS)
7460
7461 typedef struct
7462 {
7463 void *p;
7464 char *file;
7465 int line;
7466 size_t size;
7467 } stb_malloc_record;
7468
7469 #ifndef STB_MALLOC_HISTORY_COUNT
7470 #define STB_MALLOC_HISTORY_COUNT 50 // 800 bytes
7471 #endif
7472
7473 stb_malloc_record *stb__allocations;
7474 static int stb__alloc_size, stb__alloc_limit, stb__alloc_mask;
7475 int stb__alloc_count;
7476
7477 stb_malloc_record stb__alloc_history[STB_MALLOC_HISTORY_COUNT];
7478 int stb__history_pos;
7479
7480 static int stb__hashfind(void *p)
7481 {
7482 stb_uint32 h = stb_hashptr(p);
7483 int s,n = h & stb__alloc_mask;
7484 if (stb__allocations[n].p == p)
7485 return n;
7486 s = stb_rehash(h)|1;
7487 for(;;) {
7488 if (stb__allocations[n].p == NULL)
7489 return -1;
7490 n = (n+s) & stb__alloc_mask;
7491 if (stb__allocations[n].p == p)
7492 return n;
7493 }
7494 }
7495
7496 size_t stb_wrapper_allocsize(void *p)
7497 {
7498 int n = stb__hashfind(p);
7499 if (n < 0) return 0;
7500 return stb__allocations[n].size;
7501 }
7502
7503 static int stb__historyfind(void *p)
7504 {
7505 int n = stb__history_pos;
7506 int i;
7507 for (i=0; i < STB_MALLOC_HISTORY_COUNT; ++i) {
7508 if (--n < 0) n = STB_MALLOC_HISTORY_COUNT-1;
7509 if (stb__alloc_history[n].p == p)
7510 return n;
7511 }
7512 return -1;
7513 }
7514
7515 static void stb__add_alloc(void *p, size_t sz, char *file, int line);
7516 static void stb__grow_alloc(void)
7517 {
7518 int i,old_num = stb__alloc_size;
7519 stb_malloc_record *old = stb__allocations;
7520 if (stb__alloc_size == 0)
7521 stb__alloc_size = 64;
7522 else
7523 stb__alloc_size *= 2;
7524
7525 stb__allocations = (stb_malloc_record *) stb__realloc_raw(NULL, stb__alloc_size * sizeof(stb__allocations[0]));
7526 if (stb__allocations == NULL)
7527 stb_fatal("Internal error: couldn't grow malloc wrapper table");
7528 memset(stb__allocations, 0, stb__alloc_size * sizeof(stb__allocations[0]));
7529 stb__alloc_limit = (stb__alloc_size*3)>>2;
7530 stb__alloc_mask = stb__alloc_size-1;
7531
7532 stb__alloc_count = 0;
7533
7534 for (i=0; i < old_num; ++i)
7535 if (old[i].p > STB_DEL) {
7536 stb__add_alloc(old[i].p, old[i].size, old[i].file, old[i].line);
7537 assert(stb__hashfind(old[i].p) >= 0);
7538 }
7539 for (i=0; i < old_num; ++i)
7540 if (old[i].p > STB_DEL)
7541 assert(stb__hashfind(old[i].p) >= 0);
7542 stb__realloc_raw(old, 0);
7543 }
7544
7545 static void stb__add_alloc(void *p, size_t sz, char *file, int line)
7546 {
7547 stb_uint32 h;
7548 int n;
7549 if (stb__alloc_count >= stb__alloc_limit)
7550 stb__grow_alloc();
7551 h = stb_hashptr(p);
7552 n = h & stb__alloc_mask;
7553 if (stb__allocations[n].p > STB_DEL) {
7554 int s = stb_rehash(h)|1;
7555 do {
7556 n = (n+s) & stb__alloc_mask;
7557 } while (stb__allocations[n].p > STB_DEL);
7558 }
7559 assert(stb__allocations[n].p == NULL || stb__allocations[n].p == STB_DEL);
7560 stb__allocations[n].p = p;
7561 stb__allocations[n].size = sz;
7562 stb__allocations[n].line = line;
7563 stb__allocations[n].file = file;
7564 ++stb__alloc_count;
7565 }
7566
7567 static void stb__remove_alloc(int n, char *file, int line)
7568 {
7569 stb__alloc_history[stb__history_pos] = stb__allocations[n];
7570 stb__alloc_history[stb__history_pos].file = file;
7571 stb__alloc_history[stb__history_pos].line = line;
7572 if (++stb__history_pos == STB_MALLOC_HISTORY_COUNT)
7573 stb__history_pos = 0;
7574 stb__allocations[n].p = STB_DEL;
7575 --stb__alloc_count;
7576 }
7577
7578 void stb_wrapper_malloc(void *p, size_t sz, char *file, int line)
7579 {
7580 if (!p) return;
7581 stb__add_alloc(p,sz,file,line);
7582 }
7583
7584 void stb_wrapper_free(void *p, char *file, int line)
7585 {
7586 int n;
7587
7588 if (p == NULL) return;
7589
7590 n = stb__hashfind(p);
7591
7592 if (n >= 0)
7593 stb__remove_alloc(n, file, line);
7594 else {
7595 // tried to free something we hadn't allocated!
7596 n = stb__historyfind(p);
7597 assert(0); /* NOTREACHED */
7598 if (n >= 0)
7599 stb_fatal("Attempted to free %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7600 stb__alloc_history[n].size, p,
7601 file, line,
7602 stb__alloc_history[n].file, stb__alloc_history[n].line);
7603 else
7604 stb_fatal("Attempted to free unknown block %p at %s:%d", p, file,line);
7605 }
7606 }
7607
7608 void stb_wrapper_check(void *p)
7609 {
7610 int n;
7611
7612 if (p == NULL) return;
7613
7614 n = stb__hashfind(p);
7615
7616 if (n >= 0) return;
7617
7618 for (n=0; n < stb__alloc_size; ++n)
7619 if (stb__allocations[n].p == p)
7620 stb_fatal("Internal error: pointer %p was allocated, but hash search failed", p);
7621
7622 // tried to free something that wasn't allocated!
7623 n = stb__historyfind(p);
7624 if (n >= 0)
7625 stb_fatal("Checked %d-byte block %p previously freed/realloced at %s:%d",
7626 stb__alloc_history[n].size, p,
7627 stb__alloc_history[n].file, stb__alloc_history[n].line);
7628 stb_fatal("Checked unknown block %p");
7629 }
7630
7631 void stb_wrapper_realloc(void *p, void *q, size_t sz, char *file, int line)
7632 {
7633 int n;
7634 if (p == NULL) { stb_wrapper_malloc(q, sz, file, line); return; }
7635 if (q == NULL) return; // nothing happened
7636
7637 n = stb__hashfind(p);
7638 if (n == -1) {
7639 // tried to free something we hadn't allocated!
7640 // this is weird, though, because we got past the realloc!
7641 n = stb__historyfind(p);
7642 assert(0); /* NOTREACHED */
7643 if (n >= 0)
7644 stb_fatal("Attempted to realloc %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7645 stb__alloc_history[n].size, p,
7646 file, line,
7647 stb__alloc_history[n].file, stb__alloc_history[n].line);
7648 else
7649 stb_fatal("Attempted to realloc unknown block %p at %s:%d", p, file,line);
7650 } else {
7651 if (q == p) {
7652 stb__allocations[n].size = sz;
7653 stb__allocations[n].file = file;
7654 stb__allocations[n].line = line;
7655 } else {
7656 stb__remove_alloc(n, file, line);
7657 stb__add_alloc(q,sz,file,line);
7658 }
7659 }
7660 }
7661
7662 void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line))
7663 {
7664 int i;
7665 for (i=0; i < stb__alloc_size; ++i)
7666 if (stb__allocations[i].p > STB_DEL)
7667 func(stb__allocations[i].p , stb__allocations[i].size,
7668 stb__allocations[i].file, stb__allocations[i].line);
7669 }
7670
7671 void stb_wrapper_dump(char *filename)
7672 {
7673 int i;
7674 FILE *f = stb_p_fopen(filename, "w");
7675 if (!f) return;
7676 for (i=0; i < stb__alloc_size; ++i)
7677 if (stb__allocations[i].p > STB_DEL)
7678 fprintf(f, "%p %7d - %4d %s\n",
7679 stb__allocations[i].p , (int) stb__allocations[i].size,
7680 stb__allocations[i].line, stb__allocations[i].file);
7681 }
7682 #endif // STB_DEFINE
7683
7684
7685 //////////////////////////////////////////////////////////////////////////////
7686 //
7687 // stb_pointer_set
7688 //
7689 //
7690 // For data structures that support querying by key, data structure
7691 // classes always hand-wave away the issue of what to do if two entries
7692 // have the same key: basically, store a linked list of all the nodes
7693 // which have the same key (a LISP-style list).
7694 //
7695 // The thing is, it's not that trivial. If you have an O(log n)
7696 // lookup data structure, but then n/4 items have the same value,
7697 // you don't want to spend O(n) time scanning that list when
7698 // deleting an item if you already have a pointer to the item.
7699 // (You have to spend O(n) time enumerating all the items with
7700 // a given key, sure, and you can't accelerate deleting a particular
7701 // item if you only have the key, not a pointer to the item.)
7702 //
7703 // I'm going to call this data structure, whatever it turns out to
7704 // be, a "pointer set", because we don't store any associated data for
7705 // items in this data structure, we just answer the question of
7706 // whether an item is in it or not (it's effectively one bit per pointer).
7707 // Technically they don't have to be pointers; you could cast ints
7708 // to (void *) if you want, but you can't store 0 or 1 because of the
7709 // hash table.
7710 //
7711 // Since the fastest data structure we might want to add support for
7712 // identical-keys to is a hash table with O(1)-ish lookup time,
7713 // that means that the conceptual "linked list of all items with
7714 // the same indexed value" that we build needs to have the same
7715 // performance; that way when we index a table we think is arbitrary
7716 // ints, but in fact half of them are 0, we don't get screwed.
7717 //
7718 // Therefore, it needs to be a hash table, at least when it gets
7719 // large. On the other hand, when the data has totally arbitrary ints
7720 // or floats, there won't be many collisions, and we'll have tons of
7721 // 1-item bitmaps. That will be grossly inefficient as hash tables;
7722 // trade-off; the hash table is reasonably efficient per-item when
7723 // it's large, but not when it's small. So we need to do something
7724 // Judy-like and use different strategies depending on the size.
7725 //
7726 // Like Judy, we'll use the bottom bit to encode the strategy:
7727 //
7728 // bottom bits:
7729 // 00 - direct pointer
7730 // 01 - 4-item bucket (16 bytes, no length, NULLs)
7731 // 10 - N-item array
7732 // 11 - hash table
7733
7734 typedef struct stb_ps stb_ps;
7735
7736 STB_EXTERN int stb_ps_find (stb_ps *ps, void *value);
7737 STB_EXTERN stb_ps * stb_ps_add (stb_ps *ps, void *value);
7738 STB_EXTERN stb_ps * stb_ps_remove(stb_ps *ps, void *value);
7739 STB_EXTERN stb_ps * stb_ps_remove_any(stb_ps *ps, void **value);
7740 STB_EXTERN void stb_ps_delete(stb_ps *ps);
7741 STB_EXTERN int stb_ps_count (stb_ps *ps);
7742
7743 STB_EXTERN stb_ps * stb_ps_copy (stb_ps *ps);
7744 STB_EXTERN int stb_ps_subset(stb_ps *bigger, stb_ps *smaller);
7745 STB_EXTERN int stb_ps_eq (stb_ps *p0, stb_ps *p1);
7746
7747 STB_EXTERN void ** stb_ps_getlist (stb_ps *ps, int *count);
7748 STB_EXTERN int stb_ps_writelist(stb_ps *ps, void **list, int size );
7749
7750 // enum and fastlist don't allocate storage, but you must consume the
7751 // list before there's any chance the data structure gets screwed up;
7752 STB_EXTERN int stb_ps_enum (stb_ps *ps, void *data,
7753 int (*func)(void *value, void*data) );
7754 STB_EXTERN void ** stb_ps_fastlist(stb_ps *ps, int *count);
7755 // result:
7756 // returns a list, *count is the length of that list,
7757 // but some entries of the list may be invalid;
7758 // test with 'stb_ps_fastlist_valid(x)'
7759
7760 #define stb_ps_fastlist_valid(x) ((stb_uinta) (x) > 1)
7761
7762 #ifdef STB_DEFINE
7763
7764 enum
7765 {
7766 STB_ps_direct = 0,
7767 STB_ps_bucket = 1,
7768 STB_ps_array = 2,
7769 STB_ps_hash = 3,
7770 };
7771
7772 #define STB_BUCKET_SIZE 4
7773
7774 typedef struct
7775 {
7776 void *p[STB_BUCKET_SIZE];
7777 } stb_ps_bucket;
7778 #define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket))
7779 #define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket))
7780
7781 static void stb_bucket_free(stb_ps_bucket *b)
7782 {
7783 free(b);
7784 }
7785
7786 static stb_ps_bucket *stb_bucket_create2(void *v0, void *v1)
7787 {
7788 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7789 b->p[0] = v0;
7790 b->p[1] = v1;
7791 b->p[2] = NULL;
7792 b->p[3] = NULL;
7793 return b;
7794 }
7795
7796 static stb_ps_bucket * stb_bucket_create3(void **v)
7797 {
7798 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7799 b->p[0] = v[0];
7800 b->p[1] = v[1];
7801 b->p[2] = v[2];
7802 b->p[3] = NULL;
7803 return b;
7804 }
7805
7806
7807 // could use stb_arr, but this will save us memory
7808 typedef struct
7809 {
7810 int count;
7811 void *p[1];
7812 } stb_ps_array;
7813 #define GetArray(p) ((stb_ps_array *) ((char *) (p) - STB_ps_array))
7814 #define EncodeArray(p) ((stb_ps *) ((char *) (p) + STB_ps_array))
7815
7816 static int stb_ps_array_max = 13;
7817
7818 typedef struct
7819 {
7820 int size, mask;
7821 int count, count_deletes;
7822 int grow_threshhold;
7823 int shrink_threshhold;
7824 int rehash_threshhold;
7825 int any_offset;
7826 void *table[1];
7827 } stb_ps_hash;
7828 #define GetHash(p) ((stb_ps_hash *) ((char *) (p) - STB_ps_hash))
7829 #define EncodeHash(p) ((stb_ps *) ((char *) (p) + STB_ps_hash))
7830
7831 #define stb_ps_empty(v) (((stb_uint32) v) <= 1)
7832
7833 static stb_ps_hash *stb_ps_makehash(int size, int old_size, void **old_data)
7834 {
7835 int i;
7836 stb_ps_hash *h = (stb_ps_hash *) malloc(sizeof(*h) + (size-1) * sizeof(h->table[0]));
7837 assert(stb_is_pow2(size));
7838 h->size = size;
7839 h->mask = size-1;
7840 h->shrink_threshhold = (int) (0.3f * size);
7841 h-> grow_threshhold = (int) (0.8f * size);
7842 h->rehash_threshhold = (int) (0.9f * size);
7843 h->count = 0;
7844 h->count_deletes = 0;
7845 h->any_offset = 0;
7846 memset(h->table, 0, size * sizeof(h->table[0]));
7847 for (i=0; i < old_size; ++i)
7848 if (!stb_ps_empty((size_t)old_data[i]))
7849 stb_ps_add(EncodeHash(h), old_data[i]);
7850 return h;
7851 }
7852
7853 void stb_ps_delete(stb_ps *ps)
7854 {
7855 switch (3 & (int)(size_t) ps) {
7856 case STB_ps_direct: break;
7857 case STB_ps_bucket: stb_bucket_free(GetBucket(ps)); break;
7858 case STB_ps_array : free(GetArray(ps)); break;
7859 case STB_ps_hash : free(GetHash(ps)); break;
7860 }
7861 }
7862
7863 stb_ps *stb_ps_copy(stb_ps *ps)
7864 {
7865 int i;
7866 // not a switch: order based on expected performance/power-law distribution
7867 switch (3 & (int)(size_t) ps) {
7868 case STB_ps_direct: return ps;
7869 case STB_ps_bucket: {
7870 stb_ps_bucket *n = (stb_ps_bucket *) malloc(sizeof(*n));
7871 *n = *GetBucket(ps);
7872 return EncodeBucket(n);
7873 }
7874 case STB_ps_array: {
7875 stb_ps_array *a = GetArray(ps);
7876 stb_ps_array *n = (stb_ps_array *) malloc(sizeof(*n) + stb_ps_array_max * sizeof(n->p[0]));
7877 n->count = a->count;
7878 for (i=0; i < a->count; ++i)
7879 n->p[i] = a->p[i];
7880 return EncodeArray(n);
7881 }
7882 case STB_ps_hash: {
7883 stb_ps_hash *h = GetHash(ps);
7884 stb_ps_hash *n = stb_ps_makehash(h->size, h->size, h->table);
7885 return EncodeHash(n);
7886 }
7887 }
7888 assert(0); /* NOTREACHED */
7889 return NULL;
7890 }
7891
7892 int stb_ps_find(stb_ps *ps, void *value)
7893 {
7894 int i, code = 3 & (int)(size_t) ps;
7895 assert((3 & (int)(size_t) value) == STB_ps_direct);
7896 assert(stb_ps_fastlist_valid(value));
7897 // not a switch: order based on expected performance/power-law distribution
7898 if (code == STB_ps_direct)
7899 return value == ps;
7900 if (code == STB_ps_bucket) {
7901 stb_ps_bucket *b = GetBucket(ps);
7902 assert(STB_BUCKET_SIZE == 4);
7903 if (b->p[0] == value || b->p[1] == value ||
7904 b->p[2] == value || b->p[3] == value)
7905 return STB_TRUE;
7906 return STB_FALSE;
7907 }
7908 if (code == STB_ps_array) {
7909 stb_ps_array *a = GetArray(ps);
7910 for (i=0; i < a->count; ++i)
7911 if (a->p[i] == value)
7912 return STB_TRUE;
7913 return STB_FALSE;
7914 } else {
7915 stb_ps_hash *h = GetHash(ps);
7916 stb_uint32 hash = stb_hashptr(value);
7917 stb_uint32 s, n = hash & h->mask;
7918 void **t = h->table;
7919 if (t[n] == value) return STB_TRUE;
7920 if (t[n] == NULL) return STB_FALSE;
7921 s = stb_rehash(hash) | 1;
7922 do {
7923 n = (n + s) & h->mask;
7924 if (t[n] == value) return STB_TRUE;
7925 } while (t[n] != NULL);
7926 return STB_FALSE;
7927 }
7928 }
7929
7930 stb_ps * stb_ps_add (stb_ps *ps, void *value)
7931 {
7932 #ifdef STB_DEBUG
7933 assert(!stb_ps_find(ps,value));
7934 #endif
7935 if (value == NULL) return ps; // ignore NULL adds to avoid bad breakage
7936 assert((3 & (int)(size_t) value) == STB_ps_direct);
7937 assert(stb_ps_fastlist_valid(value));
7938 assert(value != STB_DEL); // STB_DEL is less likely
7939
7940 switch (3 & (int)(size_t) ps) {
7941 case STB_ps_direct:
7942 if (ps == NULL) return (stb_ps *) value;
7943 return EncodeBucket(stb_bucket_create2(ps,value));
7944
7945 case STB_ps_bucket: {
7946 stb_ps_bucket *b = GetBucket(ps);
7947 stb_ps_array *a;
7948 assert(STB_BUCKET_SIZE == 4);
7949 if (b->p[0] == NULL) { b->p[0] = value; return ps; }
7950 if (b->p[1] == NULL) { b->p[1] = value; return ps; }
7951 if (b->p[2] == NULL) { b->p[2] = value; return ps; }
7952 if (b->p[3] == NULL) { b->p[3] = value; return ps; }
7953 a = (stb_ps_array *) malloc(sizeof(*a) + 7 * sizeof(a->p[0])); // 8 slots, must be 2^k
7954 memcpy(a->p, b, sizeof(*b));
7955 a->p[4] = value;
7956 a->count = 5;
7957 stb_bucket_free(b);
7958 return EncodeArray(a);
7959 }
7960
7961 case STB_ps_array: {
7962 stb_ps_array *a = GetArray(ps);
7963 if (a->count == stb_ps_array_max) {
7964 // promote from array to hash
7965 stb_ps_hash *h = stb_ps_makehash(2 << stb_log2_ceil(a->count), a->count, a->p);
7966 free(a);
7967 return stb_ps_add(EncodeHash(h), value);
7968 }
7969 // do we need to resize the array? the array doubles in size when it
7970 // crosses a power-of-two
7971 if ((a->count & (a->count-1))==0) {
7972 int newsize = a->count*2;
7973 // clamp newsize to max if:
7974 // 1. it's larger than max
7975 // 2. newsize*1.5 is larger than max (to avoid extra resizing)
7976 if (newsize + a->count > stb_ps_array_max)
7977 newsize = stb_ps_array_max;
7978 a = (stb_ps_array *) realloc(a, sizeof(*a) + (newsize-1) * sizeof(a->p[0]));
7979 }
7980 a->p[a->count++] = value;
7981 return EncodeArray(a);
7982 }
7983 case STB_ps_hash: {
7984 stb_ps_hash *h = GetHash(ps);
7985 stb_uint32 hash = stb_hashptr(value);
7986 stb_uint32 n = hash & h->mask;
7987 void **t = h->table;
7988 // find first NULL or STB_DEL entry
7989 if (!stb_ps_empty((size_t)t[n])) {
7990 stb_uint32 s = stb_rehash(hash) | 1;
7991 do {
7992 n = (n + s) & h->mask;
7993 } while (!stb_ps_empty((size_t)t[n]));
7994 }
7995 if (t[n] == STB_DEL)
7996 -- h->count_deletes;
7997 t[n] = value;
7998 ++ h->count;
7999 if (h->count == h->grow_threshhold) {
8000 stb_ps_hash *h2 = stb_ps_makehash(h->size*2, h->size, t);
8001 free(h);
8002 return EncodeHash(h2);
8003 }
8004 if (h->count + h->count_deletes == h->rehash_threshhold) {
8005 stb_ps_hash *h2 = stb_ps_makehash(h->size, h->size, t);
8006 free(h);
8007 return EncodeHash(h2);
8008 }
8009 return ps;
8010 }
8011 }
8012 return NULL; /* NOTREACHED */
8013 }
8014
8015 stb_ps *stb_ps_remove(stb_ps *ps, void *value)
8016 {
8017 #ifdef STB_DEBUG
8018 assert(stb_ps_find(ps, value));
8019 #endif
8020 assert((3 & (int)(size_t) value) == STB_ps_direct);
8021 if (value == NULL) return ps; // ignore NULL removes to avoid bad breakage
8022 switch (3 & (int)(size_t) ps) {
8023 case STB_ps_direct:
8024 return ps == value ? NULL : ps;
8025 case STB_ps_bucket: {
8026 stb_ps_bucket *b = GetBucket(ps);
8027 int count=0;
8028 assert(STB_BUCKET_SIZE == 4);
8029 if (b->p[0] == value) b->p[0] = NULL; else count += (b->p[0] != NULL);
8030 if (b->p[1] == value) b->p[1] = NULL; else count += (b->p[1] != NULL);
8031 if (b->p[2] == value) b->p[2] = NULL; else count += (b->p[2] != NULL);
8032 if (b->p[3] == value) b->p[3] = NULL; else count += (b->p[3] != NULL);
8033 if (count == 1) { // shrink bucket at size 1
8034 value = b->p[0];
8035 if (value == NULL) value = b->p[1];
8036 if (value == NULL) value = b->p[2];
8037 if (value == NULL) value = b->p[3];
8038 assert(value != NULL);
8039 stb_bucket_free(b);
8040 return (stb_ps *) value; // return STB_ps_direct of value
8041 }
8042 return ps;
8043 }
8044 case STB_ps_array: {
8045 stb_ps_array *a = GetArray(ps);
8046 int i;
8047 for (i=0; i < a->count; ++i) {
8048 if (a->p[i] == value) {
8049 a->p[i] = a->p[--a->count];
8050 if (a->count == 3) { // shrink to bucket!
8051 stb_ps_bucket *b = stb_bucket_create3(a->p);
8052 free(a);
8053 return EncodeBucket(b);
8054 }
8055 return ps;
8056 }
8057 }
8058 return ps;
8059 }
8060 case STB_ps_hash: {
8061 stb_ps_hash *h = GetHash(ps);
8062 stb_uint32 hash = stb_hashptr(value);
8063 stb_uint32 s, n = hash & h->mask;
8064 void **t = h->table;
8065 if (t[n] != value) {
8066 s = stb_rehash(hash) | 1;
8067 do {
8068 n = (n + s) & h->mask;
8069 } while (t[n] != value);
8070 }
8071 t[n] = STB_DEL;
8072 -- h->count;
8073 ++ h->count_deletes;
8074 // should we shrink down to an array?
8075 if (h->count < stb_ps_array_max) {
8076 int n = 1 << stb_log2_floor(stb_ps_array_max);
8077 if (h->count < n) {
8078 stb_ps_array *a = (stb_ps_array *) malloc(sizeof(*a) + (n-1) * sizeof(a->p[0]));
8079 int i,j=0;
8080 for (i=0; i < h->size; ++i)
8081 if (!stb_ps_empty((size_t)t[i]))
8082 a->p[j++] = t[i];
8083 assert(j == h->count);
8084 a->count = j;
8085 free(h);
8086 return EncodeArray(a);
8087 }
8088 }
8089 if (h->count == h->shrink_threshhold) {
8090 stb_ps_hash *h2 = stb_ps_makehash(h->size >> 1, h->size, t);
8091 free(h);
8092 return EncodeHash(h2);
8093 }
8094 return ps;
8095 }
8096 }
8097 return ps; /* NOTREACHED */
8098 }
8099
8100 stb_ps *stb_ps_remove_any(stb_ps *ps, void **value)
8101 {
8102 assert(ps != NULL);
8103 switch (3 & (int)(size_t) ps) {
8104 case STB_ps_direct:
8105 *value = ps;
8106 return NULL;
8107 case STB_ps_bucket: {
8108 stb_ps_bucket *b = GetBucket(ps);
8109 int count=0, slast=0, last=0;
8110 assert(STB_BUCKET_SIZE == 4);
8111 if (b->p[0]) { ++count; last = 0; }
8112 if (b->p[1]) { ++count; slast = last; last = 1; }
8113 if (b->p[2]) { ++count; slast = last; last = 2; }
8114 if (b->p[3]) { ++count; slast = last; last = 3; }
8115 *value = b->p[last];
8116 b->p[last] = 0;
8117 if (count == 2) {
8118 void *leftover = b->p[slast]; // second to last
8119 stb_bucket_free(b);
8120 return (stb_ps *) leftover;
8121 }
8122 return ps;
8123 }
8124 case STB_ps_array: {
8125 stb_ps_array *a = GetArray(ps);
8126 *value = a->p[a->count-1];
8127 if (a->count == 4)
8128 return stb_ps_remove(ps, *value);
8129 --a->count;
8130 return ps;
8131 }
8132 case STB_ps_hash: {
8133 stb_ps_hash *h = GetHash(ps);
8134 void **t = h->table;
8135 stb_uint32 n = h->any_offset;
8136 while (stb_ps_empty((size_t)t[n]))
8137 n = (n + 1) & h->mask;
8138 *value = t[n];
8139 h->any_offset = (n+1) & h->mask;
8140 // check if we need to skip down to the previous type
8141 if (h->count-1 < stb_ps_array_max || h->count-1 == h->shrink_threshhold)
8142 return stb_ps_remove(ps, *value);
8143 t[n] = STB_DEL;
8144 -- h->count;
8145 ++ h->count_deletes;
8146 return ps;
8147 }
8148 }
8149 return ps; /* NOTREACHED */
8150 }
8151
8152
8153 void ** stb_ps_getlist(stb_ps *ps, int *count)
8154 {
8155 int i,n=0;
8156 void **p = NULL;
8157 switch (3 & (int)(size_t) ps) {
8158 case STB_ps_direct:
8159 if (ps == NULL) { *count = 0; return NULL; }
8160 p = (void **) malloc(sizeof(*p) * 1);
8161 p[0] = ps;
8162 *count = 1;
8163 return p;
8164 case STB_ps_bucket: {
8165 stb_ps_bucket *b = GetBucket(ps);
8166 p = (void **) malloc(sizeof(*p) * STB_BUCKET_SIZE);
8167 for (i=0; i < STB_BUCKET_SIZE; ++i)
8168 if (b->p[i] != NULL)
8169 p[n++] = b->p[i];
8170 break;
8171 }
8172 case STB_ps_array: {
8173 stb_ps_array *a = GetArray(ps);
8174 p = (void **) malloc(sizeof(*p) * a->count);
8175 memcpy(p, a->p, sizeof(*p) * a->count);
8176 *count = a->count;
8177 return p;
8178 }
8179 case STB_ps_hash: {
8180 stb_ps_hash *h = GetHash(ps);
8181 p = (void **) malloc(sizeof(*p) * h->count);
8182 for (i=0; i < h->size; ++i)
8183 if (!stb_ps_empty((size_t)h->table[i]))
8184 p[n++] = h->table[i];
8185 break;
8186 }
8187 }
8188 *count = n;
8189 return p;
8190 }
8191
8192 int stb_ps_writelist(stb_ps *ps, void **list, int size )
8193 {
8194 int i,n=0;
8195 switch (3 & (int)(size_t) ps) {
8196 case STB_ps_direct:
8197 if (ps == NULL || size <= 0) return 0;
8198 list[0] = ps;
8199 return 1;
8200 case STB_ps_bucket: {
8201 stb_ps_bucket *b = GetBucket(ps);
8202 for (i=0; i < STB_BUCKET_SIZE; ++i)
8203 if (b->p[i] != NULL && n < size)
8204 list[n++] = b->p[i];
8205 return n;
8206 }
8207 case STB_ps_array: {
8208 stb_ps_array *a = GetArray(ps);
8209 n = stb_min(size, a->count);
8210 memcpy(list, a->p, sizeof(*list) * n);
8211 return n;
8212 }
8213 case STB_ps_hash: {
8214 stb_ps_hash *h = GetHash(ps);
8215 if (size <= 0) return 0;
8216 for (i=0; i < h->count; ++i) {
8217 if (!stb_ps_empty((size_t)h->table[i])) {
8218 list[n++] = h->table[i];
8219 if (n == size) break;
8220 }
8221 }
8222 return n;
8223 }
8224 }
8225 return 0; /* NOTREACHED */
8226 }
8227
8228 int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data))
8229 {
8230 int i;
8231 switch (3 & (int)(size_t) ps) {
8232 case STB_ps_direct:
8233 if (ps == NULL) return STB_TRUE;
8234 return func(ps, data);
8235 case STB_ps_bucket: {
8236 stb_ps_bucket *b = GetBucket(ps);
8237 for (i=0; i < STB_BUCKET_SIZE; ++i)
8238 if (b->p[i] != NULL)
8239 if (!func(b->p[i], data))
8240 return STB_FALSE;
8241 return STB_TRUE;
8242 }
8243 case STB_ps_array: {
8244 stb_ps_array *a = GetArray(ps);
8245 for (i=0; i < a->count; ++i)
8246 if (!func(a->p[i], data))
8247 return STB_FALSE;
8248 return STB_TRUE;
8249 }
8250 case STB_ps_hash: {
8251 stb_ps_hash *h = GetHash(ps);
8252 for (i=0; i < h->count; ++i)
8253 if (!stb_ps_empty((size_t)h->table[i]))
8254 if (!func(h->table[i], data))
8255 return STB_FALSE;
8256 return STB_TRUE;
8257 }
8258 }
8259 return STB_TRUE; /* NOTREACHED */
8260 }
8261
8262 int stb_ps_count (stb_ps *ps)
8263 {
8264 switch (3 & (int)(size_t) ps) {
8265 case STB_ps_direct:
8266 return ps != NULL;
8267 case STB_ps_bucket: {
8268 stb_ps_bucket *b = GetBucket(ps);
8269 return (b->p[0] != NULL) + (b->p[1] != NULL) +
8270 (b->p[2] != NULL) + (b->p[3] != NULL);
8271 }
8272 case STB_ps_array: {
8273 stb_ps_array *a = GetArray(ps);
8274 return a->count;
8275 }
8276 case STB_ps_hash: {
8277 stb_ps_hash *h = GetHash(ps);
8278 return h->count;
8279 }
8280 }
8281 return 0;
8282 }
8283
8284 void ** stb_ps_fastlist(stb_ps *ps, int *count)
8285 {
8286 static void *storage;
8287
8288 switch (3 & (int)(size_t) ps) {
8289 case STB_ps_direct:
8290 if (ps == NULL) { *count = 0; return NULL; }
8291 storage = ps;
8292 *count = 1;
8293 return &storage;
8294 case STB_ps_bucket: {
8295 stb_ps_bucket *b = GetBucket(ps);
8296 *count = STB_BUCKET_SIZE;
8297 return b->p;
8298 }
8299 case STB_ps_array: {
8300 stb_ps_array *a = GetArray(ps);
8301 *count = a->count;
8302 return a->p;
8303 }
8304 case STB_ps_hash: {
8305 stb_ps_hash *h = GetHash(ps);
8306 *count = h->size;
8307 return h->table;
8308 }
8309 }
8310 return NULL; /* NOTREACHED */
8311 }
8312
8313 int stb_ps_subset(stb_ps *bigger, stb_ps *smaller)
8314 {
8315 int i, listlen;
8316 void **list = stb_ps_fastlist(smaller, &listlen);
8317 for(i=0; i < listlen; ++i)
8318 if (stb_ps_fastlist_valid(list[i]))
8319 if (!stb_ps_find(bigger, list[i]))
8320 return 0;
8321 return 1;
8322 }
8323
8324 int stb_ps_eq(stb_ps *p0, stb_ps *p1)
8325 {
8326 if (stb_ps_count(p0) != stb_ps_count(p1))
8327 return 0;
8328 return stb_ps_subset(p0, p1);
8329 }
8330
8331 #undef GetBucket
8332 #undef GetArray
8333 #undef GetHash
8334
8335 #undef EncodeBucket
8336 #undef EncodeArray
8337 #undef EncodeHash
8338
8339 #endif
8340
8341
8342 //////////////////////////////////////////////////////////////////////////////
8343 //
8344 // Random Numbers via Meresenne Twister or LCG
8345 //
8346
8347 STB_EXTERN unsigned int stb_srandLCG(unsigned int seed);
8348 STB_EXTERN unsigned int stb_randLCG(void);
8349 STB_EXTERN double stb_frandLCG(void);
8350
8351 STB_EXTERN void stb_srand(unsigned int seed);
8352 STB_EXTERN unsigned int stb_rand(void);
8353 STB_EXTERN double stb_frand(void);
8354 STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz,
8355 unsigned int seed);
8356 STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz);
8357
8358 STB_EXTERN unsigned int stb_randLCG_explicit(unsigned int seed);
8359
8360 #define stb_rand_define(x,y) \
8361 \
8362 unsigned int x(void) \
8363 { \
8364 static unsigned int stb__rand = y; \
8365 stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \
8366 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \
8367 }
8368
8369 #ifdef STB_DEFINE
8370 unsigned int stb_randLCG_explicit(unsigned int seed)
8371 {
8372 return seed * 2147001325 + 715136305;
8373 }
8374
8375 static unsigned int stb__rand_seed=0;
8376
8377 unsigned int stb_srandLCG(unsigned int seed)
8378 {
8379 unsigned int previous = stb__rand_seed;
8380 stb__rand_seed = seed;
8381 return previous;
8382 }
8383
8384 unsigned int stb_randLCG(void)
8385 {
8386 stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator
8387 // shuffle non-random bits to the middle, and xor to decorrelate with seed
8388 return 0x31415926 ^ ((stb__rand_seed >> 16) + (stb__rand_seed << 16));
8389 }
8390
8391 double stb_frandLCG(void)
8392 {
8393 return stb_randLCG() / ((double) (1 << 16) * (1 << 16));
8394 }
8395
8396 void stb_shuffle(void *p, size_t n, size_t sz, unsigned int seed)
8397 {
8398 char *a;
8399 unsigned int old_seed;
8400 int i;
8401 if (seed)
8402 old_seed = stb_srandLCG(seed);
8403 a = (char *) p + (n-1) * sz;
8404
8405 for (i=(int) n; i > 1; --i) {
8406 int j = stb_randLCG() % i;
8407 stb_swap(a, (char *) p + j * sz, sz);
8408 a -= sz;
8409 }
8410 if (seed)
8411 stb_srandLCG(old_seed);
8412 }
8413
8414 void stb_reverse(void *p, size_t n, size_t sz)
8415 {
8416 size_t i,j = n-1;
8417 for (i=0; i < j; ++i,--j) {
8418 stb_swap((char *) p + i * sz, (char *) p + j * sz, sz);
8419 }
8420 }
8421
8422 // public domain Mersenne Twister by Michael Brundage
8423 #define STB__MT_LEN 624
8424
8425 int stb__mt_index = STB__MT_LEN*sizeof(int)+1;
8426 unsigned int stb__mt_buffer[STB__MT_LEN];
8427
8428 void stb_srand(unsigned int seed)
8429 {
8430 int i;
8431 unsigned int old = stb_srandLCG(seed);
8432 for (i = 0; i < STB__MT_LEN; i++)
8433 stb__mt_buffer[i] = stb_randLCG();
8434 stb_srandLCG(old);
8435 stb__mt_index = STB__MT_LEN*sizeof(unsigned int);
8436 }
8437
8438 #define STB__MT_IA 397
8439 #define STB__MT_IB (STB__MT_LEN - STB__MT_IA)
8440 #define STB__UPPER_MASK 0x80000000
8441 #define STB__LOWER_MASK 0x7FFFFFFF
8442 #define STB__MATRIX_A 0x9908B0DF
8443 #define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK)
8444 #define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A)
8445
8446 unsigned int stb_rand()
8447 {
8448 unsigned int * b = stb__mt_buffer;
8449 int idx = stb__mt_index;
8450 unsigned int s,r;
8451 int i;
8452
8453 if (idx >= STB__MT_LEN*sizeof(unsigned int)) {
8454 if (idx > STB__MT_LEN*sizeof(unsigned int))
8455 stb_srand(0);
8456 idx = 0;
8457 i = 0;
8458 for (; i < STB__MT_IB; i++) {
8459 s = STB__TWIST(b, i, i+1);
8460 b[i] = b[i + STB__MT_IA] ^ (s >> 1) ^ STB__MAGIC(s);
8461 }
8462 for (; i < STB__MT_LEN-1; i++) {
8463 s = STB__TWIST(b, i, i+1);
8464 b[i] = b[i - STB__MT_IB] ^ (s >> 1) ^ STB__MAGIC(s);
8465 }
8466
8467 s = STB__TWIST(b, STB__MT_LEN-1, 0);
8468 b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s);
8469 }
8470 stb__mt_index = idx + sizeof(unsigned int);
8471
8472 r = *(unsigned int *)((unsigned char *)b + idx);
8473
8474 r ^= (r >> 11);
8475 r ^= (r << 7) & 0x9D2C5680;
8476 r ^= (r << 15) & 0xEFC60000;
8477 r ^= (r >> 18);
8478
8479 return r;
8480 }
8481
8482 double stb_frand(void)
8483 {
8484 return stb_rand() / ((double) (1 << 16) * (1 << 16));
8485 }
8486
8487 #endif
8488
8489
8490 //////////////////////////////////////////////////////////////////////////////
8491 //
8492 // stb_dupe
8493 //
8494 // stb_dupe is a duplicate-finding system for very, very large data
8495 // structures--large enough that sorting is too slow, but not so large
8496 // that we can't keep all the data in memory. using it works as follows:
8497 //
8498 // 1. create an stb_dupe:
8499 // provide a hash function
8500 // provide an equality function
8501 // provide an estimate for the size
8502 // optionally provide a comparison function
8503 //
8504 // 2. traverse your data, 'adding' pointers to the stb_dupe
8505 //
8506 // 3. finish and ask for duplicates
8507 //
8508 // the stb_dupe will discard its intermediate data and build
8509 // a collection of sorted lists of duplicates, with non-duplicate
8510 // entries omitted entirely
8511 //
8512 //
8513 // Implementation strategy:
8514 //
8515 // while collecting the N items, we keep a hash table of approximate
8516 // size sqrt(N). (if you tell use the N up front, the hash table is
8517 // just that size exactly)
8518 //
8519 // each entry in the hash table is just an stb__arr of pointers (no need
8520 // to use stb_ps, because we don't need to delete from these)
8521 //
8522 // for step 3, for each entry in the hash table, we apply stb_dupe to it
8523 // recursively. once the size gets small enough (or doesn't decrease
8524 // significantly), we switch to either using qsort() on the comparison
8525 // function, or else we just do the icky N^2 gather
8526
8527
8528 typedef struct stb_dupe stb_dupe;
8529
8530 typedef int (*stb_compare_func)(void *a, void *b);
8531 typedef int (*stb_hash_func)(void *a, unsigned int seed);
8532
8533 STB_EXTERN void stb_dupe_free(stb_dupe *sd);
8534 STB_EXTERN stb_dupe *stb_dupe_create(stb_hash_func hash,
8535 stb_compare_func eq, int size, stb_compare_func ineq);
8536 STB_EXTERN void stb_dupe_add(stb_dupe *sd, void *item);
8537 STB_EXTERN void stb_dupe_finish(stb_dupe *sd);
8538 STB_EXTERN int stb_dupe_numsets(stb_dupe *sd);
8539 STB_EXTERN void **stb_dupe_set(stb_dupe *sd, int num);
8540 STB_EXTERN int stb_dupe_set_count(stb_dupe *sd, int num);
8541
8542 struct stb_dupe
8543 {
8544 void ***hash_table;
8545 int hash_size;
8546 int size_log2;
8547 int population;
8548
8549 int hash_shift;
8550 stb_hash_func hash;
8551
8552 stb_compare_func eq;
8553 stb_compare_func ineq;
8554
8555 void ***dupes;
8556 };
8557
8558 #ifdef STB_DEFINE
8559
8560 int stb_dupe_numsets(stb_dupe *sd)
8561 {
8562 assert(sd->hash_table == NULL);
8563 return stb_arr_len(sd->dupes);
8564 }
8565
8566 void **stb_dupe_set(stb_dupe *sd, int num)
8567 {
8568 assert(sd->hash_table == NULL);
8569 return sd->dupes[num];
8570 }
8571
8572 int stb_dupe_set_count(stb_dupe *sd, int num)
8573 {
8574 assert(sd->hash_table == NULL);
8575 return stb_arr_len(sd->dupes[num]);
8576 }
8577
8578 stb_dupe *stb_dupe_create(stb_hash_func hash, stb_compare_func eq, int size,
8579 stb_compare_func ineq)
8580 {
8581 int i, hsize;
8582 stb_dupe *sd = (stb_dupe *) malloc(sizeof(*sd));
8583
8584 sd->size_log2 = 4;
8585 hsize = 1 << sd->size_log2;
8586 while (hsize * hsize < size) {
8587 ++sd->size_log2;
8588 hsize *= 2;
8589 }
8590
8591 sd->hash = hash;
8592 sd->eq = eq;
8593 sd->ineq = ineq;
8594 sd->hash_shift = 0;
8595
8596 sd->population = 0;
8597 sd->hash_size = hsize;
8598 sd->hash_table = (void ***) malloc(sizeof(*sd->hash_table) * hsize);
8599 for (i=0; i < hsize; ++i)
8600 sd->hash_table[i] = NULL;
8601
8602 sd->dupes = NULL;
8603
8604 return sd;
8605 }
8606
8607 void stb_dupe_add(stb_dupe *sd, void *item)
8608 {
8609 stb_uint32 hash = sd->hash(item, sd->hash_shift);
8610 int z = hash & (sd->hash_size-1);
8611 stb_arr_push(sd->hash_table[z], item);
8612 ++sd->population;
8613 }
8614
8615 void stb_dupe_free(stb_dupe *sd)
8616 {
8617 int i;
8618 for (i=0; i < stb_arr_len(sd->dupes); ++i)
8619 if (sd->dupes[i])
8620 stb_arr_free(sd->dupes[i]);
8621 stb_arr_free(sd->dupes);
8622 free(sd);
8623 }
8624
8625 static stb_compare_func stb__compare;
8626
8627 static int stb__dupe_compare(const void *a, const void *b)
8628 {
8629 void *p = *(void **) a;
8630 void *q = *(void **) b;
8631
8632 return stb__compare(p,q);
8633 }
8634
8635 void stb_dupe_finish(stb_dupe *sd)
8636 {
8637 int i,j,k;
8638 assert(sd->dupes == NULL);
8639 for (i=0; i < sd->hash_size; ++i) {
8640 void ** list = sd->hash_table[i];
8641 if (list != NULL) {
8642 int n = stb_arr_len(list);
8643 // @TODO: measure to find good numbers instead of just making them up!
8644 int thresh = (sd->ineq ? 200 : 20);
8645 // if n is large enough to be worth it, and n is smaller than
8646 // before (so we can guarantee we'll use a smaller hash table);
8647 // and there are enough hash bits left, assuming full 32-bit hash
8648 if (n > thresh && n < (sd->population >> 3) && sd->hash_shift + sd->size_log2*2 < 32) {
8649
8650 // recursively process this row using stb_dupe, O(N log log N)
8651
8652 stb_dupe *d = stb_dupe_create(sd->hash, sd->eq, n, sd->ineq);
8653 d->hash_shift = stb_randLCG_explicit(sd->hash_shift);
8654 for (j=0; j < n; ++j)
8655 stb_dupe_add(d, list[j]);
8656 stb_arr_free(sd->hash_table[i]);
8657 stb_dupe_finish(d);
8658 for (j=0; j < stb_arr_len(d->dupes); ++j) {
8659 stb_arr_push(sd->dupes, d->dupes[j]);
8660 d->dupes[j] = NULL; // take over ownership
8661 }
8662 stb_dupe_free(d);
8663
8664 } else if (sd->ineq) {
8665
8666 // process this row using qsort(), O(N log N)
8667 stb__compare = sd->ineq;
8668 qsort(list, n, sizeof(list[0]), stb__dupe_compare);
8669
8670 // find equal subsequences of the list
8671 for (j=0; j < n-1; ) {
8672 // find a subsequence from j..k
8673 for (k=j; k < n; ++k)
8674 // only use ineq so eq can be left undefined
8675 if (sd->ineq(list[j], list[k]))
8676 break;
8677 // k is the first one not in the subsequence
8678 if (k-j > 1) {
8679 void **mylist = NULL;
8680 stb_arr_setlen(mylist, k-j);
8681 memcpy(mylist, list+j, sizeof(list[j]) * (k-j));
8682 stb_arr_push(sd->dupes, mylist);
8683 }
8684 j = k;
8685 }
8686 stb_arr_free(sd->hash_table[i]);
8687 } else {
8688
8689 // process this row using eq(), O(N^2)
8690 for (j=0; j < n; ++j) {
8691 if (list[j] != NULL) {
8692 void **output = NULL;
8693 for (k=j+1; k < n; ++k) {
8694 if (sd->eq(list[j], list[k])) {
8695 if (output == NULL)
8696 stb_arr_push(output, list[j]);
8697 stb_arr_push(output, list[k]);
8698 list[k] = NULL;
8699 }
8700 }
8701 list[j] = NULL;
8702 if (output)
8703 stb_arr_push(sd->dupes, output);
8704 }
8705 }
8706 stb_arr_free(sd->hash_table[i]);
8707 }
8708 }
8709 }
8710 free(sd->hash_table);
8711 sd->hash_table = NULL;
8712 }
8713 #endif
8714
8715 //////////////////////////////////////////////////////////////////////////////
8716 //
8717 // templatized Sort routine
8718 //
8719 // This is an attempt to implement a templated sorting algorithm.
8720 // To use it, you have to explicitly instantiate it as a _function_,
8721 // then you call that function. This allows the comparison to be inlined,
8722 // giving the sort similar performance to C++ sorts.
8723 //
8724 // It implements quicksort with three-way-median partitioning (generally
8725 // well-behaved), with a final insertion sort pass.
8726 //
8727 // When you define the compare expression, you should assume you have
8728 // elements of your array pointed to by 'a' and 'b', and perform the comparison
8729 // on those. OR you can use one or more statements; first say '0;', then
8730 // write whatever code you want, and compute the result into a variable 'c'.
8731
8732 #define stb_declare_sort(FUNCNAME, TYPE) \
8733 void FUNCNAME(TYPE *p, int n)
8734 #define stb_define_sort(FUNCNAME,TYPE,COMPARE) \
8735 stb__define_sort( void, FUNCNAME,TYPE,COMPARE)
8736 #define stb_define_sort_static(FUNCNAME,TYPE,COMPARE) \
8737 stb__define_sort(static void, FUNCNAME,TYPE,COMPARE)
8738
8739 #define stb__define_sort(MODE, FUNCNAME, TYPE, COMPARE) \
8740 \
8741 static void STB_(FUNCNAME,_ins_sort)(TYPE *p, int n) \
8742 { \
8743 int i,j; \
8744 for (i=1; i < n; ++i) { \
8745 TYPE t = p[i], *a = &t; \
8746 j = i; \
8747 while (j > 0) { \
8748 TYPE *b = &p[j-1]; \
8749 int c = COMPARE; \
8750 if (!c) break; \
8751 p[j] = p[j-1]; \
8752 --j; \
8753 } \
8754 if (i != j) \
8755 p[j] = t; \
8756 } \
8757 } \
8758 \
8759 static void STB_(FUNCNAME,_quicksort)(TYPE *p, int n) \
8760 { \
8761 /* threshold for transitioning to insertion sort */ \
8762 while (n > 12) { \
8763 TYPE *a,*b,t; \
8764 int c01,c12,c,m,i,j; \
8765 \
8766 /* compute median of three */ \
8767 m = n >> 1; \
8768 a = &p[0]; \
8769 b = &p[m]; \
8770 c = COMPARE; \
8771 c01 = c; \
8772 a = &p[m]; \
8773 b = &p[n-1]; \
8774 c = COMPARE; \
8775 c12 = c; \
8776 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ \
8777 if (c01 != c12) { \
8778 /* otherwise, we'll need to swap something else to middle */ \
8779 int z; \
8780 a = &p[0]; \
8781 b = &p[n-1]; \
8782 c = COMPARE; \
8783 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ \
8784 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ \
8785 z = (c == c12) ? 0 : n-1; \
8786 t = p[z]; \
8787 p[z] = p[m]; \
8788 p[m] = t; \
8789 } \
8790 /* now p[m] is the median-of-three */ \
8791 /* swap it to the beginning so it won't move around */ \
8792 t = p[0]; \
8793 p[0] = p[m]; \
8794 p[m] = t; \
8795 \
8796 /* partition loop */ \
8797 i=1; \
8798 j=n-1; \
8799 for(;;) { \
8800 /* handling of equality is crucial here */ \
8801 /* for sentinels & efficiency with duplicates */ \
8802 b = &p[0]; \
8803 for (;;++i) { \
8804 a=&p[i]; \
8805 c = COMPARE; \
8806 if (!c) break; \
8807 } \
8808 a = &p[0]; \
8809 for (;;--j) { \
8810 b=&p[j]; \
8811 c = COMPARE; \
8812 if (!c) break; \
8813 } \
8814 /* make sure we haven't crossed */ \
8815 if (i >= j) break; \
8816 t = p[i]; \
8817 p[i] = p[j]; \
8818 p[j] = t; \
8819 \
8820 ++i; \
8821 --j; \
8822 } \
8823 /* recurse on smaller side, iterate on larger */ \
8824 if (j < (n-i)) { \
8825 STB_(FUNCNAME,_quicksort)(p,j); \
8826 p = p+i; \
8827 n = n-i; \
8828 } else { \
8829 STB_(FUNCNAME,_quicksort)(p+i, n-i); \
8830 n = j; \
8831 } \
8832 } \
8833 } \
8834 \
8835 MODE FUNCNAME(TYPE *p, int n) \
8836 { \
8837 STB_(FUNCNAME, _quicksort)(p, n); \
8838 STB_(FUNCNAME, _ins_sort)(p, n); \
8839 } \
8840
8841
8842 //////////////////////////////////////////////////////////////////////////////
8843 //
8844 // stb_bitset an array of booleans indexed by integers
8845 //
8846
8847 typedef stb_uint32 stb_bitset;
8848
8849 STB_EXTERN stb_bitset *stb_bitset_new(int value, int len);
8850
8851 #define stb_bitset_clearall(arr,len) (memset(arr, 0, 4 * (len)))
8852 #define stb_bitset_setall(arr,len) (memset(arr, 255, 4 * (len)))
8853
8854 #define stb_bitset_setbit(arr,n) ((arr)[(n) >> 5] |= (1 << (n & 31)))
8855 #define stb_bitset_clearbit(arr,n) ((arr)[(n) >> 5] &= ~(1 << (n & 31)))
8856 #define stb_bitset_testbit(arr,n) ((arr)[(n) >> 5] & (1 << (n & 31)))
8857
8858 STB_EXTERN stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len);
8859
8860 STB_EXTERN int *stb_bitset_getlist(stb_bitset *out, int start, int end);
8861
8862 STB_EXTERN int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len);
8863 STB_EXTERN int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len);
8864 STB_EXTERN int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len);
8865 STB_EXTERN int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len);
8866 STB_EXTERN int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len);
8867
8868 #ifdef STB_DEFINE
8869 int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len)
8870 {
8871 int i;
8872 for (i=0; i < len; ++i)
8873 if (p0[i] != p1[i]) return 0;
8874 return 1;
8875 }
8876
8877 int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len)
8878 {
8879 int i;
8880 for (i=0; i < len; ++i)
8881 if (p0[i] & p1[i]) return 0;
8882 return 1;
8883 }
8884
8885 int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len)
8886 {
8887 int i;
8888 for (i=0; i < len; ++i)
8889 if ((p0[i] | p1[i]) != 0xffffffff) return 0;
8890 return 1;
8891 }
8892
8893 int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len)
8894 {
8895 int i;
8896 for (i=0; i < len; ++i)
8897 if ((bigger[i] & smaller[i]) != smaller[i]) return 0;
8898 return 1;
8899 }
8900
8901 stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len)
8902 {
8903 int i;
8904 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8905 for (i=0; i < len; ++i) d[i] = p0[i] | p1[i];
8906 return d;
8907 }
8908
8909 int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len)
8910 {
8911 int i, changed=0;
8912 for (i=0; i < len; ++i) {
8913 stb_bitset d = p0[i] | p1[i];
8914 if (d != p0[i]) {
8915 p0[i] = d;
8916 changed = 1;
8917 }
8918 }
8919 return changed;
8920 }
8921
8922 stb_bitset *stb_bitset_new(int value, int len)
8923 {
8924 int i;
8925 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8926 if (value) value = 0xffffffff;
8927 for (i=0; i < len; ++i) d[i] = value;
8928 return d;
8929 }
8930
8931 int *stb_bitset_getlist(stb_bitset *out, int start, int end)
8932 {
8933 int *list = NULL;
8934 int i;
8935 for (i=start; i < end; ++i)
8936 if (stb_bitset_testbit(out, i))
8937 stb_arr_push(list, i);
8938 return list;
8939 }
8940 #endif
8941
8942 //////////////////////////////////////////////////////////////////////////////
8943 //
8944 // stb_wordwrap quality word-wrapping for fixed-width fonts
8945 //
8946
8947 STB_EXTERN int stb_wordwrap(int *pairs, int pair_max, int count, char *str);
8948 STB_EXTERN int *stb_wordwrapalloc(int count, char *str);
8949
8950 #ifdef STB_DEFINE
8951
8952 int stb_wordwrap(int *pairs, int pair_max, int count, char *str)
8953 {
8954 int n=0,i=0, start=0,nonwhite=0;
8955 if (pairs == NULL) pair_max = 0x7ffffff0;
8956 else pair_max *= 2;
8957 // parse
8958 for(;;) {
8959 int s=i; // first whitespace char; last nonwhite+1
8960 int w; // word start
8961 // accept whitespace
8962 while (isspace(str[i])) {
8963 if (str[i] == '\n' || str[i] == '\r') {
8964 if (str[i] + str[i+1] == '\n' + '\r') ++i;
8965 if (n >= pair_max) return -1;
8966 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8967 n += 2;
8968 nonwhite=0;
8969 start = i+1;
8970 s = start;
8971 }
8972 ++i;
8973 }
8974 if (i >= start+count) {
8975 // we've gone off the end using whitespace
8976 if (nonwhite) {
8977 if (n >= pair_max) return -1;
8978 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8979 n += 2;
8980 start = s = i;
8981 nonwhite=0;
8982 } else {
8983 // output all the whitespace
8984 while (i >= start+count) {
8985 if (n >= pair_max) return -1;
8986 if (pairs) pairs[n] = start, pairs[n+1] = count;
8987 n += 2;
8988 start += count;
8989 }
8990 s = start;
8991 }
8992 }
8993
8994 if (str[i] == 0) break;
8995 // now scan out a word and see if it fits
8996 w = i;
8997 while (str[i] && !isspace(str[i])) {
8998 ++i;
8999 }
9000 // wrapped?
9001 if (i > start + count) {
9002 // huge?
9003 if (i-s <= count) {
9004 if (n >= pair_max) return -1;
9005 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
9006 n += 2;
9007 start = w;
9008 } else {
9009 // This word is longer than one line. If we wrap it onto N lines
9010 // there are leftover chars. do those chars fit on the cur line?
9011 // But if we have leading whitespace, we force it to start here.
9012 if ((w-start) + ((i-w) % count) <= count || !nonwhite) {
9013 // output a full line
9014 if (n >= pair_max) return -1;
9015 if (pairs) pairs[n] = start, pairs[n+1] = count;
9016 n += 2;
9017 start += count;
9018 w = start;
9019 } else {
9020 // output a partial line, trimming trailing whitespace
9021 if (s != start) {
9022 if (n >= pair_max) return -1;
9023 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
9024 n += 2;
9025 start = w;
9026 }
9027 }
9028 // now output full lines as needed
9029 while (start + count <= i) {
9030 if (n >= pair_max) return -1;
9031 if (pairs) pairs[n] = start, pairs[n+1] = count;
9032 n += 2;
9033 start += count;
9034 }
9035 }
9036 }
9037 nonwhite=1;
9038 }
9039 if (start < i) {
9040 if (n >= pair_max) return -1;
9041 if (pairs) pairs[n] = start, pairs[n+1] = i-start;
9042 n += 2;
9043 }
9044 return n>>1;
9045 }
9046
9047 int *stb_wordwrapalloc(int count, char *str)
9048 {
9049 int n = stb_wordwrap(NULL,0,count,str);
9050 int *z = NULL;
9051 stb_arr_setlen(z, n*2);
9052 stb_wordwrap(z, n, count, str);
9053 return z;
9054 }
9055 #endif
9056
9057
9058 //////////////////////////////////////////////////////////////////////////////
9059 //
9060 // stb_match: wildcards and regexping
9061 //
9062
9063 STB_EXTERN int stb_wildmatch (char *expr, char *candidate);
9064 STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
9065 STB_EXTERN int stb_wildfind (char *expr, char *candidate);
9066 STB_EXTERN int stb_wildfindi (char *expr, char *candidate);
9067
9068 STB_EXTERN int stb_regex(char *regex, char *candidate);
9069
9070 typedef struct stb_matcher stb_matcher;
9071
9072 STB_EXTERN stb_matcher *stb_regex_matcher(char *regex);
9073 STB_EXTERN int stb_matcher_match(stb_matcher *m, char *str);
9074 STB_EXTERN int stb_matcher_find(stb_matcher *m, char *str);
9075 STB_EXTERN void stb_matcher_free(stb_matcher *f);
9076
9077 STB_EXTERN stb_matcher *stb_lex_matcher(void);
9078 STB_EXTERN int stb_lex_item(stb_matcher *m, const char *str, int result);
9079 STB_EXTERN int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result);
9080 STB_EXTERN int stb_lex(stb_matcher *m, char *str, int *len);
9081
9082
9083
9084 #ifdef STB_DEFINE
9085
9086 static int stb__match_qstring(char *candidate, char *qstring, int qlen, int insensitive)
9087 {
9088 int i;
9089 if (insensitive) {
9090 for (i=0; i < qlen; ++i)
9091 if (qstring[i] == '?') {
9092 if (!candidate[i]) return 0;
9093 } else
9094 if (tolower(qstring[i]) != tolower(candidate[i]))
9095 return 0;
9096 } else {
9097 for (i=0; i < qlen; ++i)
9098 if (qstring[i] == '?') {
9099 if (!candidate[i]) return 0;
9100 } else
9101 if (qstring[i] != candidate[i])
9102 return 0;
9103 }
9104 return 1;
9105 }
9106
9107 static int stb__find_qstring(char *candidate, char *qstring, int qlen, int insensitive)
9108 {
9109 char c;
9110
9111 int offset=0;
9112 while (*qstring == '?') {
9113 ++qstring;
9114 --qlen;
9115 ++candidate;
9116 if (qlen == 0) return 0;
9117 if (*candidate == 0) return -1;
9118 }
9119
9120 c = *qstring++;
9121 --qlen;
9122 if (insensitive) c = tolower(c);
9123
9124 while (candidate[offset]) {
9125 if (c == (insensitive ? tolower(candidate[offset]) : candidate[offset]))
9126 if (stb__match_qstring(candidate+offset+1, qstring, qlen, insensitive))
9127 return offset;
9128 ++offset;
9129 }
9130
9131 return -1;
9132 }
9133
9134 int stb__wildmatch_raw2(char *expr, char *candidate, int search, int insensitive)
9135 {
9136 int where=0;
9137 int start = -1;
9138
9139 if (!search) {
9140 // parse to first '*'
9141 if (*expr != '*')
9142 start = 0;
9143 while (*expr != '*') {
9144 if (!*expr)
9145 return *candidate == 0 ? 0 : -1;
9146 if (*expr == '?') {
9147 if (!*candidate) return -1;
9148 } else {
9149 if (insensitive) {
9150 if (tolower(*candidate) != tolower(*expr))
9151 return -1;
9152 } else
9153 if (*candidate != *expr)
9154 return -1;
9155 }
9156 ++candidate, ++expr, ++where;
9157 }
9158 } else {
9159 // 0-length search string
9160 if (!*expr)
9161 return 0;
9162 }
9163
9164 assert(search || *expr == '*');
9165 if (!search)
9166 ++expr;
9167
9168 // implicit '*' at this point
9169
9170 while (*expr) {
9171 int o=0;
9172 // combine redundant * characters
9173 while (expr[0] == '*') ++expr;
9174
9175 // ok, at this point, expr[-1] == '*',
9176 // and expr[0] != '*'
9177
9178 if (!expr[0]) return start >= 0 ? start : 0;
9179
9180 // now find next '*'
9181 o = 0;
9182 while (expr[o] != '*') {
9183 if (expr[o] == 0)
9184 break;
9185 ++o;
9186 }
9187 // if no '*', scan to end, then match at end
9188 if (expr[o] == 0 && !search) {
9189 int z;
9190 for (z=0; z < o; ++z)
9191 if (candidate[z] == 0)
9192 return -1;
9193 while (candidate[z])
9194 ++z;
9195 // ok, now check if they match
9196 if (stb__match_qstring(candidate+z-o, expr, o, insensitive))
9197 return start >= 0 ? start : 0;
9198 return -1;
9199 } else {
9200 // if yes '*', then do stb__find_qmatch on the intervening chars
9201 int n = stb__find_qstring(candidate, expr, o, insensitive);
9202 if (n < 0)
9203 return -1;
9204 if (start < 0)
9205 start = where + n;
9206 expr += o;
9207 candidate += n+o;
9208 }
9209
9210 if (*expr == 0) {
9211 assert(search);
9212 return start;
9213 }
9214
9215 assert(*expr == '*');
9216 ++expr;
9217 }
9218
9219 return start >= 0 ? start : 0;
9220 }
9221
9222 int stb__wildmatch_raw(char *expr, char *candidate, int search, int insensitive)
9223 {
9224 char buffer[256];
9225 // handle multiple search strings
9226 char *s = strchr(expr, ';');
9227 char *last = expr;
9228 while (s) {
9229 int z;
9230 // need to allow for non-writeable strings... assume they're small
9231 if (s - last < 256) {
9232 stb_strncpy(buffer, last, (int) (s-last+1));
9233 z = stb__wildmatch_raw2(buffer, candidate, search, insensitive);
9234 } else {
9235 *s = 0;
9236 z = stb__wildmatch_raw2(last, candidate, search, insensitive);
9237 *s = ';';
9238 }
9239 if (z >= 0) return z;
9240 last = s+1;
9241 s = strchr(last, ';');
9242 }
9243 return stb__wildmatch_raw2(last, candidate, search, insensitive);
9244 }
9245
9246 int stb_wildmatch(char *expr, char *candidate)
9247 {
9248 return stb__wildmatch_raw(expr, candidate, 0,0) >= 0;
9249 }
9250
9251 int stb_wildmatchi(char *expr, char *candidate)
9252 {
9253 return stb__wildmatch_raw(expr, candidate, 0,1) >= 0;
9254 }
9255
9256 int stb_wildfind(char *expr, char *candidate)
9257 {
9258 return stb__wildmatch_raw(expr, candidate, 1,0);
9259 }
9260
9261 int stb_wildfindi(char *expr, char *candidate)
9262 {
9263 return stb__wildmatch_raw(expr, candidate, 1,1);
9264 }
9265
9266 typedef struct
9267 {
9268 stb_int16 transition[256];
9269 } stb_dfa;
9270
9271 // an NFA node represents a state you're in; it then has
9272 // an arbitrary number of edges dangling off of it
9273 // note this isn't utf8-y
9274 typedef struct
9275 {
9276 stb_int16 match; // character/set to match
9277 stb_uint16 node; // output node to go to
9278 } stb_nfa_edge;
9279
9280 typedef struct
9281 {
9282 stb_int16 goal; // does reaching this win the prize?
9283 stb_uint8 active; // is this in the active list
9284 stb_nfa_edge *out;
9285 stb_uint16 *eps; // list of epsilon closures
9286 } stb_nfa_node;
9287
9288 #define STB__DFA_UNDEF -1
9289 #define STB__DFA_GOAL -2
9290 #define STB__DFA_END -3
9291 #define STB__DFA_MGOAL -4
9292 #define STB__DFA_VALID 0
9293
9294 #define STB__NFA_STOP_GOAL -1
9295
9296 // compiled regexp
9297 struct stb_matcher
9298 {
9299 stb_uint16 start_node;
9300 stb_int16 dfa_start;
9301 stb_uint32 *charset;
9302 int num_charset;
9303 int match_start;
9304 stb_nfa_node *nodes;
9305 int does_lex;
9306
9307 // dfa matcher
9308 stb_dfa * dfa;
9309 stb_uint32 * dfa_mapping;
9310 stb_int16 * dfa_result;
9311 int num_words_per_dfa;
9312 };
9313
9314 static int stb__add_node(stb_matcher *matcher)
9315 {
9316 stb_nfa_node z;
9317 z.active = 0;
9318 z.eps = 0;
9319 z.goal = 0;
9320 z.out = 0;
9321 stb_arr_push(matcher->nodes, z);
9322 return stb_arr_len(matcher->nodes)-1;
9323 }
9324
9325 static void stb__add_epsilon(stb_matcher *matcher, int from, int to)
9326 {
9327 assert(from != to);
9328 if (matcher->nodes[from].eps == NULL)
9329 stb_arr_malloc((void **) &matcher->nodes[from].eps, matcher);
9330 stb_arr_push(matcher->nodes[from].eps, to);
9331 }
9332
9333 static void stb__add_edge(stb_matcher *matcher, int from, int to, int type)
9334 {
9335 stb_nfa_edge z = { (stb_int16)type, (stb_uint16)to };
9336 if (matcher->nodes[from].out == NULL)
9337 stb_arr_malloc((void **) &matcher->nodes[from].out, matcher);
9338 stb_arr_push(matcher->nodes[from].out, z);
9339 }
9340
9341 static char *stb__reg_parse_alt(stb_matcher *m, int s, char *r, stb_uint16 *e);
9342 static char *stb__reg_parse(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9343 {
9344 int n;
9345 int last_start = -1;
9346 stb_uint16 last_end = start;
9347
9348 while (*regex) {
9349 switch (*regex) {
9350 case '(':
9351 last_start = last_end;
9352 regex = stb__reg_parse_alt(matcher, last_end, regex+1, &last_end);
9353 if (regex == NULL || *regex != ')')
9354 return NULL;
9355 ++regex;
9356 break;
9357
9358 case '|':
9359 case ')':
9360 *end = last_end;
9361 return regex;
9362
9363 case '?':
9364 if (last_start < 0) return NULL;
9365 stb__add_epsilon(matcher, last_start, last_end);
9366 ++regex;
9367 break;
9368
9369 case '*':
9370 if (last_start < 0) return NULL;
9371 stb__add_epsilon(matcher, last_start, last_end);
9372
9373 // fall through
9374
9375 case '+':
9376 if (last_start < 0) return NULL;
9377 stb__add_epsilon(matcher, last_end, last_start);
9378 // prevent links back to last_end from chaining to last_start
9379 n = stb__add_node(matcher);
9380 stb__add_epsilon(matcher, last_end, n);
9381 last_end = n;
9382 ++regex;
9383 break;
9384
9385 case '{': // not supported!
9386 // @TODO: given {n,m}, clone last_start to last_end m times,
9387 // and include epsilons from start to first m-n blocks
9388 return NULL;
9389
9390 case '\\':
9391 ++regex;
9392 if (!*regex) return NULL;
9393
9394 // fallthrough
9395 default: // match exactly this character
9396 n = stb__add_node(matcher);
9397 stb__add_edge(matcher, last_end, n, *regex);
9398 last_start = last_end;
9399 last_end = n;
9400 ++regex;
9401 break;
9402
9403 case '$':
9404 n = stb__add_node(matcher);
9405 stb__add_edge(matcher, last_end, n, '\n');
9406 last_start = last_end;
9407 last_end = n;
9408 ++regex;
9409 break;
9410
9411 case '.':
9412 n = stb__add_node(matcher);
9413 stb__add_edge(matcher, last_end, n, -1);
9414 last_start = last_end;
9415 last_end = n;
9416 ++regex;
9417 break;
9418
9419 case '[': {
9420 stb_uint8 flags[256];
9421 int invert = 0,z;
9422 ++regex;
9423 if (matcher->num_charset == 0) {
9424 matcher->charset = (stb_uint *) stb_malloc(matcher, sizeof(*matcher->charset) * 256);
9425 memset(matcher->charset, 0, sizeof(*matcher->charset) * 256);
9426 }
9427
9428 memset(flags,0,sizeof(flags));
9429
9430 // leading ^ is special
9431 if (*regex == '^')
9432 ++regex, invert = 1;
9433
9434 // leading ] is special
9435 if (*regex == ']') {
9436 flags[(int) ']'] = 1;
9437 ++regex;
9438 }
9439 while (*regex != ']') {
9440 stb_uint a;
9441 if (!*regex) return NULL;
9442 a = *regex++;
9443 if (regex[0] == '-' && regex[1] != ']') {
9444 stb_uint i,b = regex[1];
9445 regex += 2;
9446 if (b == 0) return NULL;
9447 if (a > b) return NULL;
9448 for (i=a; i <= b; ++i)
9449 flags[i] = 1;
9450 } else
9451 flags[a] = 1;
9452 }
9453 ++regex;
9454 if (invert) {
9455 int i;
9456 for (i=0; i < 256; ++i)
9457 flags[i] = 1-flags[i];
9458 }
9459
9460 // now check if any existing charset matches
9461 for (z=0; z < matcher->num_charset; ++z) {
9462 int i, k[2] = { 0, 1 << z};
9463 for (i=0; i < 256; ++i) {
9464 unsigned int f = k[flags[i]];
9465 if ((matcher->charset[i] & k[1]) != f)
9466 break;
9467 }
9468 if (i == 256) break;
9469 }
9470
9471 if (z == matcher->num_charset) {
9472 int i;
9473 ++matcher->num_charset;
9474 if (matcher->num_charset > 32) {
9475 assert(0); /* NOTREACHED */
9476 return NULL; // too many charsets, oops
9477 }
9478 for (i=0; i < 256; ++i)
9479 if (flags[i])
9480 matcher->charset[i] |= (1 << z);
9481 }
9482
9483 n = stb__add_node(matcher);
9484 stb__add_edge(matcher, last_end, n, -2 - z);
9485 last_start = last_end;
9486 last_end = n;
9487 break;
9488 }
9489 }
9490 }
9491 *end = last_end;
9492 return regex;
9493 }
9494
9495 static char *stb__reg_parse_alt(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9496 {
9497 stb_uint16 last_end = start;
9498 stb_uint16 main_end;
9499
9500 int head, tail;
9501
9502 head = stb__add_node(matcher);
9503 stb__add_epsilon(matcher, start, head);
9504
9505 regex = stb__reg_parse(matcher, head, regex, &last_end);
9506 if (regex == NULL) return NULL;
9507 if (*regex == 0 || *regex == ')') {
9508 *end = last_end;
9509 return regex;
9510 }
9511
9512 main_end = last_end;
9513 tail = stb__add_node(matcher);
9514
9515 stb__add_epsilon(matcher, last_end, tail);
9516
9517 // start alternatives from the same starting node; use epsilon
9518 // transitions to combine their endings
9519 while(*regex && *regex != ')') {
9520 assert(*regex == '|');
9521 head = stb__add_node(matcher);
9522 stb__add_epsilon(matcher, start, head);
9523 regex = stb__reg_parse(matcher, head, regex+1, &last_end);
9524 if (regex == NULL)
9525 return NULL;
9526 stb__add_epsilon(matcher, last_end, tail);
9527 }
9528
9529 *end = tail;
9530 return regex;
9531 }
9532
9533 static char *stb__wild_parse(stb_matcher *matcher, int start, char *str, stb_uint16 *end)
9534 {
9535 int n;
9536 stb_uint16 last_end;
9537
9538 last_end = stb__add_node(matcher);
9539 stb__add_epsilon(matcher, start, last_end);
9540
9541 while (*str) {
9542 switch (*str) {
9543 // fallthrough
9544 default: // match exactly this character
9545 n = stb__add_node(matcher);
9546 if (toupper(*str) == tolower(*str)) {
9547 stb__add_edge(matcher, last_end, n, *str);
9548 } else {
9549 stb__add_edge(matcher, last_end, n, tolower(*str));
9550 stb__add_edge(matcher, last_end, n, toupper(*str));
9551 }
9552 last_end = n;
9553 ++str;
9554 break;
9555
9556 case '?':
9557 n = stb__add_node(matcher);
9558 stb__add_edge(matcher, last_end, n, -1);
9559 last_end = n;
9560 ++str;
9561 break;
9562
9563 case '*':
9564 n = stb__add_node(matcher);
9565 stb__add_edge(matcher, last_end, n, -1);
9566 stb__add_epsilon(matcher, last_end, n);
9567 stb__add_epsilon(matcher, n, last_end);
9568 last_end = n;
9569 ++str;
9570 break;
9571 }
9572 }
9573
9574 // now require end of string to match
9575 n = stb__add_node(matcher);
9576 stb__add_edge(matcher, last_end, n, 0);
9577 last_end = n;
9578
9579 *end = last_end;
9580 return str;
9581 }
9582
9583 static int stb__opt(stb_matcher *m, int n)
9584 {
9585 for(;;) {
9586 stb_nfa_node *p = &m->nodes[n];
9587 if (p->goal) return n;
9588 if (stb_arr_len(p->out)) return n;
9589 if (stb_arr_len(p->eps) != 1) return n;
9590 n = p->eps[0];
9591 }
9592 }
9593
9594 static void stb__optimize(stb_matcher *m)
9595 {
9596 // if the target of any edge is a node with exactly
9597 // one out-epsilon, shorten it
9598 int i,j;
9599 for (i=0; i < stb_arr_len(m->nodes); ++i) {
9600 stb_nfa_node *p = &m->nodes[i];
9601 for (j=0; j < stb_arr_len(p->out); ++j)
9602 p->out[j].node = stb__opt(m,p->out[j].node);
9603 for (j=0; j < stb_arr_len(p->eps); ++j)
9604 p->eps[j] = stb__opt(m,p->eps[j] );
9605 }
9606 m->start_node = stb__opt(m,m->start_node);
9607 }
9608
9609 void stb_matcher_free(stb_matcher *f)
9610 {
9611 stb_free(f);
9612 }
9613
9614 static stb_matcher *stb__alloc_matcher(void)
9615 {
9616 stb_matcher *matcher = (stb_matcher *) stb_malloc(0,sizeof(*matcher));
9617
9618 matcher->start_node = 0;
9619 stb_arr_malloc((void **) &matcher->nodes, matcher);
9620 matcher->num_charset = 0;
9621 matcher->match_start = 0;
9622 matcher->does_lex = 0;
9623
9624 matcher->dfa_start = STB__DFA_UNDEF;
9625 stb_arr_malloc((void **) &matcher->dfa, matcher);
9626 stb_arr_malloc((void **) &matcher->dfa_mapping, matcher);
9627 stb_arr_malloc((void **) &matcher->dfa_result, matcher);
9628
9629 stb__add_node(matcher);
9630
9631 return matcher;
9632 }
9633
9634 static void stb__lex_reset(stb_matcher *matcher)
9635 {
9636 // flush cached dfa data
9637 stb_arr_setlen(matcher->dfa, 0);
9638 stb_arr_setlen(matcher->dfa_mapping, 0);
9639 stb_arr_setlen(matcher->dfa_result, 0);
9640 matcher->dfa_start = STB__DFA_UNDEF;
9641 }
9642
9643 stb_matcher *stb_regex_matcher(char *regex)
9644 {
9645 char *z;
9646 stb_uint16 end;
9647 stb_matcher *matcher = stb__alloc_matcher();
9648 if (*regex == '^') {
9649 matcher->match_start = 1;
9650 ++regex;
9651 }
9652
9653 z = stb__reg_parse_alt(matcher, matcher->start_node, regex, &end);
9654
9655 if (!z || *z) {
9656 stb_free(matcher);
9657 return NULL;
9658 }
9659
9660 ((matcher->nodes)[(int) end]).goal = STB__NFA_STOP_GOAL;
9661
9662 return matcher;
9663 }
9664
9665 stb_matcher *stb_lex_matcher(void)
9666 {
9667 stb_matcher *matcher = stb__alloc_matcher();
9668
9669 matcher->match_start = 1;
9670 matcher->does_lex = 1;
9671
9672 return matcher;
9673 }
9674
9675 int stb_lex_item(stb_matcher *matcher, const char *regex, int result)
9676 {
9677 char *z;
9678 stb_uint16 end;
9679
9680 z = stb__reg_parse_alt(matcher, matcher->start_node, (char*) regex, &end);
9681
9682 if (z == NULL)
9683 return 0;
9684
9685 stb__lex_reset(matcher);
9686
9687 matcher->nodes[(int) end].goal = result;
9688 return 1;
9689 }
9690
9691 int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result)
9692 {
9693 char *z;
9694 stb_uint16 end;
9695
9696 z = stb__wild_parse(matcher, matcher->start_node, (char*) regex, &end);
9697
9698 if (z == NULL)
9699 return 0;
9700
9701 stb__lex_reset(matcher);
9702
9703 matcher->nodes[(int) end].goal = result;
9704 return 1;
9705 }
9706
9707 static void stb__clear(stb_matcher *m, stb_uint16 *list)
9708 {
9709 int i;
9710 for (i=0; i < stb_arr_len(list); ++i)
9711 m->nodes[(int) list[i]].active = 0;
9712 }
9713
9714 static int stb__clear_goalcheck(stb_matcher *m, stb_uint16 *list)
9715 {
9716 int i, t=0;
9717 for (i=0; i < stb_arr_len(list); ++i) {
9718 t += m->nodes[(int) list[i]].goal;
9719 m->nodes[(int) list[i]].active = 0;
9720 }
9721 return t;
9722 }
9723
9724 static stb_uint16 * stb__add_if_inactive(stb_matcher *m, stb_uint16 *list, int n)
9725 {
9726 if (!m->nodes[n].active) {
9727 stb_arr_push(list, n);
9728 m->nodes[n].active = 1;
9729 }
9730 return list;
9731 }
9732
9733 static stb_uint16 * stb__eps_closure(stb_matcher *m, stb_uint16 *list)
9734 {
9735 int i,n = stb_arr_len(list);
9736
9737 for(i=0; i < n; ++i) {
9738 stb_uint16 *e = m->nodes[(int) list[i]].eps;
9739 if (e) {
9740 int j,k = stb_arr_len(e);
9741 for (j=0; j < k; ++j)
9742 list = stb__add_if_inactive(m, list, e[j]);
9743 n = stb_arr_len(list);
9744 }
9745 }
9746
9747 return list;
9748 }
9749
9750 int stb_matcher_match(stb_matcher *m, char *str)
9751 {
9752 int result = 0;
9753 int i,j,y,z;
9754 stb_uint16 *previous = NULL;
9755 stb_uint16 *current = NULL;
9756 stb_uint16 *temp;
9757
9758 stb_arr_setsize(previous, 4);
9759 stb_arr_setsize(current, 4);
9760
9761 previous = stb__add_if_inactive(m, previous, m->start_node);
9762 previous = stb__eps_closure(m,previous);
9763 stb__clear(m, previous);
9764
9765 while (*str && stb_arr_len(previous)) {
9766 y = stb_arr_len(previous);
9767 for (i=0; i < y; ++i) {
9768 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9769 z = stb_arr_len(n->out);
9770 for (j=0; j < z; ++j) {
9771 if (n->out[j].match >= 0) {
9772 if (n->out[j].match == *str)
9773 current = stb__add_if_inactive(m, current, n->out[j].node);
9774 } else if (n->out[j].match == -1) {
9775 if (*str != '\n')
9776 current = stb__add_if_inactive(m, current, n->out[j].node);
9777 } else if (n->out[j].match < -1) {
9778 int z = -n->out[j].match - 2;
9779 if (m->charset[(stb_uint8) *str] & (1 << z))
9780 current = stb__add_if_inactive(m, current, n->out[j].node);
9781 }
9782 }
9783 }
9784 stb_arr_setlen(previous, 0);
9785
9786 temp = previous;
9787 previous = current;
9788 current = temp;
9789
9790 previous = stb__eps_closure(m,previous);
9791 stb__clear(m, previous);
9792
9793 ++str;
9794 }
9795
9796 // transition to pick up a '$' at the end
9797 y = stb_arr_len(previous);
9798 for (i=0; i < y; ++i)
9799 m->nodes[(int) previous[i]].active = 1;
9800
9801 for (i=0; i < y; ++i) {
9802 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9803 z = stb_arr_len(n->out);
9804 for (j=0; j < z; ++j) {
9805 if (n->out[j].match == '\n')
9806 current = stb__add_if_inactive(m, current, n->out[j].node);
9807 }
9808 }
9809
9810 previous = stb__eps_closure(m,previous);
9811 stb__clear(m, previous);
9812
9813 y = stb_arr_len(previous);
9814 for (i=0; i < y; ++i)
9815 if (m->nodes[(int) previous[i]].goal)
9816 result = 1;
9817
9818 stb_arr_free(previous);
9819 stb_arr_free(current);
9820
9821 return result && *str == 0;
9822 }
9823
9824 stb_int16 stb__get_dfa_node(stb_matcher *m, stb_uint16 *list)
9825 {
9826 stb_uint16 node;
9827 stb_uint32 data[8], *state, *newstate;
9828 int i,j,n;
9829
9830 state = (stb_uint32 *) stb_temp(data, m->num_words_per_dfa * 4);
9831 memset(state, 0, m->num_words_per_dfa*4);
9832
9833 n = stb_arr_len(list);
9834 for (i=0; i < n; ++i) {
9835 int x = list[i];
9836 state[x >> 5] |= 1 << (x & 31);
9837 }
9838
9839 // @TODO use a hash table
9840 n = stb_arr_len(m->dfa_mapping);
9841 i=j=0;
9842 for(; j < n; ++i, j += m->num_words_per_dfa) {
9843 // @TODO special case for <= 32
9844 if (!memcmp(state, m->dfa_mapping + j, m->num_words_per_dfa*4)) {
9845 node = i;
9846 goto done;
9847 }
9848 }
9849
9850 assert(stb_arr_len(m->dfa) == i);
9851 node = i;
9852
9853 newstate = stb_arr_addn(m->dfa_mapping, m->num_words_per_dfa);
9854 memcpy(newstate, state, m->num_words_per_dfa*4);
9855
9856 // set all transitions to 'unknown'
9857 stb_arr_add(m->dfa);
9858 memset(m->dfa[i].transition, -1, sizeof(m->dfa[i].transition));
9859
9860 if (m->does_lex) {
9861 int result = -1;
9862 n = stb_arr_len(list);
9863 for (i=0; i < n; ++i) {
9864 if (m->nodes[(int) list[i]].goal > result)
9865 result = m->nodes[(int) list[i]].goal;
9866 }
9867
9868 stb_arr_push(m->dfa_result, result);
9869 }
9870
9871 done:
9872 stb_tempfree(data, state);
9873 return node;
9874 }
9875
9876 static int stb__matcher_dfa(stb_matcher *m, char *str_c, int *len)
9877 {
9878 stb_uint8 *str = (stb_uint8 *) str_c;
9879 stb_int16 node,prevnode;
9880 stb_dfa *trans;
9881 int match_length = 0;
9882 stb_int16 match_result=0;
9883
9884 if (m->dfa_start == STB__DFA_UNDEF) {
9885 stb_uint16 *list;
9886
9887 m->num_words_per_dfa = (stb_arr_len(m->nodes)+31) >> 5;
9888 stb__optimize(m);
9889
9890 list = stb__add_if_inactive(m, NULL, m->start_node);
9891 list = stb__eps_closure(m,list);
9892 if (m->does_lex) {
9893 m->dfa_start = stb__get_dfa_node(m,list);
9894 stb__clear(m, list);
9895 // DON'T allow start state to be a goal state!
9896 // this allows people to specify regexes that can match 0
9897 // characters without them actually matching (also we don't
9898 // check _before_ advancing anyway
9899 if (m->dfa_start <= STB__DFA_MGOAL)
9900 m->dfa_start = -(m->dfa_start - STB__DFA_MGOAL);
9901 } else {
9902 if (stb__clear_goalcheck(m, list))
9903 m->dfa_start = STB__DFA_GOAL;
9904 else
9905 m->dfa_start = stb__get_dfa_node(m,list);
9906 }
9907 stb_arr_free(list);
9908 }
9909
9910 prevnode = STB__DFA_UNDEF;
9911 node = m->dfa_start;
9912 trans = m->dfa;
9913
9914 if (m->dfa_start == STB__DFA_GOAL)
9915 return 1;
9916
9917 for(;;) {
9918 assert(node >= STB__DFA_VALID);
9919
9920 // fast inner DFA loop; especially if STB__DFA_VALID is 0
9921
9922 do {
9923 prevnode = node;
9924 node = trans[node].transition[*str++];
9925 } while (node >= STB__DFA_VALID);
9926
9927 assert(node >= STB__DFA_MGOAL - stb_arr_len(m->dfa));
9928 assert(node < stb_arr_len(m->dfa));
9929
9930 // special case for lex: need _longest_ match, so notice goal
9931 // state without stopping
9932 if (node <= STB__DFA_MGOAL) {
9933 match_length = (int) (str - (stb_uint8 *) str_c);
9934 node = -(node - STB__DFA_MGOAL);
9935 match_result = node;
9936 continue;
9937 }
9938
9939 // slow NFA->DFA conversion
9940
9941 // or we hit the goal or the end of the string, but those
9942 // can only happen once per search...
9943
9944 if (node == STB__DFA_UNDEF) {
9945 // build a list -- @TODO special case <= 32 states
9946 // heck, use a more compact data structure for <= 16 and <= 8 ?!
9947
9948 // @TODO keep states/newstates around instead of reallocating them
9949 stb_uint16 *states = NULL;
9950 stb_uint16 *newstates = NULL;
9951 int i,j,y,z;
9952 stb_uint32 *flags = &m->dfa_mapping[prevnode * m->num_words_per_dfa];
9953 assert(prevnode != STB__DFA_UNDEF);
9954 stb_arr_setsize(states, 4);
9955 stb_arr_setsize(newstates,4);
9956 for (j=0; j < m->num_words_per_dfa; ++j) {
9957 for (i=0; i < 32; ++i) {
9958 if (*flags & (1 << i))
9959 stb_arr_push(states, j*32+i);
9960 }
9961 ++flags;
9962 }
9963 // states is now the states we were in in the previous node;
9964 // so now we can compute what node it transitions to on str[-1]
9965
9966 y = stb_arr_len(states);
9967 for (i=0; i < y; ++i) {
9968 stb_nfa_node *n = &m->nodes[(int) states[i]];
9969 z = stb_arr_len(n->out);
9970 for (j=0; j < z; ++j) {
9971 if (n->out[j].match >= 0) {
9972 if (n->out[j].match == str[-1] || (str[-1] == 0 && n->out[j].match == '\n'))
9973 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9974 } else if (n->out[j].match == -1) {
9975 if (str[-1] != '\n' && str[-1])
9976 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9977 } else if (n->out[j].match < -1) {
9978 int z = -n->out[j].match - 2;
9979 if (m->charset[str[-1]] & (1 << z))
9980 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9981 }
9982 }
9983 }
9984 // AND add in the start state!
9985 if (!m->match_start || (str[-1] == '\n' && !m->does_lex))
9986 newstates = stb__add_if_inactive(m, newstates, m->start_node);
9987 // AND epsilon close it
9988 newstates = stb__eps_closure(m, newstates);
9989 // if it's a goal state, then that's all there is to it
9990 if (stb__clear_goalcheck(m, newstates)) {
9991 if (m->does_lex) {
9992 match_length = (int) (str - (stb_uint8 *) str_c);
9993 node = stb__get_dfa_node(m,newstates);
9994 match_result = node;
9995 node = -node + STB__DFA_MGOAL;
9996 trans = m->dfa; // could have gotten realloc()ed
9997 } else
9998 node = STB__DFA_GOAL;
9999 } else if (str[-1] == 0 || stb_arr_len(newstates) == 0) {
10000 node = STB__DFA_END;
10001 } else {
10002 node = stb__get_dfa_node(m,newstates);
10003 trans = m->dfa; // could have gotten realloc()ed
10004 }
10005 trans[prevnode].transition[str[-1]] = node;
10006 if (node <= STB__DFA_MGOAL)
10007 node = -(node - STB__DFA_MGOAL);
10008 stb_arr_free(newstates);
10009 stb_arr_free(states);
10010 }
10011
10012 if (node == STB__DFA_GOAL) {
10013 return 1;
10014 }
10015 if (node == STB__DFA_END) {
10016 if (m->does_lex) {
10017 if (match_result) {
10018 if (len) *len = match_length;
10019 return m->dfa_result[(int) match_result];
10020 }
10021 }
10022 return 0;
10023 }
10024
10025 assert(node != STB__DFA_UNDEF);
10026 }
10027 }
10028
10029 int stb_matcher_find(stb_matcher *m, char *str)
10030 {
10031 assert(m->does_lex == 0);
10032 return stb__matcher_dfa(m, str, NULL);
10033 }
10034
10035 int stb_lex(stb_matcher *m, char *str, int *len)
10036 {
10037 assert(m->does_lex);
10038 return stb__matcher_dfa(m, str, len);
10039 }
10040
10041 int stb_regex(char *regex, char *str)
10042 {
10043 static stb_perfect p;
10044 static stb_matcher ** matchers;
10045 static char ** regexps;
10046 static char ** regexp_cache;
10047 static unsigned short *mapping;
10048 int z = stb_perfect_hash(&p, (int)(size_t) regex);
10049 if (z >= 0) {
10050 if (strcmp(regex, regexp_cache[(int) mapping[z]])) {
10051 int i = mapping[z];
10052 stb_matcher_free(matchers[i]);
10053 free(regexp_cache[i]);
10054 regexps[i] = regex;
10055 regexp_cache[i] = stb_p_strdup(regex);
10056 matchers[i] = stb_regex_matcher(regex);
10057 }
10058 } else {
10059 int i,n;
10060 if (regex == NULL) {
10061 for (i=0; i < stb_arr_len(matchers); ++i) {
10062 stb_matcher_free(matchers[i]);
10063 free(regexp_cache[i]);
10064 }
10065 stb_arr_free(matchers);
10066 stb_arr_free(regexps);
10067 stb_arr_free(regexp_cache);
10068 stb_perfect_destroy(&p);
10069 free(mapping); mapping = NULL;
10070 return -1;
10071 }
10072 stb_arr_push(regexps, regex);
10073 stb_arr_push(regexp_cache, stb_p_strdup(regex));
10074 stb_arr_push(matchers, stb_regex_matcher(regex));
10075 stb_perfect_destroy(&p);
10076 n = stb_perfect_create(&p, (unsigned int *) (char **) regexps, stb_arr_len(regexps));
10077 mapping = (unsigned short *) realloc(mapping, n * sizeof(*mapping));
10078 for (i=0; i < stb_arr_len(regexps); ++i)
10079 mapping[stb_perfect_hash(&p, (int)(size_t) regexps[i])] = i;
10080 z = stb_perfect_hash(&p, (int)(size_t) regex);
10081 }
10082 return stb_matcher_find(matchers[(int) mapping[z]], str);
10083 }
10084
10085 #endif // STB_DEFINE
10086
10087
10088 #if 0
10089 //////////////////////////////////////////////////////////////////////////////
10090 //
10091 // C source-code introspection
10092 //
10093
10094 // runtime structure
10095 typedef struct
10096 {
10097 char *name;
10098 char *type; // base type
10099 char *comment; // content of comment field
10100 int size; // size of base type
10101 int offset; // field offset
10102 int arrcount[8]; // array sizes; -1 = pointer indirection; 0 = end of list
10103 } stb_info_field;
10104
10105 typedef struct
10106 {
10107 char *structname;
10108 int size;
10109 int num_fields;
10110 stb_info_field *fields;
10111 } stb_info_struct;
10112
10113 extern stb_info_struct stb_introspect_output[];
10114
10115 //
10116
10117 STB_EXTERN void stb_introspect_precompiled(stb_info_struct *compiled);
10118 STB_EXTERN void stb__introspect(char *path, char *file);
10119
10120 #define stb_introspect_ship() stb__introspect(NULL, NULL, stb__introspect_output)
10121
10122 #ifdef STB_SHIP
10123 #define stb_introspect() stb_introspect_ship()
10124 #define stb_introspect_path(p) stb_introspect_ship()
10125 #else
10126 // bootstrapping: define stb_introspect() (or 'path') the first time
10127 #define stb_introspect() stb__introspect(NULL, __FILE__, NULL)
10128 #define stb_introspect_auto() stb__introspect(NULL, __FILE__, stb__introspect_output)
10129
10130 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
10131 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
10132 #endif
10133
10134 #ifdef STB_DEFINE
10135
10136 #ifndef STB_INTROSPECT_CPP
10137 #ifdef __cplusplus
10138 #define STB_INTROSPECT_CPP 1
10139 #else
10140 #define STB_INTROSPECT_CPP 0
10141 #endif
10142 #endif
10143
10144 void stb_introspect_precompiled(stb_info_struct *compiled)
10145 {
10146
10147 }
10148
10149
10150 static void stb__introspect_filename(char *buffer, char *path)
10151 {
10152 #if STB_INTROSPECT_CPP
10153 stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.cpp", path);
10154 #else
10155 stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.c", path);
10156 #endif
10157 }
10158
10159 static void stb__introspect_compute(char *path, char *file)
10160 {
10161 int i;
10162 char ** include_list = NULL;
10163 char ** introspect_list = NULL;
10164 FILE *f;
10165 f = stb_p_fopen(file, "w");
10166 if (!f) return;
10167
10168 fputs("// if you get compiler errors, change the following 0 to a 1:\n", f);
10169 fputs("#define STB_INTROSPECT_INVALID 0\n\n", f);
10170 fputs("// this will force the code to compile, and force the introspector\n", f);
10171 fputs("// to run and then exit, allowing you to recompile\n\n\n", f);
10172 fputs("#include \"stb.h\"\n\n",f );
10173 fputs("#if STB_INTROSPECT_INVALID\n", f);
10174 fputs(" stb_info_struct stb__introspect_output[] = { (void *) 1 }\n", f);
10175 fputs("#else\n\n", f);
10176 for (i=0; i < stb_arr_len(include_list); ++i)
10177 fprintf(f, " #include \"%s\"\n", include_list[i]);
10178
10179 fputs(" stb_info_struct stb__introspect_output[] =\n{\n", f);
10180 for (i=0; i < stb_arr_len(introspect_list); ++i)
10181 fprintf(f, " stb_introspect_%s,\n", introspect_list[i]);
10182 fputs(" };\n", f);
10183 fputs("#endif\n", f);
10184 fclose(f);
10185 }
10186
10187 static stb_info_struct *stb__introspect_info;
10188
10189 #ifndef STB_SHIP
10190
10191 #endif
10192
10193 void stb__introspect(char *path, char *file, stb_info_struct *compiled)
10194 {
10195 static int first=1;
10196 if (!first) return;
10197 first=0;
10198
10199 stb__introspect_info = compiled;
10200
10201 #ifndef STB_SHIP
10202 if (path || file) {
10203 int bail_flag = compiled && compiled[0].structname == (void *) 1;
10204 int needs_building = bail_flag;
10205 struct stb__stat st;
10206 char buffer[1024], buffer2[1024];
10207 if (!path) {
10208 stb_splitpath(buffer, file, STB_PATH);
10209 path = buffer;
10210 }
10211 // bail if the source path doesn't exist
10212 if (!stb_fexists(path)) return;
10213
10214 stb__introspect_filename(buffer2, path);
10215
10216 // get source/include files timestamps, compare to output-file timestamp;
10217 // if mismatched, regenerate
10218
10219 if (stb__stat(buffer2, &st))
10220 needs_building = STB_TRUE;
10221
10222 {
10223 // find any file that contains an introspection command and is newer
10224 // if needs_building is already true, we don't need to do this test,
10225 // but we still need these arrays, so go ahead and get them
10226 char **all[3];
10227 all[0] = stb_readdir_files_mask(path, "*.h");
10228 all[1] = stb_readdir_files_mask(path, "*.c");
10229 all[2] = stb_readdir_files_mask(path, "*.cpp");
10230 int i,j;
10231 if (needs_building) {
10232 for (j=0; j < 3; ++j) {
10233 for (i=0; i < stb_arr_len(all[j]); ++i) {
10234 struct stb__stat st2;
10235 if (!stb__stat(all[j][i], &st2)) {
10236 if (st.st_mtime < st2.st_mtime) {
10237 char *z = stb_filec(all[j][i], NULL);
10238 int found=STB_FALSE;
10239 while (y) {
10240 y = strstr(y, "//si");
10241 if (y && isspace(y[4])) {
10242 found = STB_TRUE;
10243 break;
10244 }
10245 }
10246 needs_building = STB_TRUE;
10247 goto done;
10248 }
10249 }
10250 }
10251 }
10252 done:;
10253 }
10254 char *z = stb_filec(all[i], NULL), *y = z;
10255 int found=STB_FALSE;
10256 while (y) {
10257 y = strstr(y, "//si");
10258 if (y && isspace(y[4])) {
10259 found = STB_TRUE;
10260 break;
10261 }
10262 }
10263 if (found)
10264 stb_arr_push(introspect_h, stb_p_strdup(all[i]));
10265 free(z);
10266 }
10267 }
10268 stb_readdir_free(all);
10269 if (!needs_building) {
10270 for (i=0; i < stb_arr_len(introspect_h); ++i) {
10271 struct stb__stat st2;
10272 if (!stb__stat(introspect_h[i], &st2))
10273 if (st.st_mtime < st2.st_mtime)
10274 needs_building = STB_TRUE;
10275 }
10276 }
10277
10278 if (needs_building) {
10279 stb__introspect_compute(path, buffer2);
10280 }
10281 }
10282 }
10283 #endif
10284 }
10285 #endif
10286 #endif
10287
10288 #ifdef STB_INTROSPECT
10289 // compile-time code-generator
10290 #define INTROSPECT(x) int main(int argc, char **argv) { stb__introspect(__FILE__); return 0; }
10291 #define FILE(x)
10292
10293 void stb__introspect(char *filename)
10294 {
10295 char *file = stb_file(filename, NULL);
10296 char *s = file, *t, **p;
10297 char *out_name = "stb_introspect.c";
10298 char *out_path;
10299 STB_ARR(char) filelist = NULL;
10300 int i,n;
10301 if (!file) stb_fatal("Couldn't open %s", filename);
10302
10303 out_path = stb_splitpathdup(filename, STB_PATH);
10304
10305 // search for the macros
10306 while (*s) {
10307 char buffer[256];
10308 while (*s && !isupper(*s)) ++s;
10309 s = stb_strtok_invert(buffer, s, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
10310 s = stb_skipwhite(s);
10311 if (*s == '(') {
10312 ++s;
10313 t = strchr(s, ')');
10314 if (t == NULL) stb_fatal("Error parsing %s", filename);
10315
10316 }
10317 }
10318 }
10319
10320
10321
10322 #endif
10323
10324
10325 //////////////////////////////////////////////////////////////////////////////
10326 //
10327 // STB-C sliding-window dictionary compression
10328 //
10329 // This uses a DEFLATE-style sliding window, but no bitwise entropy.
10330 // Everything is on byte boundaries, so you could then apply a byte-wise
10331 // entropy code, though that's nowhere near as effective.
10332 //
10333 // An STB-C stream begins with a 16-byte header:
10334 // 4 bytes: 0x57 0xBC 0x00 0x00
10335 // 8 bytes: big-endian size of decompressed data, 64-bits
10336 // 4 bytes: big-endian size of window (how far back decompressor may need)
10337 //
10338 // The following symbols appear in the stream (these were determined ad hoc,
10339 // not by analysis):
10340 //
10341 // [dict] 00000100 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10342 // [END] 00000101 11111010 cccccccc cccccccc cccccccc cccccccc
10343 // [dict] 00000110 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx
10344 // [literals] 00000111 zzzzzzzz zzzzzzzz
10345 // [literals] 00001zzz zzzzzzzz
10346 // [dict] 00010yyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10347 // [dict] 00011yyy yyyyyyyy yyyyyyyy xxxxxxxx
10348 // [literals] 001zzzzz
10349 // [dict] 01yyyyyy yyyyyyyy xxxxxxxx
10350 // [dict] 1xxxxxxx yyyyyyyy
10351 //
10352 // xxxxxxxx: match length - 1
10353 // yyyyyyyy: backwards distance - 1
10354 // zzzzzzzz: num literals - 1
10355 // cccccccc: adler32 checksum of decompressed data
10356 // (all big-endian)
10357
10358
10359 STB_EXTERN stb_uint stb_decompress_length(stb_uchar *input);
10360 STB_EXTERN stb_uint stb_decompress(stb_uchar *out,stb_uchar *in,stb_uint len);
10361 STB_EXTERN stb_uint stb_compress (stb_uchar *out,stb_uchar *in,stb_uint len);
10362 STB_EXTERN void stb_compress_window(int z);
10363 STB_EXTERN void stb_compress_hashsize(unsigned int z);
10364
10365 STB_EXTERN int stb_compress_tofile(char *filename, char *in, stb_uint len);
10366 STB_EXTERN int stb_compress_intofile(FILE *f, char *input, stb_uint len);
10367 STB_EXTERN char *stb_decompress_fromfile(char *filename, stb_uint *len);
10368
10369 STB_EXTERN int stb_compress_stream_start(FILE *f);
10370 STB_EXTERN void stb_compress_stream_end(int close);
10371 STB_EXTERN void stb_write(char *data, int data_len);
10372
10373 #ifdef STB_DEFINE
10374
10375 stb_uint stb_decompress_length(stb_uchar *input)
10376 {
10377 return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
10378 }
10379
10380 //////////////////// decompressor ///////////////////////
10381
10382 // simple implementation that just writes whole thing into big block
10383
10384 static unsigned char *stb__barrier;
10385 static unsigned char *stb__barrier2;
10386 static unsigned char *stb__barrier3;
10387 static unsigned char *stb__barrier4;
10388
10389 static stb_uchar *stb__dout;
10390 static void stb__match(stb_uchar *data, stb_uint length)
10391 {
10392 // INVERSE of memmove... write each byte before copying the next...
10393 assert (stb__dout + length <= stb__barrier);
10394 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10395 if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }
10396 while (length--) *stb__dout++ = *data++;
10397 }
10398
10399 static void stb__lit(stb_uchar *data, stb_uint length)
10400 {
10401 assert (stb__dout + length <= stb__barrier);
10402 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10403 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10404 memcpy(stb__dout, data, length);
10405 stb__dout += length;
10406 }
10407
10408 #define stb__in2(x) ((i[x] << 8) + i[(x)+1])
10409 #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
10410 #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
10411
10412 static stb_uchar *stb_decompress_token(stb_uchar *i)
10413 {
10414 if (*i >= 0x20) { // use fewer if's for cases that expand small
10415 if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10416 else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10417 else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
10418 } else { // more ifs for cases that expand large, since overhead is amortized
10419 if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10420 else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10421 else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
10422 else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
10423 else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10424 else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10425 }
10426 return i;
10427 }
10428
10429 stb_uint stb_decompress(stb_uchar *output, stb_uchar *i, stb_uint length)
10430 {
10431 stb_uint olen;
10432 if (stb__in4(0) != 0x57bC0000) return 0;
10433 if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
10434 olen = stb_decompress_length(i);
10435 stb__barrier2 = i;
10436 stb__barrier3 = i+length;
10437 stb__barrier = output + olen;
10438 stb__barrier4 = output;
10439 i += 16;
10440
10441 stb__dout = output;
10442 while (1) {
10443 stb_uchar *old_i = i;
10444 i = stb_decompress_token(i);
10445 if (i == old_i) {
10446 if (*i == 0x05 && i[1] == 0xfa) {
10447 assert(stb__dout == output + olen);
10448 if (stb__dout != output + olen) return 0;
10449 if (stb_adler32(1, output, olen) != (stb_uint) stb__in4(2))
10450 return 0;
10451 return olen;
10452 } else {
10453 assert(0); /* NOTREACHED */
10454 return 0;
10455 }
10456 }
10457 assert(stb__dout <= output + olen);
10458 if (stb__dout > output + olen)
10459 return 0;
10460 }
10461 }
10462
10463 char *stb_decompress_fromfile(char *filename, unsigned int *len)
10464 {
10465 unsigned int n;
10466 char *q;
10467 unsigned char *p;
10468 FILE *f = stb_p_fopen(filename, "rb"); if (f == NULL) return NULL;
10469 fseek(f, 0, SEEK_END);
10470 n = ftell(f);
10471 fseek(f, 0, SEEK_SET);
10472 p = (unsigned char * ) malloc(n); if (p == NULL) return NULL;
10473 fread(p, 1, n, f);
10474 fclose(f);
10475 if (p == NULL) return NULL;
10476 if (p[0] != 0x57 || p[1] != 0xBc || p[2] || p[3]) { free(p); return NULL; }
10477 q = (char *) malloc(stb_decompress_length(p)+1);
10478 if (!q) { free(p); return NULL; }
10479 *len = stb_decompress((unsigned char *) q, p, n);
10480 if (*len) q[*len] = 0;
10481 free(p);
10482 return q;
10483 }
10484
10485 #if 0
10486 // streaming decompressor
10487
10488 static struct
10489 {
10490 stb__uchar *in_buffer;
10491 stb__uchar *match;
10492
10493 stb__uint pending_literals;
10494 stb__uint pending_match;
10495 } xx;
10496
10497
10498
10499 static void stb__match(stb_uchar *data, stb_uint length)
10500 {
10501 // INVERSE of memmove... write each byte before copying the next...
10502 assert (stb__dout + length <= stb__barrier);
10503 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10504 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10505 while (length--) *stb__dout++ = *data++;
10506 }
10507
10508 static void stb__lit(stb_uchar *data, stb_uint length)
10509 {
10510 assert (stb__dout + length <= stb__barrier);
10511 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10512 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10513 memcpy(stb__dout, data, length);
10514 stb__dout += length;
10515 }
10516
10517 static void sx_match(stb_uchar *data, stb_uint length)
10518 {
10519 xx.match = data;
10520 xx.pending_match = length;
10521 }
10522
10523 static void sx_lit(stb_uchar *data, stb_uint length)
10524 {
10525 xx.pending_lit = length;
10526 }
10527
10528 static int stb_decompress_token_state(void)
10529 {
10530 stb__uchar *i = xx.in_buffer;
10531
10532 if (*i >= 0x20) { // use fewer if's for cases that expand small
10533 if (*i >= 0x80) sx_match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10534 else if (*i >= 0x40) sx_match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10535 else /* *i >= 0x20 */ sx_lit(i+1, i[0] - 0x20 + 1), i += 1;
10536 } else { // more ifs for cases that expand large, since overhead is amortized
10537 if (*i >= 0x18) sx_match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10538 else if (*i >= 0x10) sx_match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10539 else if (*i >= 0x08) sx_lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2;
10540 else if (*i == 0x07) sx_lit(i+3, stb__in2(1) + 1), i += 3;
10541 else if (*i == 0x06) sx_match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10542 else if (*i == 0x04) sx_match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10543 else return 0;
10544 }
10545 xx.in_buffer = i;
10546 return 1;
10547 }
10548 #endif
10549
10550
10551
10552 //////////////////// compressor ///////////////////////
10553
10554 static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
10555 {
10556 stb_uint i;
10557 for (i=0; i < maxlen; ++i)
10558 if (m1[i] != m2[i]) return i;
10559 return i;
10560 }
10561
10562 // simple implementation that just takes the source data in a big block
10563
10564 static stb_uchar *stb__out;
10565 static FILE *stb__outfile;
10566 static stb_uint stb__outbytes;
10567
10568 static void stb__write(unsigned char v)
10569 {
10570 fputc(v, stb__outfile);
10571 ++stb__outbytes;
10572 }
10573
10574 #define stb_out(v) (stb__out ? (void)(*stb__out++ = (stb_uchar) (v)) : stb__write((stb_uchar) (v)))
10575
10576 static void stb_out2(stb_uint v)
10577 {
10578 stb_out(v >> 8);
10579 stb_out(v);
10580 }
10581
10582 static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
10583 static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
10584 stb_out(v >> 8 ); stb_out(v); }
10585
10586 static void outliterals(stb_uchar *in, ptrdiff_t numlit)
10587 {
10588 while (numlit > 65536) {
10589 outliterals(in,65536);
10590 in += 65536;
10591 numlit -= 65536;
10592 }
10593
10594 if (numlit == 0) ;
10595 else if (numlit <= 32) stb_out (0x000020 + (stb_uint) numlit-1);
10596 else if (numlit <= 2048) stb_out2(0x000800 + (stb_uint) numlit-1);
10597 else /* numlit <= 65536) */ stb_out3(0x070000 + (stb_uint) numlit-1);
10598
10599 if (stb__out) {
10600 memcpy(stb__out,in,numlit);
10601 stb__out += numlit;
10602 } else
10603 fwrite(in, 1, numlit, stb__outfile);
10604 }
10605
10606 static int stb__window = 0x40000; // 256K
10607 void stb_compress_window(int z)
10608 {
10609 if (z >= 0x1000000) z = 0x1000000; // limit of implementation
10610 if (z < 0x100) z = 0x100; // insanely small
10611 stb__window = z;
10612 }
10613
10614 static int stb_not_crap(int best, int dist)
10615 {
10616 return ((best > 2 && dist <= 0x00100)
10617 || (best > 5 && dist <= 0x04000)
10618 || (best > 7 && dist <= 0x80000));
10619 }
10620
10621 static stb_uint stb__hashsize = 32768;
10622 void stb_compress_hashsize(unsigned int y)
10623 {
10624 unsigned int z = 1024;
10625 while (z < y) z <<= 1;
10626 stb__hashsize = z >> 2; // pass in bytes, store #pointers
10627 }
10628
10629 // note that you can play with the hashing functions all you
10630 // want without needing to change the decompressor
10631 #define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
10632 #define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
10633 #define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
10634
10635 static stb_uint32 stb__running_adler;
10636
10637 static int stb_compress_chunk(stb_uchar *history,
10638 stb_uchar *start,
10639 stb_uchar *end,
10640 int length,
10641 int *pending_literals,
10642 stb_uchar **chash,
10643 stb_uint mask)
10644 {
10645 int window = stb__window;
10646 stb_uint match_max;
10647 stb_uchar *lit_start = start - *pending_literals;
10648 stb_uchar *q = start;
10649
10650 #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
10651
10652 // stop short of the end so we don't scan off the end doing
10653 // the hashing; this means we won't compress the last few bytes
10654 // unless they were part of something longer
10655 while (q < start+length && q+12 < end) {
10656 int m;
10657 stb_uint h1,h2,h3,h4, h;
10658 stb_uchar *t;
10659 int best = 2, dist=0;
10660
10661 if (q+65536 > end)
10662 match_max = (stb_uint) (end-q);
10663 else
10664 match_max = 65536u;
10665
10666 #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
10667
10668 #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
10669 if (p ? dist != (int) (q-t) : 1) \
10670 if ((m = (int) stb_matchlen(t, q, match_max)) > best)\
10671 if (stb__nc(m,(int) (q-(t)))) \
10672 best = m, dist = (int) (q - (t))
10673
10674 // rather than search for all matches, only try 4 candidate locations,
10675 // chosen based on 4 different hash functions of different lengths.
10676 // this strategy is inspired by LZO; hashing is unrolled here using the
10677 // 'hc' macro
10678 h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
10679 t = chash[h1]; if (t) STB__TRY(t,0);
10680 h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
10681 h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
10682 h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
10683 h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
10684 h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
10685 t = chash[h4]; if (t) STB__TRY(t,1);
10686
10687 // because we use a shared hash table, can only update it
10688 // _after_ we've probed all of them
10689 chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
10690
10691 if (best > 2)
10692 assert(dist > 0);
10693
10694 // see if our best match qualifies
10695 if (best < 3) { // fast path literals
10696 ++q;
10697 } else if (best > 2 && best <= 0x80 && dist <= 0x100) {
10698 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10699 stb_out(0x80 + best-1);
10700 stb_out(dist-1);
10701 } else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
10702 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10703 stb_out2(0x4000 + dist-1);
10704 stb_out(best-1);
10705 } else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
10706 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10707 stb_out3(0x180000 + dist-1);
10708 stb_out(best-1);
10709 } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
10710 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10711 stb_out3(0x100000 + dist-1);
10712 stb_out2(best-1);
10713 } else if (best > 9 && dist <= 0x1000000) {
10714 if (best > 65536) best = 65536;
10715 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10716 if (best <= 0x100) {
10717 stb_out(0x06);
10718 stb_out3(dist-1);
10719 stb_out(best-1);
10720 } else {
10721 stb_out(0x04);
10722 stb_out3(dist-1);
10723 stb_out2(best-1);
10724 }
10725 } else { // fallback literals if no match was a balanced tradeoff
10726 ++q;
10727 }
10728 }
10729
10730 // if we didn't get all the way, add the rest to literals
10731 if (q-start < length)
10732 q = start+length;
10733
10734 // the literals are everything from lit_start to q
10735 *pending_literals = (int) (q - lit_start);
10736
10737 stb__running_adler = stb_adler32(stb__running_adler, start, (int) (q - start));
10738 return (int) (q - start);
10739 }
10740
10741 static int stb_compress_inner(stb_uchar *input, stb_uint length)
10742 {
10743 int literals = 0;
10744 stb_uint len,i;
10745
10746 stb_uchar **chash;
10747 chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
10748 if (chash == NULL) return 0; // failure
10749 for (i=0; i < stb__hashsize; ++i)
10750 chash[i] = NULL;
10751
10752 // stream signature
10753 stb_out(0x57); stb_out(0xbc);
10754 stb_out2(0);
10755
10756 stb_out4(0); // 64-bit length requires 32-bit leading 0
10757 stb_out4(length);
10758 stb_out4(stb__window);
10759
10760 stb__running_adler = 1;
10761
10762 len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
10763 assert(len == length);
10764
10765 outliterals(input+length - literals, literals);
10766
10767 free(chash);
10768
10769 stb_out2(0x05fa); // end opcode
10770
10771 stb_out4(stb__running_adler);
10772
10773 return 1; // success
10774 }
10775
10776 stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
10777 {
10778 stb__out = out;
10779 stb__outfile = NULL;
10780
10781 stb_compress_inner(input, length);
10782
10783 return (stb_uint) (stb__out - out);
10784 }
10785
10786 int stb_compress_tofile(char *filename, char *input, unsigned int length)
10787 {
10788 //int maxlen = length + 512 + (length >> 2); // total guess
10789 //char *buffer = (char *) malloc(maxlen);
10790 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10791
10792 stb__out = NULL;
10793 stb__outfile = stb_p_fopen(filename, "wb");
10794 if (!stb__outfile) return 0;
10795
10796 stb__outbytes = 0;
10797
10798 if (!stb_compress_inner((stb_uchar*)input, length))
10799 return 0;
10800
10801 fclose(stb__outfile);
10802
10803 return stb__outbytes;
10804 }
10805
10806 int stb_compress_intofile(FILE *f, char *input, unsigned int length)
10807 {
10808 //int maxlen = length + 512 + (length >> 2); // total guess
10809 //char *buffer = (char*)malloc(maxlen);
10810 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10811
10812 stb__out = NULL;
10813 stb__outfile = f;
10814 if (!stb__outfile) return 0;
10815
10816 stb__outbytes = 0;
10817
10818 if (!stb_compress_inner((stb_uchar*)input, length))
10819 return 0;
10820
10821 return stb__outbytes;
10822 }
10823
10824 ////////////////////// streaming I/O version /////////////////////
10825
10826
10827 static size_t stb_out_backpatch_id(void)
10828 {
10829 if (stb__out)
10830 return (size_t) stb__out;
10831 else
10832 return ftell(stb__outfile);
10833 }
10834
10835 static void stb_out_backpatch(size_t id, stb_uint value)
10836 {
10837 stb_uchar data[4] = { (stb_uchar)(value >> 24), (stb_uchar)(value >> 16), (stb_uchar)(value >> 8), (stb_uchar)(value) };
10838 if (stb__out) {
10839 memcpy((void *) id, data, 4);
10840 } else {
10841 stb_uint where = ftell(stb__outfile);
10842 fseek(stb__outfile, (long) id, SEEK_SET);
10843 fwrite(data, 4, 1, stb__outfile);
10844 fseek(stb__outfile, where, SEEK_SET);
10845 }
10846 }
10847
10848 // ok, the wraparound buffer was a total failure. let's instead
10849 // use a copying-in-place buffer, which lets us share the code.
10850 // This is way less efficient but it'll do for now.
10851
10852 static struct
10853 {
10854 stb_uchar *buffer;
10855 int size; // physical size of buffer in bytes
10856
10857 int valid; // amount of valid data in bytes
10858 int start; // bytes of data already output
10859
10860 int window;
10861 int fsize;
10862
10863 int pending_literals; // bytes not-quite output but counted in start
10864 int length_id;
10865
10866 stb_uint total_bytes;
10867
10868 stb_uchar **chash;
10869 stb_uint hashmask;
10870 } xtb;
10871
10872 static int stb_compress_streaming_start(void)
10873 {
10874 stb_uint i;
10875 xtb.size = stb__window * 3;
10876 xtb.buffer = (stb_uchar*)malloc(xtb.size);
10877 if (!xtb.buffer) return 0;
10878
10879 xtb.chash = (stb_uchar**)malloc(sizeof(*xtb.chash) * stb__hashsize);
10880 if (!xtb.chash) {
10881 free(xtb.buffer);
10882 return 0;
10883 }
10884
10885 for (i=0; i < stb__hashsize; ++i)
10886 xtb.chash[i] = NULL;
10887
10888 xtb.hashmask = stb__hashsize-1;
10889
10890 xtb.valid = 0;
10891 xtb.start = 0;
10892 xtb.window = stb__window;
10893 xtb.fsize = stb__window;
10894 xtb.pending_literals = 0;
10895 xtb.total_bytes = 0;
10896
10897 // stream signature
10898 stb_out(0x57); stb_out(0xbc); stb_out2(0);
10899
10900 stb_out4(0); // 64-bit length requires 32-bit leading 0
10901
10902 xtb.length_id = (int) stb_out_backpatch_id();
10903 stb_out4(0); // we don't know the output length yet
10904
10905 stb_out4(stb__window);
10906
10907 stb__running_adler = 1;
10908
10909 return 1;
10910 }
10911
10912 static int stb_compress_streaming_end(void)
10913 {
10914 // flush out any remaining data
10915 stb_compress_chunk(xtb.buffer, xtb.buffer+xtb.start, xtb.buffer+xtb.valid,
10916 xtb.valid-xtb.start, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10917
10918 // write out pending literals
10919 outliterals(xtb.buffer + xtb.valid - xtb.pending_literals, xtb.pending_literals);
10920
10921 stb_out2(0x05fa); // end opcode
10922 stb_out4(stb__running_adler);
10923
10924 stb_out_backpatch(xtb.length_id, xtb.total_bytes);
10925
10926 free(xtb.buffer);
10927 free(xtb.chash);
10928 return 1;
10929 }
10930
10931 void stb_write(char *data, int data_len)
10932 {
10933 stb_uint i;
10934
10935 // @TODO: fast path for filling the buffer and doing nothing else
10936 // if (xtb.valid + data_len < xtb.size)
10937
10938 xtb.total_bytes += data_len;
10939
10940 while (data_len) {
10941 // fill buffer
10942 if (xtb.valid < xtb.size) {
10943 int amt = xtb.size - xtb.valid;
10944 if (data_len < amt) amt = data_len;
10945 memcpy(xtb.buffer + xtb.valid, data, amt);
10946 data_len -= amt;
10947 data += amt;
10948 xtb.valid += amt;
10949 }
10950 if (xtb.valid < xtb.size)
10951 return;
10952
10953 // at this point, the buffer is full
10954
10955 // if we can process some data, go for it; make sure
10956 // we leave an 'fsize's worth of data, though
10957 if (xtb.start + xtb.fsize < xtb.valid) {
10958 int amount = (xtb.valid - xtb.fsize) - xtb.start;
10959 int n;
10960 assert(amount > 0);
10961 n = stb_compress_chunk(xtb.buffer, xtb.buffer + xtb.start, xtb.buffer + xtb.valid,
10962 amount, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10963 xtb.start += n;
10964 }
10965
10966 assert(xtb.start + xtb.fsize >= xtb.valid);
10967 // at this point, our future size is too small, so we
10968 // need to flush some history. we, in fact, flush exactly
10969 // one window's worth of history
10970
10971 {
10972 int flush = xtb.window;
10973 assert(xtb.start >= flush);
10974 assert(xtb.valid >= flush);
10975
10976 // if 'pending literals' extends back into the shift region,
10977 // write them out
10978 if (xtb.start - xtb.pending_literals < flush) {
10979 outliterals(xtb.buffer + xtb.start - xtb.pending_literals, xtb.pending_literals);
10980 xtb.pending_literals = 0;
10981 }
10982
10983 // now shift the window
10984 memmove(xtb.buffer, xtb.buffer + flush, xtb.valid - flush);
10985 xtb.start -= flush;
10986 xtb.valid -= flush;
10987
10988 for (i=0; i <= xtb.hashmask; ++i)
10989 if (xtb.chash[i] < xtb.buffer + flush)
10990 xtb.chash[i] = NULL;
10991 else
10992 xtb.chash[i] -= flush;
10993 }
10994 // and now that we've made room for more data, go back to the top
10995 }
10996 }
10997
10998 int stb_compress_stream_start(FILE *f)
10999 {
11000 stb__out = NULL;
11001 stb__outfile = f;
11002
11003 if (f == NULL)
11004 return 0;
11005
11006 if (!stb_compress_streaming_start())
11007 return 0;
11008
11009 return 1;
11010 }
11011
11012 void stb_compress_stream_end(int close)
11013 {
11014 stb_compress_streaming_end();
11015 if (close && stb__outfile) {
11016 fclose(stb__outfile);
11017 }
11018 }
11019
11020 #endif // STB_DEFINE
11021
11022 //////////////////////////////////////////////////////////////////////////////
11023 //
11024 // File abstraction... tired of not having this... we can write
11025 // compressors to be layers over these that auto-close their children.
11026
11027
11028 typedef struct stbfile
11029 {
11030 int (*getbyte)(struct stbfile *); // -1 on EOF
11031 unsigned int (*getdata)(struct stbfile *, void *block, unsigned int len);
11032
11033 int (*putbyte)(struct stbfile *, int byte);
11034 unsigned int (*putdata)(struct stbfile *, void *block, unsigned int len);
11035
11036 unsigned int (*size)(struct stbfile *);
11037
11038 unsigned int (*tell)(struct stbfile *);
11039 void (*backpatch)(struct stbfile *, unsigned int tell, void *block, unsigned int len);
11040
11041 void (*close)(struct stbfile *);
11042
11043 FILE *f; // file to fread/fwrite
11044 unsigned char *buffer; // input/output buffer
11045 unsigned char *indata, *inend; // input buffer
11046 union {
11047 int various;
11048 void *ptr;
11049 };
11050 } stbfile;
11051
11052 STB_EXTERN unsigned int stb_getc(stbfile *f); // read
11053 STB_EXTERN int stb_putc(stbfile *f, int ch); // write
11054 STB_EXTERN unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len); // read
11055 STB_EXTERN unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len); // write
11056 STB_EXTERN unsigned int stb_tell(stbfile *f); // read
11057 STB_EXTERN unsigned int stb_size(stbfile *f); // read/write
11058 STB_EXTERN void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len); // write
11059
11060 #ifdef STB_DEFINE
11061
11062 unsigned int stb_getc(stbfile *f) { return f->getbyte(f); }
11063 int stb_putc(stbfile *f, int ch) { return f->putbyte(f, ch); }
11064
11065 unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len)
11066 {
11067 return f->getdata(f, buffer, len);
11068 }
11069 unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len)
11070 {
11071 return f->putdata(f, buffer, len);
11072 }
11073 void stb_close(stbfile *f)
11074 {
11075 f->close(f);
11076 free(f);
11077 }
11078 unsigned int stb_tell(stbfile *f) { return f->tell(f); }
11079 unsigned int stb_size(stbfile *f) { return f->size(f); }
11080 void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len)
11081 {
11082 f->backpatch(f,tell,buffer,len);
11083 }
11084
11085 // FILE * implementation
11086 static int stb__fgetbyte(stbfile *f) { return fgetc(f->f); }
11087 static int stb__fputbyte(stbfile *f, int ch) { return fputc(ch, f->f)==0; }
11088 static unsigned int stb__fgetdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fread(buffer,1,len,f->f); }
11089 static unsigned int stb__fputdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fwrite(buffer,1,len,f->f); }
11090 static unsigned int stb__fsize(stbfile *f) { return (unsigned int) stb_filelen(f->f); }
11091 static unsigned int stb__ftell(stbfile *f) { return (unsigned int) ftell(f->f); }
11092 static void stb__fbackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len)
11093 {
11094 fseek(f->f, where, SEEK_SET);
11095 fwrite(buffer, 1, len, f->f);
11096 fseek(f->f, 0, SEEK_END);
11097 }
11098 static void stb__fclose(stbfile *f) { fclose(f->f); }
11099
11100 stbfile *stb_openf(FILE *f)
11101 {
11102 stbfile m = { stb__fgetbyte, stb__fgetdata,
11103 stb__fputbyte, stb__fputdata,
11104 stb__fsize, stb__ftell, stb__fbackpatch, stb__fclose,
11105 0,0,0, };
11106 stbfile *z = (stbfile *) malloc(sizeof(*z));
11107 if (z) {
11108 *z = m;
11109 z->f = f;
11110 }
11111 return z;
11112 }
11113
11114 static int stb__nogetbyte(stbfile *f) { assert(0); return -1; }
11115 static unsigned int stb__nogetdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
11116 static int stb__noputbyte(stbfile *f, int ch) { assert(0); return 0; }
11117 static unsigned int stb__noputdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
11118 static void stb__nobackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len) { assert(0); }
11119
11120 static int stb__bgetbyte(stbfile *s)
11121 {
11122 if (s->indata < s->inend)
11123 return *s->indata++;
11124 else
11125 return -1;
11126 }
11127
11128 static unsigned int stb__bgetdata(stbfile *s, void *buffer, unsigned int len)
11129 {
11130 if (s->indata + len > s->inend)
11131 len = (unsigned int) (s->inend - s->indata);
11132 memcpy(buffer, s->indata, len);
11133 s->indata += len;
11134 return len;
11135 }
11136 static unsigned int stb__bsize(stbfile *s) { return (unsigned int) (s->inend - s->buffer); }
11137 static unsigned int stb__btell(stbfile *s) { return (unsigned int) (s->indata - s->buffer); }
11138
11139 static void stb__bclose(stbfile *s)
11140 {
11141 if (s->various)
11142 free(s->buffer);
11143 }
11144
11145 stbfile *stb_open_inbuffer(void *buffer, unsigned int len)
11146 {
11147 stbfile m = { stb__bgetbyte, stb__bgetdata,
11148 stb__noputbyte, stb__noputdata,
11149 stb__bsize, stb__btell, stb__nobackpatch, stb__bclose };
11150 stbfile *z = (stbfile *) malloc(sizeof(*z));
11151 if (z) {
11152 *z = m;
11153 z->buffer = (unsigned char *) buffer;
11154 z->indata = z->buffer;
11155 z->inend = z->indata + len;
11156 }
11157 return z;
11158 }
11159
11160 stbfile *stb_open_inbuffer_free(void *buffer, unsigned int len)
11161 {
11162 stbfile *z = stb_open_inbuffer(buffer, len);
11163 if (z)
11164 z->various = 1; // free
11165 return z;
11166 }
11167
11168 #ifndef STB_VERSION
11169 // if we've been cut-and-pasted elsewhere, you get a limited
11170 // version of stb_open, without the 'k' flag and utf8 support
11171 static void stb__fclose2(stbfile *f)
11172 {
11173 fclose(f->f);
11174 }
11175
11176 stbfile *stb_open(char *filename, char *mode)
11177 {
11178 FILE *f = stb_p_fopen(filename, mode);
11179 stbfile *s;
11180 if (f == NULL) return NULL;
11181 s = stb_openf(f);
11182 if (s)
11183 s->close = stb__fclose2;
11184 return s;
11185 }
11186 #else
11187 // the full version depends on some code in stb.h; this
11188 // also includes the memory buffer output format implemented with stb_arr
11189 static void stb__fclose2(stbfile *f)
11190 {
11191 stb_fclose(f->f, f->various);
11192 }
11193
11194 stbfile *stb_open(char *filename, char *mode)
11195 {
11196 FILE *f = stb_fopen(filename, mode[0] == 'k' ? mode+1 : mode);
11197 stbfile *s;
11198 if (f == NULL) return NULL;
11199 s = stb_openf(f);
11200 if (s) {
11201 s->close = stb__fclose2;
11202 s->various = mode[0] == 'k' ? stb_keep_if_different : stb_keep_yes;
11203 }
11204 return s;
11205 }
11206
11207 static int stb__aputbyte(stbfile *f, int ch)
11208 {
11209 stb_arr_push(f->buffer, ch);
11210 return 1;
11211 }
11212 static unsigned int stb__aputdata(stbfile *f, void *data, unsigned int len)
11213 {
11214 memcpy(stb_arr_addn(f->buffer, (int) len), data, len);
11215 return len;
11216 }
11217 static unsigned int stb__asize(stbfile *f) { return stb_arr_len(f->buffer); }
11218 static void stb__abackpatch(stbfile *f, unsigned int where, void *data, unsigned int len)
11219 {
11220 memcpy(f->buffer+where, data, len);
11221 }
11222 static void stb__aclose(stbfile *f)
11223 {
11224 *(unsigned char **) f->ptr = f->buffer;
11225 }
11226
11227 stbfile *stb_open_outbuffer(unsigned char **update_on_close)
11228 {
11229 stbfile m = { stb__nogetbyte, stb__nogetdata,
11230 stb__aputbyte, stb__aputdata,
11231 stb__asize, stb__asize, stb__abackpatch, stb__aclose };
11232 stbfile *z = (stbfile *) malloc(sizeof(*z));
11233 if (z) {
11234 z->ptr = update_on_close;
11235 *z = m;
11236 }
11237 return z;
11238 }
11239 #endif
11240 #endif
11241
11242
11243 //////////////////////////////////////////////////////////////////////////////
11244 //
11245 // Arithmetic coder... based on cbloom's notes on the subject, should be
11246 // less code than a huffman code.
11247
11248 typedef struct
11249 {
11250 unsigned int range_low;
11251 unsigned int range_high;
11252 unsigned int code, range; // decode
11253 int buffered_u8;
11254 int pending_ffs;
11255 stbfile *output;
11256 } stb_arith;
11257
11258 STB_EXTERN void stb_arith_init_encode(stb_arith *a, stbfile *out);
11259 STB_EXTERN void stb_arith_init_decode(stb_arith *a, stbfile *in);
11260 STB_EXTERN stbfile *stb_arith_encode_close(stb_arith *a);
11261 STB_EXTERN stbfile *stb_arith_decode_close(stb_arith *a);
11262
11263 STB_EXTERN void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11264 STB_EXTERN void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11265 STB_EXTERN unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq);
11266 STB_EXTERN void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11267 STB_EXTERN unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2);
11268 STB_EXTERN void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11269
11270 STB_EXTERN void stb_arith_encode_byte(stb_arith *a, int byte);
11271 STB_EXTERN int stb_arith_decode_byte(stb_arith *a);
11272
11273 // this is a memory-inefficient way of doing things, but it's
11274 // fast(?) and simple
11275 typedef struct
11276 {
11277 unsigned short cumfreq;
11278 unsigned short samples;
11279 } stb_arith_symstate_item;
11280
11281 typedef struct
11282 {
11283 int num_sym;
11284 unsigned int pow2;
11285 int countdown;
11286 stb_arith_symstate_item data[1];
11287 } stb_arith_symstate;
11288
11289 #ifdef STB_DEFINE
11290 void stb_arith_init_encode(stb_arith *a, stbfile *out)
11291 {
11292 a->range_low = 0;
11293 a->range_high = 0xffffffff;
11294 a->pending_ffs = -1; // means no buffered character currently, to speed up normal case
11295 a->output = out;
11296 }
11297
11298 static void stb__arith_carry(stb_arith *a)
11299 {
11300 int i;
11301 assert(a->pending_ffs != -1); // can't carry with no data
11302 stb_putc(a->output, a->buffered_u8);
11303 for (i=0; i < a->pending_ffs; ++i)
11304 stb_putc(a->output, 0);
11305 }
11306
11307 static void stb__arith_putbyte(stb_arith *a, int byte)
11308 {
11309 if (a->pending_ffs) {
11310 if (a->pending_ffs == -1) { // means no buffered data; encoded for fast path efficiency
11311 if (byte == 0xff)
11312 stb_putc(a->output, byte); // just write it immediately
11313 else {
11314 a->buffered_u8 = byte;
11315 a->pending_ffs = 0;
11316 }
11317 } else if (byte == 0xff) {
11318 ++a->pending_ffs;
11319 } else {
11320 int i;
11321 stb_putc(a->output, a->buffered_u8);
11322 for (i=0; i < a->pending_ffs; ++i)
11323 stb_putc(a->output, 0xff);
11324 }
11325 } else if (byte == 0xff) {
11326 ++a->pending_ffs;
11327 } else {
11328 // fast path
11329 stb_putc(a->output, a->buffered_u8);
11330 a->buffered_u8 = byte;
11331 }
11332 }
11333
11334 static void stb__arith_flush(stb_arith *a)
11335 {
11336 if (a->pending_ffs >= 0) {
11337 int i;
11338 stb_putc(a->output, a->buffered_u8);
11339 for (i=0; i < a->pending_ffs; ++i)
11340 stb_putc(a->output, 0xff);
11341 }
11342 }
11343
11344 static void stb__renorm_encoder(stb_arith *a)
11345 {
11346 stb__arith_putbyte(a, a->range_low >> 24);
11347 a->range_low <<= 8;
11348 a->range_high = (a->range_high << 8) | 0xff;
11349 }
11350
11351 static void stb__renorm_decoder(stb_arith *a)
11352 {
11353 int c = stb_getc(a->output);
11354 a->code = (a->code << 8) + (c >= 0 ? c : 0); // if EOF, insert 0
11355 }
11356
11357 void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11358 {
11359 unsigned int range = a->range_high - a->range_low;
11360 unsigned int old = a->range_low;
11361 range /= totalfreq;
11362 a->range_low += range * cumfreq;
11363 a->range_high = a->range_low + range*freq;
11364 if (a->range_low < old)
11365 stb__arith_carry(a);
11366 while (a->range_high - a->range_low < 0x1000000)
11367 stb__renorm_encoder(a);
11368 }
11369
11370 void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11371 {
11372 unsigned int range = a->range_high - a->range_low;
11373 unsigned int old = a->range_low;
11374 range >>= totalfreq2;
11375 a->range_low += range * cumfreq;
11376 a->range_high = a->range_low + range*freq;
11377 if (a->range_low < old)
11378 stb__arith_carry(a);
11379 while (a->range_high - a->range_low < 0x1000000)
11380 stb__renorm_encoder(a);
11381 }
11382
11383 unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq)
11384 {
11385 unsigned int freqsize = a->range / totalfreq;
11386 unsigned int z = a->code / freqsize;
11387 return z >= totalfreq ? totalfreq-1 : z;
11388 }
11389
11390 void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11391 {
11392 unsigned int freqsize = a->range / totalfreq; // @OPTIMIZE, share with above divide somehow?
11393 a->code -= freqsize * cumfreq;
11394 a->range = freqsize * freq;
11395 while (a->range < 0x1000000)
11396 stb__renorm_decoder(a);
11397 }
11398
11399 unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2)
11400 {
11401 unsigned int freqsize = a->range >> totalfreq2;
11402 unsigned int z = a->code / freqsize;
11403 return z >= (1U<<totalfreq2) ? (1U<<totalfreq2)-1 : z;
11404 }
11405
11406 void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11407 {
11408 unsigned int freqsize = a->range >> totalfreq2;
11409 a->code -= freqsize * cumfreq;
11410 a->range = freqsize * freq;
11411 while (a->range < 0x1000000)
11412 stb__renorm_decoder(a);
11413 }
11414
11415 stbfile *stb_arith_encode_close(stb_arith *a)
11416 {
11417 // put exactly as many bytes as we'll read, so we can turn on/off arithmetic coding in a stream
11418 stb__arith_putbyte(a, a->range_low >> 24);
11419 stb__arith_putbyte(a, a->range_low >> 16);
11420 stb__arith_putbyte(a, a->range_low >> 8);
11421 stb__arith_putbyte(a, a->range_low >> 0);
11422 stb__arith_flush(a);
11423 return a->output;
11424 }
11425
11426 stbfile *stb_arith_decode_close(stb_arith *a)
11427 {
11428 return a->output;
11429 }
11430 #endif
11431
11432 //////////////////////////////////////////////////////////////////////////////
11433 //
11434 // Threads
11435 //
11436
11437 #ifndef _WIN32
11438 #ifdef STB_THREADS
11439 #error "threads not implemented except for Windows"
11440 #endif
11441 #endif
11442
11443 // call this function to free any global variables for memory testing
11444 STB_EXTERN void stb_thread_cleanup(void);
11445
11446 typedef void * (*stb_thread_func)(void *);
11447
11448 // do not rely on these types, this is an implementation detail.
11449 // compare against STB_THREAD_NULL and ST_SEMAPHORE_NULL
11450 typedef void *stb_thread;
11451 typedef void *stb_semaphore;
11452 typedef void *stb_mutex;
11453 typedef struct stb__sync *stb_sync;
11454
11455 #define STB_SEMAPHORE_NULL NULL
11456 #define STB_THREAD_NULL NULL
11457 #define STB_MUTEX_NULL NULL
11458 #define STB_SYNC_NULL NULL
11459
11460 // get the number of processors (limited to those in the affinity mask for this process).
11461 STB_EXTERN int stb_processor_count(void);
11462 // force to run on a single core -- needed for RDTSC to work, e.g. for iprof
11463 STB_EXTERN void stb_force_uniprocessor(void);
11464
11465 // stb_work functions: queue up work to be done by some worker threads
11466
11467 // set number of threads to serve the queue; you can change this on the fly,
11468 // but if you decrease it, it won't decrease until things currently on the
11469 // queue are finished
11470 STB_EXTERN void stb_work_numthreads(int n);
11471 // set maximum number of units in the queue; you can only set this BEFORE running any work functions
11472 STB_EXTERN int stb_work_maxunits(int n);
11473 // enqueue some work to be done (can do this from any thread, or even from a piece of work);
11474 // return value of f is stored in *return_code if non-NULL
11475 STB_EXTERN int stb_work(stb_thread_func f, void *d, volatile void **return_code);
11476 // as above, but stb_sync_reach is called on 'rel' after work is complete
11477 STB_EXTERN int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11478
11479
11480 // necessary to call this when using volatile to order writes/reads
11481 STB_EXTERN void stb_barrier(void);
11482
11483 // support for independent queues with their own threads
11484
11485 typedef struct stb__workqueue stb_workqueue;
11486
11487 STB_EXTERN stb_workqueue*stb_workq_new(int numthreads, int max_units);
11488 STB_EXTERN stb_workqueue*stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex);
11489 STB_EXTERN void stb_workq_delete(stb_workqueue *q);
11490 STB_EXTERN void stb_workq_numthreads(stb_workqueue *q, int n);
11491 STB_EXTERN int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code);
11492 STB_EXTERN int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11493 STB_EXTERN int stb_workq_length(stb_workqueue *q);
11494
11495 STB_EXTERN stb_thread stb_create_thread (stb_thread_func f, void *d);
11496 STB_EXTERN stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel);
11497 STB_EXTERN void stb_destroy_thread(stb_thread t);
11498
11499 STB_EXTERN stb_semaphore stb_sem_new(int max_val);
11500 STB_EXTERN stb_semaphore stb_sem_new_extra(int max_val, int start_val);
11501 STB_EXTERN void stb_sem_delete (stb_semaphore s);
11502 STB_EXTERN void stb_sem_waitfor(stb_semaphore s);
11503 STB_EXTERN void stb_sem_release(stb_semaphore s);
11504
11505 STB_EXTERN stb_mutex stb_mutex_new(void);
11506 STB_EXTERN void stb_mutex_delete(stb_mutex m);
11507 STB_EXTERN void stb_mutex_begin(stb_mutex m);
11508 STB_EXTERN void stb_mutex_end(stb_mutex m);
11509
11510 STB_EXTERN stb_sync stb_sync_new(void);
11511 STB_EXTERN void stb_sync_delete(stb_sync s);
11512 STB_EXTERN int stb_sync_set_target(stb_sync s, int count);
11513 STB_EXTERN void stb_sync_reach_and_wait(stb_sync s); // wait for 'target' reachers
11514 STB_EXTERN int stb_sync_reach(stb_sync s);
11515
11516 typedef struct stb__threadqueue stb_threadqueue;
11517 #define STB_THREADQ_DYNAMIC 0
11518 STB_EXTERN stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove);
11519 STB_EXTERN void stb_threadq_delete(stb_threadqueue *tq);
11520 STB_EXTERN int stb_threadq_get(stb_threadqueue *tq, void *output);
11521 STB_EXTERN void stb_threadq_get_block(stb_threadqueue *tq, void *output);
11522 STB_EXTERN int stb_threadq_add(stb_threadqueue *tq, void *input);
11523 // can return FALSE if STB_THREADQ_DYNAMIC and attempt to grow fails
11524 STB_EXTERN int stb_threadq_add_block(stb_threadqueue *tq, void *input);
11525
11526 #ifdef STB_THREADS
11527 #ifdef STB_DEFINE
11528
11529 typedef struct
11530 {
11531 stb_thread_func f;
11532 void *d;
11533 volatile void **return_val;
11534 stb_semaphore sem;
11535 } stb__thread;
11536
11537 // this is initialized along all possible paths to create threads, therefore
11538 // it's always initialized before any other threads are create, therefore
11539 // it's free of races AS LONG AS you only create threads through stb_*
11540 static stb_mutex stb__threadmutex, stb__workmutex;
11541
11542 static void stb__threadmutex_init(void)
11543 {
11544 if (stb__threadmutex == STB_SEMAPHORE_NULL) {
11545 stb__threadmutex = stb_mutex_new();
11546 stb__workmutex = stb_mutex_new();
11547 }
11548 }
11549
11550 #ifdef STB_THREAD_TEST
11551 volatile float stb__t1=1, stb__t2;
11552
11553 static void stb__wait(int n)
11554 {
11555 float z = 0;
11556 int i;
11557 for (i=0; i < n; ++i)
11558 z += 1 / (stb__t1+i);
11559 stb__t2 = z;
11560 }
11561 #else
11562 #define stb__wait(x)
11563 #endif
11564
11565 #ifdef _WIN32
11566
11567 // avoid including windows.h -- note that our definitions aren't
11568 // exactly the same (we don't define the security descriptor struct)
11569 // so if you want to include windows.h, make sure you do it first.
11570 #include <process.h>
11571
11572 #ifndef _WINDOWS_ // check windows.h guard
11573 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
11574 #define STB__DW unsigned long
11575
11576 STB__IMPORT int __stdcall TerminateThread(void *, STB__DW);
11577 STB__IMPORT void * __stdcall CreateSemaphoreA(void *sec, long,long,char*);
11578 STB__IMPORT int __stdcall CloseHandle(void *);
11579 STB__IMPORT STB__DW __stdcall WaitForSingleObject(void *, STB__DW);
11580 STB__IMPORT int __stdcall ReleaseSemaphore(void *, long, long *);
11581 STB__IMPORT void __stdcall Sleep(STB__DW);
11582 #endif
11583
11584 // necessary to call this when using volatile to order writes/reads
11585 void stb_barrier(void)
11586 {
11587 #ifdef MemoryBarrier
11588 MemoryBarrier();
11589 #else
11590 long temp;
11591 __asm xchg temp,eax;
11592 #endif
11593 }
11594
11595 static void stb__thread_run(void *t)
11596 {
11597 void *res;
11598 stb__thread info = * (stb__thread *) t;
11599 free(t);
11600 res = info.f(info.d);
11601 if (info.return_val)
11602 *info.return_val = res;
11603 if (info.sem != STB_SEMAPHORE_NULL)
11604 stb_sem_release(info.sem);
11605 }
11606
11607 static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11608 {
11609 #ifdef _MT
11610 #if defined(STB_FASTMALLOC) && !defined(STB_FASTMALLOC_ITS_OKAY_I_ONLY_MALLOC_IN_ONE_THREAD)
11611 stb_fatal("Error! Cannot use STB_FASTMALLOC with threads.\n");
11612 return STB_THREAD_NULL;
11613 #else
11614 unsigned long id;
11615 stb__thread *data = (stb__thread *) malloc(sizeof(*data));
11616 if (!data) return NULL;
11617 stb__threadmutex_init();
11618 data->f = f;
11619 data->d = d;
11620 data->return_val = return_code;
11621 data->sem = rel;
11622 id = _beginthread(stb__thread_run, 0, data);
11623 if (id == -1) return NULL;
11624 return (void *) id;
11625 #endif
11626 #else
11627 #ifdef STB_NO_STB_STRINGS
11628 stb_fatal("Invalid compilation");
11629 #else
11630 stb_fatal("Must compile mult-threaded to use stb_thread/stb_work.");
11631 #endif
11632 return NULL;
11633 #endif
11634 }
11635
11636 // trivial win32 wrappers
11637 void stb_destroy_thread(stb_thread t) { TerminateThread(t,0); }
11638 stb_semaphore stb_sem_new(int maxv) {return CreateSemaphoreA(NULL,0,maxv,NULL); }
11639 stb_semaphore stb_sem_new_extra(int maxv,int start){return CreateSemaphoreA(NULL,start,maxv,NULL); }
11640 void stb_sem_delete(stb_semaphore s) { if (s != NULL) CloseHandle(s); }
11641 void stb_sem_waitfor(stb_semaphore s) { WaitForSingleObject(s, 0xffffffff); } // INFINITE
11642 void stb_sem_release(stb_semaphore s) { ReleaseSemaphore(s,1,NULL); }
11643 static void stb__thread_sleep(int ms) { Sleep(ms); }
11644
11645 #ifndef _WINDOWS_
11646 STB__IMPORT int __stdcall GetProcessAffinityMask(void *, STB__DW *, STB__DW *);
11647 STB__IMPORT void * __stdcall GetCurrentProcess(void);
11648 STB__IMPORT int __stdcall SetProcessAffinityMask(void *, STB__DW);
11649 #endif
11650
11651 int stb_processor_count(void)
11652 {
11653 unsigned long proc,sys;
11654 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11655 return stb_bitcount(proc);
11656 }
11657
11658 void stb_force_uniprocessor(void)
11659 {
11660 unsigned long proc,sys;
11661 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11662 if (stb_bitcount(proc) > 1) {
11663 int z;
11664 for (z=0; z < 32; ++z)
11665 if (proc & (1 << z))
11666 break;
11667 if (z < 32) {
11668 proc = 1 << z;
11669 SetProcessAffinityMask(GetCurrentProcess(), proc);
11670 }
11671 }
11672 }
11673
11674 #ifdef _WINDOWS_
11675 #define STB_MUTEX_NATIVE
11676 void *stb_mutex_new(void)
11677 {
11678 CRITICAL_SECTION *p = (CRITICAL_SECTION *) malloc(sizeof(*p));
11679 if (p)
11680 #if _WIN32_WINNT >= 0x0500
11681 InitializeCriticalSectionAndSpinCount(p, 500);
11682 #else
11683 InitializeCriticalSection(p);
11684 #endif
11685 return p;
11686 }
11687
11688 void stb_mutex_delete(void *p)
11689 {
11690 if (p) {
11691 DeleteCriticalSection((CRITICAL_SECTION *) p);
11692 free(p);
11693 }
11694 }
11695
11696 void stb_mutex_begin(void *p)
11697 {
11698 stb__wait(500);
11699 if (p)
11700 EnterCriticalSection((CRITICAL_SECTION *) p);
11701 }
11702
11703 void stb_mutex_end(void *p)
11704 {
11705 if (p)
11706 LeaveCriticalSection((CRITICAL_SECTION *) p);
11707 stb__wait(500);
11708 }
11709 #endif // _WINDOWS_
11710
11711 #if 0
11712 // for future reference,
11713 // InterlockedCompareExchange for x86:
11714 int cas64_mp(void * dest, void * xcmp, void * xxchg) {
11715 __asm
11716 {
11717 mov esi, [xxchg] ; exchange
11718 mov ebx, [esi + 0]
11719 mov ecx, [esi + 4]
11720
11721 mov esi, [xcmp] ; comparand
11722 mov eax, [esi + 0]
11723 mov edx, [esi + 4]
11724
11725 mov edi, [dest] ; destination
11726 lock cmpxchg8b [edi]
11727 jz yyyy;
11728
11729 mov [esi + 0], eax;
11730 mov [esi + 4], edx;
11731
11732 yyyy:
11733 xor eax, eax;
11734 setz al;
11735 };
11736
11737 inline unsigned __int64 _InterlockedCompareExchange64(volatile unsigned __int64 *dest
11738 ,unsigned __int64 exchange
11739 ,unsigned __int64 comperand)
11740 {
11741 //value returned in eax::edx
11742 __asm {
11743 lea esi,comperand;
11744 lea edi,exchange;
11745
11746 mov eax,[esi];
11747 mov edx,4[esi];
11748 mov ebx,[edi];
11749 mov ecx,4[edi];
11750 mov esi,dest;
11751 lock CMPXCHG8B [esi];
11752 }
11753 #endif // #if 0
11754
11755 #endif // _WIN32
11756
11757 stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11758 {
11759 return stb_create_thread_raw(f,d,return_code,rel);
11760 }
11761
11762 stb_thread stb_create_thread(stb_thread_func f, void *d)
11763 {
11764 return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL);
11765 }
11766
11767 // mutex implemented by wrapping semaphore
11768 #ifndef STB_MUTEX_NATIVE
11769 stb_mutex stb_mutex_new(void) { return stb_sem_new_extra(1,1); }
11770 void stb_mutex_delete(stb_mutex m) { stb_sem_delete (m); }
11771 void stb_mutex_begin(stb_mutex m) { stb__wait(500); if (m) stb_sem_waitfor(m); }
11772 void stb_mutex_end(stb_mutex m) { if (m) stb_sem_release(m); stb__wait(500); }
11773 #endif
11774
11775 // thread merge operation
11776 struct stb__sync
11777 {
11778 int target; // target number of threads to hit it
11779 int sofar; // total threads that hit it
11780 int waiting; // total threads waiting
11781
11782 stb_mutex start; // mutex to prevent starting again before finishing previous
11783 stb_mutex mutex; // mutex while tweaking state
11784 stb_semaphore release; // semaphore wake up waiting threads
11785 // we have to wake them up one at a time, rather than using a single release
11786 // call, because win32 semaphores don't let you dynamically change the max count!
11787 };
11788
11789 stb_sync stb_sync_new(void)
11790 {
11791 stb_sync s = (stb_sync) malloc(sizeof(*s));
11792 if (!s) return s;
11793
11794 s->target = s->sofar = s->waiting = 0;
11795 s->mutex = stb_mutex_new();
11796 s->start = stb_mutex_new();
11797 s->release = stb_sem_new(1);
11798 if (s->mutex == STB_MUTEX_NULL || s->release == STB_SEMAPHORE_NULL || s->start == STB_MUTEX_NULL) {
11799 stb_mutex_delete(s->mutex);
11800 stb_mutex_delete(s->mutex);
11801 stb_sem_delete(s->release);
11802 free(s);
11803 return NULL;
11804 }
11805 return s;
11806 }
11807
11808 void stb_sync_delete(stb_sync s)
11809 {
11810 if (s->waiting) {
11811 // it's bad to delete while there are threads waiting!
11812 // shall we wait for them to reach, or just bail? just bail
11813 assert(0);
11814 }
11815 stb_mutex_delete(s->mutex);
11816 stb_mutex_delete(s->release);
11817 free(s);
11818 }
11819
11820 int stb_sync_set_target(stb_sync s, int count)
11821 {
11822 // don't allow setting a target until the last one is fully released;
11823 // note that this can lead to inefficient pipelining, and maybe we'd
11824 // be better off ping-ponging between two internal syncs?
11825 // I tried seeing how often this happened using TryEnterCriticalSection
11826 // and could _never_ get it to happen in imv(stb), even with more threads
11827 // than processors. So who knows!
11828 stb_mutex_begin(s->start);
11829
11830 // this mutex is pointless, since it's not valid for threads
11831 // to call reach() before anyone calls set_target() anyway
11832 stb_mutex_begin(s->mutex);
11833
11834 assert(s->target == 0); // enforced by start mutex
11835 s->target = count;
11836 s->sofar = 0;
11837 s->waiting = 0;
11838 stb_mutex_end(s->mutex);
11839 return STB_TRUE;
11840 }
11841
11842 void stb__sync_release(stb_sync s)
11843 {
11844 if (s->waiting)
11845 stb_sem_release(s->release);
11846 else {
11847 s->target = 0;
11848 stb_mutex_end(s->start);
11849 }
11850 }
11851
11852 int stb_sync_reach(stb_sync s)
11853 {
11854 int n;
11855 stb_mutex_begin(s->mutex);
11856 assert(s->sofar < s->target);
11857 n = ++s->sofar; // record this value to avoid possible race if we did 'return s->sofar';
11858 if (s->sofar == s->target)
11859 stb__sync_release(s);
11860 stb_mutex_end(s->mutex);
11861 return n;
11862 }
11863
11864 void stb_sync_reach_and_wait(stb_sync s)
11865 {
11866 stb_mutex_begin(s->mutex);
11867 assert(s->sofar < s->target);
11868 ++s->sofar;
11869 if (s->sofar == s->target) {
11870 stb__sync_release(s);
11871 stb_mutex_end(s->mutex);
11872 } else {
11873 ++s->waiting; // we're waiting, so one more waiter
11874 stb_mutex_end(s->mutex); // release the mutex to other threads
11875
11876 stb_sem_waitfor(s->release); // wait for merge completion
11877
11878 stb_mutex_begin(s->mutex); // on merge completion, grab the mutex
11879 --s->waiting; // we're done waiting
11880 stb__sync_release(s); // restart the next waiter
11881 stb_mutex_end(s->mutex); // and now we're done
11882 // this ends the same as the first case, but it's a lot
11883 // clearer to understand without sharing the code
11884 }
11885 }
11886
11887 struct stb__threadqueue
11888 {
11889 stb_mutex add, remove;
11890 stb_semaphore nonempty, nonfull;
11891 int head_blockers; // number of threads blocking--used to know whether to release(avail)
11892 int tail_blockers;
11893 int head, tail, array_size, growable;
11894 int item_size;
11895 char *data;
11896 };
11897
11898 static int stb__tq_wrap(volatile stb_threadqueue *z, int p)
11899 {
11900 if (p == z->array_size)
11901 return p - z->array_size;
11902 else
11903 return p;
11904 }
11905
11906 int stb__threadq_get_raw(stb_threadqueue *tq2, void *output, int block)
11907 {
11908 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11909 if (tq->head == tq->tail && !block) return 0;
11910
11911 stb_mutex_begin(tq->remove);
11912
11913 while (tq->head == tq->tail) {
11914 if (!block) {
11915 stb_mutex_end(tq->remove);
11916 return 0;
11917 }
11918 ++tq->head_blockers;
11919 stb_mutex_end(tq->remove);
11920
11921 stb_sem_waitfor(tq->nonempty);
11922
11923 stb_mutex_begin(tq->remove);
11924 --tq->head_blockers;
11925 }
11926
11927 memcpy(output, tq->data + tq->head*tq->item_size, tq->item_size);
11928 stb_barrier();
11929 tq->head = stb__tq_wrap(tq, tq->head+1);
11930
11931 stb_sem_release(tq->nonfull);
11932 if (tq->head_blockers) // can't check if actually non-empty due to race?
11933 stb_sem_release(tq->nonempty); // if there are other blockers, wake one
11934
11935 stb_mutex_end(tq->remove);
11936 return STB_TRUE;
11937 }
11938
11939 int stb__threadq_grow(volatile stb_threadqueue *tq)
11940 {
11941 int n;
11942 char *p;
11943 assert(tq->remove != STB_MUTEX_NULL); // must have this to allow growth!
11944 stb_mutex_begin(tq->remove);
11945
11946 n = tq->array_size * 2;
11947 p = (char *) realloc(tq->data, n * tq->item_size);
11948 if (p == NULL) {
11949 stb_mutex_end(tq->remove);
11950 stb_mutex_end(tq->add);
11951 return STB_FALSE;
11952 }
11953 if (tq->tail < tq->head) {
11954 memcpy(p + tq->array_size * tq->item_size, p, tq->tail * tq->item_size);
11955 tq->tail += tq->array_size;
11956 }
11957 tq->data = p;
11958 tq->array_size = n;
11959
11960 stb_mutex_end(tq->remove);
11961 return STB_TRUE;
11962 }
11963
11964 int stb__threadq_add_raw(stb_threadqueue *tq2, void *input, int block)
11965 {
11966 int tail,pos;
11967 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11968 stb_mutex_begin(tq->add);
11969 for(;;) {
11970 pos = tq->tail;
11971 tail = stb__tq_wrap(tq, pos+1);
11972 if (tail != tq->head) break;
11973
11974 // full
11975 if (tq->growable) {
11976 if (!stb__threadq_grow(tq)) {
11977 stb_mutex_end(tq->add);
11978 return STB_FALSE; // out of memory
11979 }
11980 } else if (!block) {
11981 stb_mutex_end(tq->add);
11982 return STB_FALSE;
11983 } else {
11984 ++tq->tail_blockers;
11985 stb_mutex_end(tq->add);
11986
11987 stb_sem_waitfor(tq->nonfull);
11988
11989 stb_mutex_begin(tq->add);
11990 --tq->tail_blockers;
11991 }
11992 }
11993 memcpy(tq->data + tq->item_size * pos, input, tq->item_size);
11994 stb_barrier();
11995 tq->tail = tail;
11996 stb_sem_release(tq->nonempty);
11997 if (tq->tail_blockers) // can't check if actually non-full due to race?
11998 stb_sem_release(tq->nonfull);
11999 stb_mutex_end(tq->add);
12000 return STB_TRUE;
12001 }
12002
12003 int stb_threadq_length(stb_threadqueue *tq2)
12004 {
12005 int a,b,n;
12006 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
12007 stb_mutex_begin(tq->add);
12008 a = tq->head;
12009 b = tq->tail;
12010 n = tq->array_size;
12011 stb_mutex_end(tq->add);
12012 if (a > b) b += n;
12013 return b-a;
12014 }
12015
12016 int stb_threadq_get(stb_threadqueue *tq, void *output)
12017 {
12018 return stb__threadq_get_raw(tq, output, STB_FALSE);
12019 }
12020
12021 void stb_threadq_get_block(stb_threadqueue *tq, void *output)
12022 {
12023 stb__threadq_get_raw(tq, output, STB_TRUE);
12024 }
12025
12026 int stb_threadq_add(stb_threadqueue *tq, void *input)
12027 {
12028 return stb__threadq_add_raw(tq, input, STB_FALSE);
12029 }
12030
12031 int stb_threadq_add_block(stb_threadqueue *tq, void *input)
12032 {
12033 return stb__threadq_add_raw(tq, input, STB_TRUE);
12034 }
12035
12036 void stb_threadq_delete(stb_threadqueue *tq)
12037 {
12038 if (tq) {
12039 free(tq->data);
12040 stb_mutex_delete(tq->add);
12041 stb_mutex_delete(tq->remove);
12042 stb_sem_delete(tq->nonempty);
12043 stb_sem_delete(tq->nonfull);
12044 free(tq);
12045 }
12046 }
12047
12048 #define STB_THREADQUEUE_DYNAMIC 0
12049 stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove)
12050 {
12051 int error=0;
12052 stb_threadqueue *tq = (stb_threadqueue *) malloc(sizeof(*tq));
12053 if (tq == NULL) return NULL;
12054
12055 if (num_items == STB_THREADQUEUE_DYNAMIC) {
12056 tq->growable = STB_TRUE;
12057 num_items = 32;
12058 } else
12059 tq->growable = STB_FALSE;
12060
12061 tq->item_size = item_size;
12062 tq->array_size = num_items+1;
12063
12064 tq->add = tq->remove = STB_MUTEX_NULL;
12065 tq->nonempty = tq->nonfull = STB_SEMAPHORE_NULL;
12066 tq->data = NULL;
12067 if (many_add)
12068 { tq->add = stb_mutex_new(); if (tq->add == STB_MUTEX_NULL) goto error; }
12069 if (many_remove || tq->growable)
12070 { tq->remove = stb_mutex_new(); if (tq->remove == STB_MUTEX_NULL) goto error; }
12071 tq->nonempty = stb_sem_new(1); if (tq->nonempty == STB_SEMAPHORE_NULL) goto error;
12072 tq->nonfull = stb_sem_new(1); if (tq->nonfull == STB_SEMAPHORE_NULL) goto error;
12073 tq->data = (char *) malloc(tq->item_size * tq->array_size);
12074 if (tq->data == NULL) goto error;
12075
12076 tq->head = tq->tail = 0;
12077 tq->head_blockers = tq->tail_blockers = 0;
12078
12079 return tq;
12080
12081 error:
12082 stb_threadq_delete(tq);
12083 return NULL;
12084 }
12085
12086 typedef struct
12087 {
12088 stb_thread_func f;
12089 void *d;
12090 volatile void **retval;
12091 stb_sync sync;
12092 } stb__workinfo;
12093
12094 //static volatile stb__workinfo *stb__work;
12095
12096 struct stb__workqueue
12097 {
12098 int numthreads;
12099 stb_threadqueue *tq;
12100 };
12101
12102 static stb_workqueue *stb__work_global;
12103
12104 static void *stb__thread_workloop(void *p)
12105 {
12106 volatile stb_workqueue *q = (volatile stb_workqueue *) p;
12107 for(;;) {
12108 void *z;
12109 stb__workinfo w;
12110 stb_threadq_get_block(q->tq, &w);
12111 if (w.f == NULL) // null work is a signal to end the thread
12112 return NULL;
12113 z = w.f(w.d);
12114 if (w.retval) { stb_barrier(); *w.retval = z; }
12115 if (w.sync != STB_SYNC_NULL) stb_sync_reach(w.sync);
12116 }
12117 }
12118
12119 stb_workqueue *stb_workq_new(int num_threads, int max_units)
12120 {
12121 return stb_workq_new_flags(num_threads, max_units, 0,0);
12122 }
12123
12124 stb_workqueue *stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex)
12125 {
12126 stb_workqueue *q = (stb_workqueue *) malloc(sizeof(*q));
12127 if (q == NULL) return NULL;
12128 q->tq = stb_threadq_new(sizeof(stb__workinfo), max_units, !no_add_mutex, !no_remove_mutex);
12129 if (q->tq == NULL) { free(q); return NULL; }
12130 q->numthreads = 0;
12131 stb_workq_numthreads(q, numthreads);
12132 return q;
12133 }
12134
12135 void stb_workq_delete(stb_workqueue *q)
12136 {
12137 while (stb_workq_length(q) != 0)
12138 stb__thread_sleep(1);
12139 stb_threadq_delete(q->tq);
12140 free(q);
12141 }
12142
12143 static int stb__work_maxitems = STB_THREADQUEUE_DYNAMIC;
12144
12145 static void stb_work_init(int num_threads)
12146 {
12147 if (stb__work_global == NULL) {
12148 stb__threadmutex_init();
12149 stb_mutex_begin(stb__workmutex);
12150 stb_barrier();
12151 if (*(stb_workqueue * volatile *) &stb__work_global == NULL)
12152 stb__work_global = stb_workq_new(num_threads, stb__work_maxitems);
12153 stb_mutex_end(stb__workmutex);
12154 }
12155 }
12156
12157 static int stb__work_raw(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12158 {
12159 stb__workinfo w;
12160 if (q == NULL) {
12161 stb_work_init(1);
12162 q = stb__work_global;
12163 }
12164 w.f = f;
12165 w.d = d;
12166 w.retval = return_code;
12167 w.sync = rel;
12168 return stb_threadq_add(q->tq, &w);
12169 }
12170
12171 int stb_workq_length(stb_workqueue *q)
12172 {
12173 return stb_threadq_length(q->tq);
12174 }
12175
12176 int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code)
12177 {
12178 if (f == NULL) return 0;
12179 return stb_workq_reach(q, f, d, return_code, NULL);
12180 }
12181
12182 int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12183 {
12184 if (f == NULL) return 0;
12185 return stb__work_raw(q, f, d, return_code, rel);
12186 }
12187
12188 static void stb__workq_numthreads(stb_workqueue *q, int n)
12189 {
12190 while (q->numthreads < n) {
12191 stb_create_thread(stb__thread_workloop, q);
12192 ++q->numthreads;
12193 }
12194 while (q->numthreads > n) {
12195 stb__work_raw(q, NULL, NULL, NULL, NULL);
12196 --q->numthreads;
12197 }
12198 }
12199
12200 void stb_workq_numthreads(stb_workqueue *q, int n)
12201 {
12202 stb_mutex_begin(stb__threadmutex);
12203 stb__workq_numthreads(q,n);
12204 stb_mutex_end(stb__threadmutex);
12205 }
12206
12207 int stb_work_maxunits(int n)
12208 {
12209 if (stb__work_global == NULL) {
12210 stb__work_maxitems = n;
12211 stb_work_init(1);
12212 }
12213 return stb__work_maxitems;
12214 }
12215
12216 int stb_work(stb_thread_func f, void *d, volatile void **return_code)
12217 {
12218 return stb_workq(stb__work_global, f,d,return_code);
12219 }
12220
12221 int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12222 {
12223 return stb_workq_reach(stb__work_global, f,d,return_code,rel);
12224 }
12225
12226 void stb_work_numthreads(int n)
12227 {
12228 if (stb__work_global == NULL)
12229 stb_work_init(n);
12230 else
12231 stb_workq_numthreads(stb__work_global, n);
12232 }
12233 #endif // STB_DEFINE
12234
12235
12236 //////////////////////////////////////////////////////////////////////////////
12237 //
12238 // Background disk I/O
12239 //
12240 //
12241
12242 #define STB_BGIO_READ_ALL (-1)
12243 STB_EXTERN int stb_bgio_read (char *filename, int offset, int len, stb_uchar **result, int *olen);
12244 STB_EXTERN int stb_bgio_readf (FILE *f , int offset, int len, stb_uchar **result, int *olen);
12245 STB_EXTERN int stb_bgio_read_to (char *filename, int offset, int len, stb_uchar *buffer, int *olen);
12246 STB_EXTERN int stb_bgio_readf_to(FILE *f , int offset, int len, stb_uchar *buffer, int *olen);
12247
12248 typedef struct
12249 {
12250 int have_data;
12251 int is_valid;
12252 int is_dir;
12253 time_t filetime;
12254 stb_int64 filesize;
12255 } stb_bgstat;
12256
12257 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result);
12258
12259 #ifdef STB_DEFINE
12260
12261 static stb_workqueue *stb__diskio;
12262 static stb_mutex stb__diskio_mutex;
12263
12264 void stb_thread_cleanup(void)
12265 {
12266 if (stb__work_global) stb_workq_delete(stb__work_global); stb__work_global = NULL;
12267 if (stb__threadmutex) stb_mutex_delete(stb__threadmutex); stb__threadmutex = NULL;
12268 if (stb__workmutex) stb_mutex_delete(stb__workmutex); stb__workmutex = NULL;
12269 if (stb__diskio) stb_workq_delete(stb__diskio); stb__diskio = NULL;
12270 if (stb__diskio_mutex)stb_mutex_delete(stb__diskio_mutex);stb__diskio_mutex= NULL;
12271 }
12272
12273
12274 typedef struct
12275 {
12276 char *filename;
12277 FILE *f;
12278 int offset;
12279 int len;
12280
12281 stb_bgstat *stat_out;
12282 stb_uchar *output;
12283 stb_uchar **result;
12284 int *len_output;
12285 int *flag;
12286 } stb__disk_command;
12287
12288 #define STB__MAX_DISK_COMMAND 100
12289 static stb__disk_command stb__dc_queue[STB__MAX_DISK_COMMAND];
12290 static int stb__dc_offset;
12291
12292 void stb__io_init(void)
12293 {
12294 if (!stb__diskio) {
12295 stb__threadmutex_init();
12296 stb_mutex_begin(stb__threadmutex);
12297 stb_barrier();
12298 if (*(stb_thread * volatile *) &stb__diskio == NULL) {
12299 stb__diskio_mutex = stb_mutex_new();
12300 // use many threads so OS can try to schedule seeks
12301 stb__diskio = stb_workq_new_flags(16,STB__MAX_DISK_COMMAND,STB_FALSE,STB_FALSE);
12302 }
12303 stb_mutex_end(stb__threadmutex);
12304 }
12305 }
12306
12307 static void * stb__io_error(stb__disk_command *dc)
12308 {
12309 if (dc->len_output) *dc->len_output = 0;
12310 if (dc->result) *dc->result = NULL;
12311 if (dc->flag) *dc->flag = -1;
12312 return NULL;
12313 }
12314
12315 static void * stb__io_task(void *p)
12316 {
12317 stb__disk_command *dc = (stb__disk_command *) p;
12318 int len;
12319 FILE *f;
12320 stb_uchar *buf;
12321
12322 if (dc->stat_out) {
12323 struct _stati64 s;
12324 if (!_stati64(dc->filename, &s)) {
12325 dc->stat_out->filesize = s.st_size;
12326 dc->stat_out->filetime = s.st_mtime;
12327 dc->stat_out->is_dir = s.st_mode & _S_IFDIR;
12328 dc->stat_out->is_valid = (s.st_mode & _S_IFREG) || dc->stat_out->is_dir;
12329 } else
12330 dc->stat_out->is_valid = 0;
12331 stb_barrier();
12332 dc->stat_out->have_data = 1;
12333 free(dc->filename);
12334 return 0;
12335 }
12336 if (dc->f) {
12337 #ifdef WIN32
12338 f = _fdopen(_dup(_fileno(dc->f)), "rb");
12339 #else
12340 f = fdopen(dup(fileno(dc->f)), "rb");
12341 #endif
12342 if (!f)
12343 return stb__io_error(dc);
12344 } else {
12345 f = fopen(dc->filename, "rb");
12346 free(dc->filename);
12347 if (!f)
12348 return stb__io_error(dc);
12349 }
12350
12351 len = dc->len;
12352 if (len < 0) {
12353 fseek(f, 0, SEEK_END);
12354 len = ftell(f) - dc->offset;
12355 }
12356
12357 if (fseek(f, dc->offset, SEEK_SET)) {
12358 fclose(f);
12359 return stb__io_error(dc);
12360 }
12361
12362 if (dc->output)
12363 buf = dc->output;
12364 else {
12365 buf = (stb_uchar *) malloc(len);
12366 if (buf == NULL) {
12367 fclose(f);
12368 return stb__io_error(dc);
12369 }
12370 }
12371
12372 len = fread(buf, 1, len, f);
12373 fclose(f);
12374 if (dc->len_output) *dc->len_output = len;
12375 if (dc->result) *dc->result = buf;
12376 if (dc->flag) *dc->flag = 1;
12377
12378 return NULL;
12379 }
12380
12381 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)
12382 {
12383 int res;
12384 stb__io_init();
12385 // do memory allocation outside of mutex
12386 if (fname) fname = stb_p_strdup(fname);
12387 stb_mutex_begin(stb__diskio_mutex);
12388 {
12389 stb__disk_command *dc = &stb__dc_queue[stb__dc_offset];
12390 dc->filename = fname;
12391 dc->f = f;
12392 dc->offset = off;
12393 dc->len = len;
12394 dc->output = out;
12395 dc->result = result;
12396 dc->len_output = olen;
12397 dc->flag = flag;
12398 dc->stat_out = stat;
12399 res = stb_workq(stb__diskio, stb__io_task, dc, NULL);
12400 if (res)
12401 stb__dc_offset = (stb__dc_offset + 1 == STB__MAX_DISK_COMMAND ? 0 : stb__dc_offset+1);
12402 }
12403 stb_mutex_end(stb__diskio_mutex);
12404 return res;
12405 }
12406
12407 int stb_bgio_read(char *filename, int offset, int len, stb_uchar **result, int *olen)
12408 {
12409 return stb__io_add(filename,NULL,offset,len,NULL,result,olen,NULL,NULL);
12410 }
12411
12412 int stb_bgio_readf(FILE *f, int offset, int len, stb_uchar **result, int *olen)
12413 {
12414 return stb__io_add(NULL,f,offset,len,NULL,result,olen,NULL,NULL);
12415 }
12416
12417 int stb_bgio_read_to(char *filename, int offset, int len, stb_uchar *buffer, int *olen)
12418 {
12419 return stb__io_add(filename,NULL,offset,len,buffer,NULL,olen,NULL,NULL);
12420 }
12421
12422 int stb_bgio_readf_to(FILE *f, int offset, int len, stb_uchar *buffer, int *olen)
12423 {
12424 return stb__io_add(NULL,f,offset,len,buffer,NULL,olen,NULL,NULL);
12425 }
12426
12427 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result)
12428 {
12429 result->have_data = 0;
12430 return stb__io_add(filename,NULL,0,0,0,NULL,0,NULL, result);
12431 }
12432 #endif
12433 #endif
12434
12435
12436
12437 //////////////////////////////////////////////////////////////////////////////
12438 //
12439 // Fast malloc implementation
12440 //
12441 // This is a clone of TCMalloc, but without the thread support.
12442 // 1. large objects are allocated directly, page-aligned
12443 // 2. small objects are allocated in homogeonous heaps, 0 overhead
12444 //
12445 // We keep an allocation table for pages a la TCMalloc. This would
12446 // require 4MB for the entire address space, but we only allocate
12447 // the parts that are in use. The overhead from using homogenous heaps
12448 // everywhere is 3MB. (That is, if you allocate 1 object of each size,
12449 // you'll use 3MB.)
12450
12451 #if defined(STB_DEFINE) && ((defined(_WIN32) && !defined(_M_AMD64)) || defined(STB_FASTMALLOC))
12452
12453 #ifdef _WIN32
12454 #ifndef _WINDOWS_
12455 #ifndef STB__IMPORT
12456 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
12457 #define STB__DW unsigned long
12458 #endif
12459 STB__IMPORT void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
12460 STB__IMPORT int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
12461 #endif
12462 #define stb__alloc_pages_raw(x) (stb_uint32) VirtualAlloc(NULL, (x), 0x3000, 0x04)
12463 #define stb__dealloc_pages_raw(p) VirtualFree((void *) p, 0, 0x8000)
12464 #else
12465 #error "Platform not currently supported"
12466 #endif
12467
12468 typedef struct stb__span
12469 {
12470 int start, len;
12471 struct stb__span *next, *prev;
12472 void *first_free;
12473 unsigned short list; // 1..256 free; 257..511 sizeclass; 0=large block
12474 short allocations; // # outstanding allocations for sizeclass
12475 } stb__span; // 24
12476
12477 static stb__span **stb__span_for_page;
12478 static int stb__firstpage, stb__lastpage;
12479 static void stb__update_page_range(int first, int last)
12480 {
12481 stb__span **sfp;
12482 int i, f,l;
12483 if (first >= stb__firstpage && last <= stb__lastpage) return;
12484 if (stb__span_for_page == NULL) {
12485 f = first;
12486 l = f+stb_max(last-f, 16384);
12487 l = stb_min(l, 1<<20);
12488 } else if (last > stb__lastpage) {
12489 f = stb__firstpage;
12490 l = f + (stb__lastpage - f) * 2;
12491 l = stb_clamp(last, l,1<<20);
12492 } else {
12493 l = stb__lastpage;
12494 f = l - (l - stb__firstpage) * 2;
12495 f = stb_clamp(f, 0,first);
12496 }
12497 sfp = (stb__span **) stb__alloc_pages_raw(sizeof(void *) * (l-f));
12498 for (i=f; i < stb__firstpage; ++i) sfp[i - f] = NULL;
12499 for ( ; i < stb__lastpage ; ++i) sfp[i - f] = stb__span_for_page[i - stb__firstpage];
12500 for ( ; i < l ; ++i) sfp[i - f] = NULL;
12501 if (stb__span_for_page) stb__dealloc_pages_raw(stb__span_for_page);
12502 stb__firstpage = f;
12503 stb__lastpage = l;
12504 stb__span_for_page = sfp;
12505 }
12506
12507 static stb__span *stb__span_free=NULL;
12508 static stb__span *stb__span_first, *stb__span_end;
12509 static stb__span *stb__span_alloc(void)
12510 {
12511 stb__span *s = stb__span_free;
12512 if (s)
12513 stb__span_free = s->next;
12514 else {
12515 if (!stb__span_first) {
12516 stb__span_first = (stb__span *) stb__alloc_pages_raw(65536);
12517 if (stb__span_first == NULL) return NULL;
12518 stb__span_end = stb__span_first + (65536 / sizeof(stb__span));
12519 }
12520 s = stb__span_first++;
12521 if (stb__span_first == stb__span_end) stb__span_first = NULL;
12522 }
12523 return s;
12524 }
12525
12526 static stb__span *stb__spanlist[512];
12527
12528 static void stb__spanlist_unlink(stb__span *s)
12529 {
12530 if (s->prev)
12531 s->prev->next = s->next;
12532 else {
12533 int n = s->list;
12534 assert(stb__spanlist[n] == s);
12535 stb__spanlist[n] = s->next;
12536 }
12537 if (s->next)
12538 s->next->prev = s->prev;
12539 s->next = s->prev = NULL;
12540 s->list = 0;
12541 }
12542
12543 static void stb__spanlist_add(int n, stb__span *s)
12544 {
12545 s->list = n;
12546 s->next = stb__spanlist[n];
12547 s->prev = NULL;
12548 stb__spanlist[n] = s;
12549 if (s->next) s->next->prev = s;
12550 }
12551
12552 #define stb__page_shift 12
12553 #define stb__page_size (1 << stb__page_shift)
12554 #define stb__page_number(x) ((x) >> stb__page_shift)
12555 #define stb__page_address(x) ((x) << stb__page_shift)
12556
12557 static void stb__set_span_for_page(stb__span *s)
12558 {
12559 int i;
12560 for (i=0; i < s->len; ++i)
12561 stb__span_for_page[s->start + i - stb__firstpage] = s;
12562 }
12563
12564 static stb__span *stb__coalesce(stb__span *a, stb__span *b)
12565 {
12566 assert(a->start + a->len == b->start);
12567 if (a->list) stb__spanlist_unlink(a);
12568 if (b->list) stb__spanlist_unlink(b);
12569 a->len += b->len;
12570 b->len = 0;
12571 b->next = stb__span_free;
12572 stb__span_free = b;
12573 stb__set_span_for_page(a);
12574 return a;
12575 }
12576
12577 static void stb__free_span(stb__span *s)
12578 {
12579 stb__span *n = NULL;
12580 if (s->start > stb__firstpage) {
12581 n = stb__span_for_page[s->start-1 - stb__firstpage];
12582 if (n && n->allocations == -2 && n->start + n->len == s->start) s = stb__coalesce(n,s);
12583 }
12584 if (s->start + s->len < stb__lastpage) {
12585 n = stb__span_for_page[s->start + s->len - stb__firstpage];
12586 if (n && n->allocations == -2 && s->start + s->len == n->start) s = stb__coalesce(s,n);
12587 }
12588 s->allocations = -2;
12589 stb__spanlist_add(s->len > 256 ? 256 : s->len, s);
12590 }
12591
12592 static stb__span *stb__alloc_pages(int num)
12593 {
12594 stb__span *s = stb__span_alloc();
12595 int p;
12596 if (!s) return NULL;
12597 p = stb__alloc_pages_raw(num << stb__page_shift);
12598 if (p == 0) { s->next = stb__span_free; stb__span_free = s; return 0; }
12599 assert(stb__page_address(stb__page_number(p)) == p);
12600 p = stb__page_number(p);
12601 stb__update_page_range(p, p+num);
12602 s->start = p;
12603 s->len = num;
12604 s->next = NULL;
12605 s->prev = NULL;
12606 stb__set_span_for_page(s);
12607 return s;
12608 }
12609
12610 static stb__span *stb__alloc_span(int pagecount)
12611 {
12612 int i;
12613 stb__span *p = NULL;
12614 for(i=pagecount; i < 256; ++i)
12615 if (stb__spanlist[i]) {
12616 p = stb__spanlist[i];
12617 break;
12618 }
12619 if (!p) {
12620 p = stb__spanlist[256];
12621 while (p && p->len < pagecount)
12622 p = p->next;
12623 }
12624 if (!p) {
12625 p = stb__alloc_pages(pagecount < 16 ? 16 : pagecount);
12626 if (p == NULL) return 0;
12627 } else
12628 stb__spanlist_unlink(p);
12629
12630 if (p->len > pagecount) {
12631 stb__span *q = stb__span_alloc();
12632 if (q) {
12633 q->start = p->start + pagecount;
12634 q->len = p->len - pagecount;
12635 p->len = pagecount;
12636 for (i=0; i < q->len; ++i)
12637 stb__span_for_page[q->start+i - stb__firstpage] = q;
12638 stb__spanlist_add(q->len > 256 ? 256 : q->len, q);
12639 }
12640 }
12641 return p;
12642 }
12643
12644 #define STB__MAX_SMALL_SIZE 32768
12645 #define STB__MAX_SIZE_CLASSES 256
12646
12647 static unsigned char stb__class_base[32];
12648 static unsigned char stb__class_shift[32];
12649 static unsigned char stb__pages_for_class[STB__MAX_SIZE_CLASSES];
12650 static int stb__size_for_class[STB__MAX_SIZE_CLASSES];
12651
12652 stb__span *stb__get_nonempty_sizeclass(int c)
12653 {
12654 int s = c + 256, i, size, tsize; // remap to span-list index
12655 char *z;
12656 void *q;
12657 stb__span *p = stb__spanlist[s];
12658 if (p) {
12659 if (p->first_free) return p; // fast path: it's in the first one in list
12660 for (p=p->next; p; p=p->next)
12661 if (p->first_free) {
12662 // move to front for future queries
12663 stb__spanlist_unlink(p);
12664 stb__spanlist_add(s, p);
12665 return p;
12666 }
12667 }
12668 // no non-empty ones, so allocate a new one
12669 p = stb__alloc_span(stb__pages_for_class[c]);
12670 if (!p) return NULL;
12671 // create the free list up front
12672 size = stb__size_for_class[c];
12673 tsize = stb__pages_for_class[c] << stb__page_shift;
12674 i = 0;
12675 z = (char *) stb__page_address(p->start);
12676 q = NULL;
12677 while (i + size <= tsize) {
12678 * (void **) z = q; q = z;
12679 z += size;
12680 i += size;
12681 }
12682 p->first_free = q;
12683 p->allocations = 0;
12684 stb__spanlist_add(s,p);
12685 return p;
12686 }
12687
12688 static int stb__sizeclass(size_t sz)
12689 {
12690 int z = stb_log2_floor(sz); // -1 below to group e.g. 13,14,15,16 correctly
12691 return stb__class_base[z] + ((sz-1) >> stb__class_shift[z]);
12692 }
12693
12694 static void stb__init_sizeclass(void)
12695 {
12696 int i, size, overhead;
12697 int align_shift = 2; // allow 4-byte and 12-byte blocks as well, vs. TCMalloc
12698 int next_class = 1;
12699 int last_log = 0;
12700
12701 for (i = 0; i < align_shift; i++) {
12702 stb__class_base [i] = next_class;
12703 stb__class_shift[i] = align_shift;
12704 }
12705
12706 for (size = 1 << align_shift; size <= STB__MAX_SMALL_SIZE; size += 1 << align_shift) {
12707 i = stb_log2_floor(size);
12708 if (i > last_log) {
12709 if (size == 16) ++align_shift; // switch from 4-byte to 8-byte alignment
12710 else if (size >= 128 && align_shift < 8) ++align_shift;
12711 stb__class_base[i] = next_class - ((size-1) >> align_shift);
12712 stb__class_shift[i] = align_shift;
12713 last_log = i;
12714 }
12715 stb__size_for_class[next_class++] = size;
12716 }
12717
12718 for (i=1; i <= STB__MAX_SMALL_SIZE; ++i)
12719 assert(i <= stb__size_for_class[stb__sizeclass(i)]);
12720
12721 overhead = 0;
12722 for (i = 1; i < next_class; i++) {
12723 int s = stb__size_for_class[i];
12724 size = stb__page_size;
12725 while (size % s > size >> 3)
12726 size += stb__page_size;
12727 stb__pages_for_class[i] = (unsigned char) (size >> stb__page_shift);
12728 overhead += size;
12729 }
12730 assert(overhead < (4 << 20)); // make sure it's under 4MB of overhead
12731 }
12732
12733 #ifdef STB_DEBUG
12734 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12735 #elif defined(STB_FASTMALLOC_INIT)
12736 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12737 #else
12738 #define stb__smemset(a,b,c)
12739 #endif
12740 void *stb_smalloc(size_t sz)
12741 {
12742 stb__span *s;
12743 if (sz == 0) return NULL;
12744 if (stb__size_for_class[1] == 0) stb__init_sizeclass();
12745 if (sz > STB__MAX_SMALL_SIZE) {
12746 s = stb__alloc_span((sz + stb__page_size - 1) >> stb__page_shift);
12747 if (s == NULL) return NULL;
12748 s->list = 0;
12749 s->next = s->prev = NULL;
12750 s->allocations = -32767;
12751 stb__smemset(stb__page_address(s->start), 0xcd, (sz+3)&~3);
12752 return (void *) stb__page_address(s->start);
12753 } else {
12754 void *p;
12755 int c = stb__sizeclass(sz);
12756 s = stb__spanlist[256+c];
12757 if (!s || !s->first_free)
12758 s = stb__get_nonempty_sizeclass(c);
12759 if (s == NULL) return NULL;
12760 p = s->first_free;
12761 s->first_free = * (void **) p;
12762 ++s->allocations;
12763 stb__smemset(p,0xcd, sz);
12764 return p;
12765 }
12766 }
12767
12768 int stb_ssize(void *p)
12769 {
12770 stb__span *s;
12771 if (p == NULL) return 0;
12772 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12773 if (s->list >= 256) {
12774 return stb__size_for_class[s->list - 256];
12775 } else {
12776 assert(s->list == 0);
12777 return s->len << stb__page_shift;
12778 }
12779 }
12780
12781 void stb_sfree(void *p)
12782 {
12783 stb__span *s;
12784 if (p == NULL) return;
12785 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12786 if (s->list >= 256) {
12787 stb__smemset(p, 0xfe, stb__size_for_class[s->list-256]);
12788 * (void **) p = s->first_free;
12789 s->first_free = p;
12790 if (--s->allocations == 0) {
12791 stb__spanlist_unlink(s);
12792 stb__free_span(s);
12793 }
12794 } else {
12795 assert(s->list == 0);
12796 stb__smemset(p, 0xfe, stb_ssize(p));
12797 stb__free_span(s);
12798 }
12799 }
12800
12801 void *stb_srealloc(void *p, size_t sz)
12802 {
12803 size_t cur_size;
12804 if (p == NULL) return stb_smalloc(sz);
12805 if (sz == 0) { stb_sfree(p); return NULL; }
12806 cur_size = stb_ssize(p);
12807 if (sz > cur_size || sz <= (cur_size >> 1)) {
12808 void *q;
12809 if (sz > cur_size && sz < (cur_size << 1)) sz = cur_size << 1;
12810 q = stb_smalloc(sz); if (q == NULL) return NULL;
12811 memcpy(q, p, sz < cur_size ? sz : cur_size);
12812 stb_sfree(p);
12813 return q;
12814 }
12815 return p;
12816 }
12817
12818 void *stb_scalloc(size_t n, size_t sz)
12819 {
12820 void *p;
12821 if (n == 0 || sz == 0) return NULL;
12822 if (stb_log2_ceil(n) + stb_log2_ceil(n) >= 32) return NULL;
12823 p = stb_smalloc(n*sz);
12824 if (p) memset(p, 0, n*sz);
12825 return p;
12826 }
12827
12828 char *stb_sstrdup(char *s)
12829 {
12830 int n = strlen(s);
12831 char *p = (char *) stb_smalloc(n+1);
12832 if (p) stb_p_strcpy_s(p,n+1,s);
12833 return p;
12834 }
12835 #endif // STB_DEFINE
12836
12837
12838
12839 //////////////////////////////////////////////////////////////////////////////
12840 //
12841 // Source code constants
12842 //
12843 // This is a trivial system to let you specify constants in source code,
12844 // then while running you can change the constants.
12845 //
12846 // Note that you can't wrap the #defines, because we need to know their
12847 // names. So we provide a pre-wrapped version without 'STB_' for convenience;
12848 // to request it, #define STB_CONVENIENT_H, yielding:
12849 // KI -- integer
12850 // KU -- unsigned integer
12851 // KF -- float
12852 // KD -- double
12853 // KS -- string constant
12854 //
12855 // Defaults to functioning in debug build, not in release builds.
12856 // To force on, define STB_ALWAYS_H
12857
12858 #ifdef STB_CONVENIENT_H
12859 #define KI(x) STB_I(x)
12860 #define KU(x) STB_UI(x)
12861 #define KF(x) STB_F(x)
12862 #define KD(x) STB_D(x)
12863 #define KS(x) STB_S(x)
12864 #endif
12865
12866 STB_EXTERN void stb_source_path(char *str);
12867 #ifdef STB_DEFINE
12868 char *stb__source_path;
12869 void stb_source_path(char *path)
12870 {
12871 stb__source_path = path;
12872 }
12873
12874 char *stb__get_sourcefile_path(char *file)
12875 {
12876 static char filebuf[512];
12877 if (stb__source_path) {
12878 stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "%s/%s", stb__source_path, file);
12879 if (stb_fexists(filebuf)) return filebuf;
12880 }
12881
12882 if (stb_fexists(file)) return file;
12883
12884 stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "../%s", file);
12885 if (!stb_fexists(filebuf)) return filebuf;
12886
12887 return file;
12888 }
12889 #endif
12890
12891 #define STB_F(x) ((float) STB_H(x))
12892 #define STB_UI(x) ((unsigned int) STB_I(x))
12893
12894 #if !defined(STB_DEBUG) && !defined(STB_ALWAYS_H)
12895 #define STB_D(x) ((double) (x))
12896 #define STB_I(x) ((int) (x))
12897 #define STB_S(x) ((char *) (x))
12898 #else
12899 #define STB_D(x) stb__double_constant(__FILE__, __LINE__-1, (x))
12900 #define STB_I(x) stb__int_constant(__FILE__, __LINE__-1, (x))
12901 #define STB_S(x) stb__string_constant(__FILE__, __LINE__-1, (x))
12902
12903 STB_EXTERN double stb__double_constant(char *file, int line, double x);
12904 STB_EXTERN int stb__int_constant(char *file, int line, int x);
12905 STB_EXTERN char * stb__string_constant(char *file, int line, char *str);
12906
12907 #ifdef STB_DEFINE
12908
12909 enum
12910 {
12911 STB__CTYPE_int,
12912 STB__CTYPE_uint,
12913 STB__CTYPE_float,
12914 STB__CTYPE_double,
12915 STB__CTYPE_string,
12916 };
12917
12918 typedef struct
12919 {
12920 int line;
12921 int type;
12922 union {
12923 int ival;
12924 double dval;
12925 char *sval;
12926 };
12927 } stb__Entry;
12928
12929 typedef struct
12930 {
12931 stb__Entry *entries;
12932 char *filename;
12933 time_t timestamp;
12934 char **file_data;
12935 int file_len;
12936 unsigned short *line_index;
12937 } stb__FileEntry;
12938
12939 static void stb__constant_parse(stb__FileEntry *f, int i)
12940 {
12941 char *s;
12942 int n;
12943 if (!stb_arr_valid(f->entries, i)) return;
12944 n = f->entries[i].line;
12945 if (n >= f->file_len) return;
12946 s = f->file_data[n];
12947 switch (f->entries[i].type) {
12948 case STB__CTYPE_float:
12949 while (*s) {
12950 if (!strncmp(s, "STB_D(", 6)) { s+=6; goto matched_float; }
12951 if (!strncmp(s, "STB_F(", 6)) { s+=6; goto matched_float; }
12952 if (!strncmp(s, "KD(", 3)) { s+=3; goto matched_float; }
12953 if (!strncmp(s, "KF(", 3)) { s+=3; goto matched_float; }
12954 ++s;
12955 }
12956 break;
12957 matched_float:
12958 f->entries[i].dval = strtod(s, NULL);
12959 break;
12960 case STB__CTYPE_int:
12961 while (*s) {
12962 if (!strncmp(s, "STB_I(", 6)) { s+=6; goto matched_int; }
12963 if (!strncmp(s, "STB_UI(", 7)) { s+=7; goto matched_int; }
12964 if (!strncmp(s, "KI(", 3)) { s+=3; goto matched_int; }
12965 if (!strncmp(s, "KU(", 3)) { s+=3; goto matched_int; }
12966 ++s;
12967 }
12968 break;
12969 matched_int: {
12970 int neg=0;
12971 s = stb_skipwhite(s);
12972 while (*s == '-') { neg = !neg; s = stb_skipwhite(s+1); } // handle '- - 5', pointlessly
12973 if (s[0] == '0' && tolower(s[1]) == 'x')
12974 f->entries[i].ival = strtol(s, NULL, 16);
12975 else if (s[0] == '0')
12976 f->entries[i].ival = strtol(s, NULL, 8);
12977 else
12978 f->entries[i].ival = strtol(s, NULL, 10);
12979 if (neg) f->entries[i].ival = -f->entries[i].ival;
12980 break;
12981 }
12982 case STB__CTYPE_string:
12983 // @TODO
12984 break;
12985 }
12986 }
12987
12988 static stb_sdict *stb__constant_file_hash;
12989
12990 stb__Entry *stb__constant_get_entry(char *filename, int line, int type)
12991 {
12992 int i;
12993 stb__FileEntry *f;
12994 if (stb__constant_file_hash == NULL)
12995 stb__constant_file_hash = stb_sdict_new(STB_TRUE);
12996 f = (stb__FileEntry*) stb_sdict_get(stb__constant_file_hash, filename);
12997 if (f == NULL) {
12998 char *s = stb__get_sourcefile_path(filename);
12999 if (s == NULL || !stb_fexists(s)) return 0;
13000 f = (stb__FileEntry *) malloc(sizeof(*f));
13001 f->timestamp = stb_ftimestamp(s);
13002 f->file_data = stb_stringfile(s, &f->file_len);
13003 f->filename = stb_p_strdup(s); // cache the full path
13004 f->entries = NULL;
13005 f->line_index = 0;
13006 stb_arr_setlen(f->line_index, f->file_len);
13007 memset(f->line_index, 0xff, stb_arr_storage(f->line_index));
13008 } else {
13009 time_t t = stb_ftimestamp(f->filename);
13010 if (f->timestamp != t) {
13011 f->timestamp = t;
13012 free(f->file_data);
13013 f->file_data = stb_stringfile(f->filename, &f->file_len);
13014 stb_arr_setlen(f->line_index, f->file_len);
13015 for (i=0; i < stb_arr_len(f->entries); ++i)
13016 stb__constant_parse(f, i);
13017 }
13018 }
13019
13020 if (line >= f->file_len) return 0;
13021
13022 if (f->line_index[line] >= stb_arr_len(f->entries)) {
13023 // need a new entry
13024 int n = stb_arr_len(f->entries);
13025 stb__Entry e;
13026 e.line = line;
13027 if (line < f->file_len)
13028 f->line_index[line] = n;
13029 e.type = type;
13030 stb_arr_push(f->entries, e);
13031 stb__constant_parse(f, n);
13032 }
13033 return f->entries + f->line_index[line];
13034 }
13035
13036 double stb__double_constant(char *file, int line, double x)
13037 {
13038 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_float);
13039 if (!e) return x;
13040 return e->dval;
13041 }
13042
13043 int stb__int_constant(char *file, int line, int x)
13044 {
13045 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_int);
13046 if (!e) return x;
13047 return e->ival;
13048 }
13049
13050 char * stb__string_constant(char *file, int line, char *x)
13051 {
13052 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_string);
13053 if (!e) return x;
13054 return e->sval;
13055 }
13056
13057 #endif // STB_DEFINE
13058 #endif // !STB_DEBUG && !STB_ALWAYS_H
13059
13060
13061 #ifdef STB_STUA
13062 #error "STUA is no longer supported"
13063 //////////////////////////////////////////////////////////////////////////
13064 //
13065 // stua: little scripting language
13066 //
13067 // define STB_STUA to compile it
13068 //
13069 // see http://nothings.org/stb/stb_stua.html for documentation
13070 //
13071 // basic parsing model:
13072 //
13073 // lexical analysis
13074 // use stb_lex() to parse tokens; keywords get their own tokens
13075 //
13076 // parsing:
13077 // recursive descent parser. too much of a hassle to make an unambiguous
13078 // LR(1) grammar, and one-pass generation is clumsier (recursive descent
13079 // makes it easier to e.g. compile nested functions). on the other hand,
13080 // dictionary syntax required hackery to get extra lookahead.
13081 //
13082 // codegen:
13083 // output into an evaluation tree, using array indices as 'pointers'
13084 //
13085 // run:
13086 // traverse the tree; support for 'break/continue/return' is tricky
13087 //
13088 // garbage collection:
13089 // stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots
13090
13091 typedef stb_int32 stua_obj;
13092
13093 typedef stb_idict stua_dict;
13094
13095 STB_EXTERN void stua_run_script(char *s);
13096 STB_EXTERN void stua_uninit(void);
13097
13098 extern stua_obj stua_globals;
13099
13100 STB_EXTERN double stua_number(stua_obj z);
13101
13102 STB_EXTERN stua_obj stua_getnil(void);
13103 STB_EXTERN stua_obj stua_getfalse(void);
13104 STB_EXTERN stua_obj stua_gettrue(void);
13105 STB_EXTERN stua_obj stua_string(char *z);
13106 STB_EXTERN stua_obj stua_make_number(double d);
13107 STB_EXTERN stua_obj stua_box(int type, void *data, int size);
13108
13109 enum
13110 {
13111 STUA_op_negate=129,
13112 STUA_op_shl, STUA_op_ge,
13113 STUA_op_shr, STUA_op_le,
13114 STUA_op_shru,
13115 STUA_op_last
13116 };
13117
13118 #define STUA_NO_VALUE 2 // equivalent to a tagged NULL
13119 STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c);
13120
13121 STB_EXTERN stua_obj stua_error(char *err, ...);
13122
13123 STB_EXTERN stua_obj stua_pushroot(stua_obj o);
13124 STB_EXTERN void stua_poproot ( void );
13125
13126
13127 #ifdef STB_DEFINE
13128 // INTERPRETER
13129
13130 // 31-bit floating point implementation
13131 // force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent;
13132 // then shift and set the bottom bit
13133
13134 static stua_obj stu__floatp(float *f)
13135 {
13136 unsigned int n = *(unsigned int *) f;
13137 unsigned int e = n & (0xff << 23);
13138
13139 assert(sizeof(int) == 4 && sizeof(float) == 4);
13140
13141 if (!e) // zero?
13142 n = n; // no change
13143 else if (e < (64 << 23)) // underflow of the packed encoding?
13144 n = (n & 0x80000000); // signed 0
13145 else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN)
13146 n = (n & 0x80000000) + (127 << 23); // new INF encoding
13147 else
13148 n -= 0x20000000;
13149
13150 // now we need to shuffle the bits so that the spare bit is at the bottom
13151 assert((n & 0x40000000) == 0);
13152 return (n & 0x80000000) + (n << 1) + 1;
13153 }
13154
13155 static unsigned char stu__getfloat_addend[256];
13156 static float stu__getfloat(stua_obj v)
13157 {
13158 unsigned int n;
13159 unsigned int e = ((unsigned int) v) >> 24;
13160
13161 n = (int) v >> 1; // preserve high bit
13162 n += stu__getfloat_addend[e] << 24;
13163 return *(float *) &n;
13164 }
13165
13166 stua_obj stua_float(float f)
13167 {
13168 return stu__floatp(&f);
13169 }
13170
13171 static void stu__float_init(void)
13172 {
13173 int i;
13174 stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0
13175 for (i=1; i < 127; ++i)
13176 stu__getfloat_addend[i] = 32; // undo the -0x20000000
13177 stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f)
13178
13179 for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down
13180 stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64;
13181 }
13182
13183 // Tagged data type implementation
13184
13185 // TAGS:
13186 #define stu__int_tag 0 // of 2 bits // 00 int
13187 #define stu__float_tag 1 // of 1 bit // 01 float
13188 #define stu__ptr_tag 2 // of 2 bits // 10 boxed
13189 // 11 float
13190
13191 #define stu__tag(x) ((x) & 3)
13192 #define stu__number(x) (stu__tag(x) != stu__ptr_tag)
13193 #define stu__isint(x) (stu__tag(x) == stu__int_tag)
13194
13195 #define stu__int(x) ((x) >> 2)
13196 #define stu__float(x) (stu__getfloat(x))
13197
13198 #define stu__makeint(v) ((v)*4+stu__int_tag)
13199
13200 // boxed data, and tag support for boxed data
13201
13202 enum
13203 {
13204 STU___float = 1, STU___int = 2,
13205 STU___number = 3, STU___string = 4,
13206 STU___function = 5, STU___dict = 6,
13207 STU___boolean = 7, STU___error = 8,
13208 };
13209
13210 // boxed data
13211 #define STU__BOX short type, stua_gc
13212 typedef struct stu__box { STU__BOX; } stu__box;
13213
13214 stu__box stu__nil = { 0, 1 };
13215 stu__box stu__true = { STU___boolean, 1, };
13216 stu__box stu__false = { STU___boolean, 1, };
13217
13218 #define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag)
13219
13220 #define stua_nil stu__makeptr(&stu__nil)
13221 #define stua_true stu__makeptr(&stu__true)
13222 #define stua_false stu__makeptr(&stu__false)
13223
13224 stua_obj stua_getnil(void) { return stua_nil; }
13225 stua_obj stua_getfalse(void) { return stua_false; }
13226 stua_obj stua_gettrue(void) { return stua_true; }
13227
13228 #define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag))
13229
13230 #define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \
13231 (t) == STU___int ? stu__isint(x) : \
13232 (t) == STU___number ? stu__number(x) : \
13233 stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t))
13234
13235 typedef struct
13236 {
13237 STU__BOX;
13238 void *ptr;
13239 } stu__wrapper;
13240
13241 // implementation of a 'function' or function + closure
13242
13243 typedef struct stu__func
13244 {
13245 STU__BOX;
13246 stua_obj closure_source; // 0 - regular function; 4 - C function
13247 // if closure, pointer to source function
13248 union {
13249 stua_obj closure_data; // partial-application data
13250 void *store; // pointer to free that holds 'code'
13251 stua_obj (*func)(stua_dict *context);
13252 } f;
13253 // closure ends here
13254 short *code;
13255 int num_param;
13256 stua_obj *param; // list of parameter strings
13257 } stu__func;
13258
13259 // apply this to 'short *code' to get at data
13260 #define stu__const(f) ((stua_obj *) (f))
13261
13262 static void stu__free_func(stu__func *f)
13263 {
13264 if (f->closure_source == 0) free(f->f.store);
13265 if ((stb_uint) f->closure_source <= 4) free(f->param);
13266 free(f);
13267 }
13268
13269 #define stu__pd(x) ((stua_dict *) stu__ptr(x))
13270 #define stu__pw(x) ((stu__wrapper *) stu__ptr(x))
13271 #define stu__pf(x) ((stu__func *) stu__ptr(x))
13272
13273
13274 // garbage-collection
13275
13276
13277 static stu__box ** stu__gc_ptrlist;
13278 static stua_obj * stu__gc_root_stack;
13279
13280 stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; }
13281 void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); }
13282
13283 static stb_sdict *stu__strings;
13284 static void stu__mark(stua_obj z)
13285 {
13286 int i;
13287 stu__box *p = stu__ptr(z);
13288 if (p->stua_gc == 1) return; // already marked
13289 assert(p->stua_gc == 0);
13290 p->stua_gc = 1;
13291 switch(p->type) {
13292 case STU___function: {
13293 stu__func *f = (stu__func *) p;
13294 if ((stb_uint) f->closure_source <= 4) {
13295 if (f->closure_source == 0) {
13296 for (i=1; i <= f->code[0]; ++i)
13297 if (!stu__number(((stua_obj *) f->code)[-i]))
13298 stu__mark(((stua_obj *) f->code)[-i]);
13299 }
13300 for (i=0; i < f->num_param; ++i)
13301 stu__mark(f->param[i]);
13302 } else {
13303 stu__mark(f->closure_source);
13304 stu__mark(f->f.closure_data);
13305 }
13306 break;
13307 }
13308 case STU___dict: {
13309 stua_dict *e = (stua_dict *) p;
13310 for (i=0; i < e->limit; ++i)
13311 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) {
13312 if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k);
13313 if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v);
13314 }
13315 break;
13316 }
13317 }
13318 }
13319
13320 static int stu__num_allocs, stu__size_allocs;
13321 static stua_obj stu__flow_val = stua_nil; // used for break & return
13322
13323 static void stua_gc(int force)
13324 {
13325 int i;
13326 if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return;
13327 stu__num_allocs = stu__size_allocs = 0;
13328 //printf("[gc]\n");
13329
13330 // clear marks
13331 for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i)
13332 stu__gc_ptrlist[i]->stua_gc = 0;
13333
13334 // stu__mark everything reachable
13335 stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1;
13336 stu__mark(stua_globals);
13337 if (!stu__number(stu__flow_val))
13338 stu__mark(stu__flow_val);
13339 for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i)
13340 if (!stu__number(stu__gc_root_stack[i]))
13341 stu__mark(stu__gc_root_stack[i]);
13342
13343 // sweep unreachables
13344 for (i=0; i < stb_arr_len(stu__gc_ptrlist);) {
13345 stu__box *z = stu__gc_ptrlist[i];
13346 if (!z->stua_gc) {
13347 switch (z->type) {
13348 case STU___dict: stb_idict_destroy((stua_dict *) z); break;
13349 case STU___error: free(((stu__wrapper *) z)->ptr); break;
13350 case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break;
13351 case STU___function: stu__free_func((stu__func *) z); break;
13352 }
13353 // swap in the last item over this, and repeat
13354 z = stb_arr_pop(stu__gc_ptrlist);
13355 stu__gc_ptrlist[i] = z;
13356 } else
13357 ++i;
13358 }
13359 }
13360
13361 static void stu__consider_gc(stua_obj x)
13362 {
13363 if (stu__size_allocs < 100000) return;
13364 if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return;
13365 stb_arr_push(stu__gc_root_stack, x);
13366 stua_gc(0);
13367 stb_arr_pop(stu__gc_root_stack);
13368 }
13369
13370 static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc)
13371 {
13372 stua_obj x = stu__makeptr(data);
13373 ((stu__box *) data)->type = type;
13374 stb_arr_push(stu__gc_ptrlist, (stu__box *) data);
13375 stu__num_allocs += 1;
13376 stu__size_allocs += size;
13377 if (safe_to_gc) stu__consider_gc(x);
13378 return x;
13379 }
13380
13381 stua_obj stua_box(int type, void *data, int size)
13382 {
13383 stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p));
13384 p->ptr = data;
13385 return stu__makeobj(type, p, size, 0);
13386 }
13387
13388 // a stu string can be directly compared for equality, because
13389 // they go into a hash table
13390 stua_obj stua_string(char *z)
13391 {
13392 stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z);
13393 if (b == NULL) {
13394 int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b));
13395 b = stu__pw(o);
13396 stb_sdict_add(stu__strings, z, b);
13397 stb_sdict_getkey(stu__strings, z, (char **) &b->ptr);
13398 }
13399 return stu__makeptr(b);
13400 }
13401
13402 // stb_obj dictionary is just an stb_idict
13403 static void stu__set(stua_dict *d, stua_obj k, stua_obj v)
13404 { if (stb_idict_set(d, k, v)) stu__size_allocs += 8; }
13405
13406 static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res)
13407 {
13408 stb_idict_get_flag(d, k, &res);
13409 return res;
13410 }
13411
13412 static stua_obj make_string(char *z, int len)
13413 {
13414 stua_obj s;
13415 char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q;
13416 while (len > 0) {
13417 if (*z == '\\') {
13418 if (z[1] == 'n') *p = '\n';
13419 else if (z[1] == 'r') *p = '\r';
13420 else if (z[1] == 't') *p = '\t';
13421 else *p = z[1];
13422 p += 1; z += 2; len -= 2;
13423 } else {
13424 *p++ = *z++; len -= 1;
13425 }
13426 }
13427 *p = 0;
13428 s = stua_string(q);
13429 stb_tempfree(temp, q);
13430 return s;
13431 }
13432
13433 enum token_names
13434 {
13435 T__none=128,
13436 ST_shl = STUA_op_shl, ST_ge = STUA_op_ge,
13437 ST_shr = STUA_op_shr, ST_le = STUA_op_le,
13438 ST_shru = STUA_op_shru, STU__negate = STUA_op_negate,
13439 ST__reset_numbering = STUA_op_last,
13440 ST_white,
13441 ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number,
13442 // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them
13443 ST_if, ST_while, ST_for, ST_eq, ST_nil,
13444 ST_then, ST_do, ST_in, ST_ne, ST_true,
13445 ST_else, ST_break, ST_let, ST_and, ST_false,
13446 ST_elseif, ST_continue, ST_into, ST_or, ST_repeat,
13447 ST_end, ST_as, ST_return, ST_var, ST_func,
13448 ST_catch, ST__frame,
13449 ST__max_terminals,
13450
13451 STU__defaultparm, STU__seq,
13452 };
13453
13454 static stua_dict * stu__globaldict;
13455 stua_obj stua_globals;
13456
13457 static enum
13458 {
13459 FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error,
13460 } stu__flow;
13461
13462 stua_obj stua_error(char *z, ...)
13463 {
13464 stua_obj a;
13465 char temp[4096], *x;
13466 va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v);
13467 x = stb_p_strdup(temp);
13468 a = stua_box(STU___error, x, strlen(x));
13469 stu__flow = FLOW_error;
13470 stu__flow_val = a;
13471 return stua_nil;
13472 }
13473
13474 double stua_number(stua_obj z)
13475 {
13476 return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z);
13477 }
13478
13479 stua_obj stua_make_number(double d)
13480 {
13481 double e = floor(d);
13482 if (e == d && e < (1 << 29) && e >= -(1 << 29))
13483 return stu__makeint((int) e);
13484 else
13485 return stua_float((float) d);
13486 }
13487
13488 stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL;
13489
13490 static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c)
13491 {
13492 stua_obj r = STUA_NO_VALUE;
13493 if (op == '+') {
13494 if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) {
13495 ;// @TODO: string concatenation
13496 } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) {
13497 stu__func *f = (stu__func *) malloc(12);
13498 assert(offsetof(stu__func, code)==12);
13499 f->closure_source = a;
13500 f->f.closure_data = b;
13501 return stu__makeobj(STU___function, f, 16, 1);
13502 }
13503 }
13504 if (stua_overload) r = stua_overload(op,a,b,c);
13505 if (stu__flow != FLOW_error && r == STUA_NO_VALUE)
13506 stua_error("Typecheck for operator %d", op), r=stua_nil;
13507 return r;
13508 }
13509
13510 #define STU__EVAL2(a,b) \
13511 a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \
13512 b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break;
13513
13514 #define STU__FB(op) \
13515 STU__EVAL2(a,b) \
13516 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13517 return ((a) op (b)); \
13518 if (stu__number(a) && stu__number(b)) \
13519 return stua_make_number(stua_number(a) op stua_number(b)); \
13520 return stu__op(stu__f[n], a,b, stua_nil)
13521
13522 #define STU__F(op) \
13523 STU__EVAL2(a,b) \
13524 if (stu__number(a) && stu__number(b)) \
13525 return stua_make_number(stua_number(a) op stua_number(b)); \
13526 return stu__op(stu__f[n], a,b, stua_nil)
13527
13528 #define STU__I(op) \
13529 STU__EVAL2(a,b) \
13530 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13531 return stu__makeint(stu__int(a) op stu__int(b)); \
13532 return stu__op(stu__f[n], a,b, stua_nil)
13533
13534 #define STU__C(op) \
13535 STU__EVAL2(a,b) \
13536 if (stu__number(a) && stu__number(b)) \
13537 return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \
13538 return stu__op(stu__f[n], a,b, stua_nil)
13539
13540 #define STU__CE(op) \
13541 STU__EVAL2(a,b) \
13542 return (a op b) ? stua_true : stua_false
13543
13544 static short *stu__f;
13545 static stua_obj stu__f_obj;
13546 static stua_dict *stu__c;
13547 static stua_obj stu__funceval(stua_obj fo, stua_obj co);
13548
13549 static int stu__cond(stua_obj x)
13550 {
13551 if (stu__flow) return 0;
13552 if (!stu__checkt(STU___boolean, x))
13553 x = stu__op('!', x, stua_nil, stua_nil);
13554 if (x == stua_true ) return 1;
13555 if (x == stua_false) return 0;
13556 stu__flow = FLOW_error;
13557 return 0;
13558 }
13559
13560 // had to manually eliminate tailcall recursion for debugging complex stuff
13561 #define TAILCALL(x) n = (x); goto top;
13562 static stua_obj stu__eval(int n)
13563 {
13564 top:
13565 if (stu__flow >= FLOW_return) return stua_nil; // is this needed?
13566 if (n < 0) return stu__const(stu__f)[n];
13567 assert(n != 0 && n != 1);
13568 switch (stu__f[n]) {
13569 stua_obj a,b,c;
13570 case ST_catch: a = stu__eval(stu__f[n+1]);
13571 if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; }
13572 return a;
13573 case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break;
13574 stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b);
13575 return b;
13576 case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break;
13577 TAILCALL(stu__f[n+2]);
13578 case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil;
13579 TAILCALL(stu__f[n+2]);
13580 case ST_else: a = stu__cond(stu__eval(stu__f[n+1]));
13581 TAILCALL(stu__f[n + 2 + !a]);
13582 #define STU__HANDLE_BREAK \
13583 if (stu__flow >= FLOW_break) { \
13584 if (stu__flow == FLOW_break) { \
13585 a = stu__flow_val; \
13586 stu__flow = FLOW_normal; \
13587 stu__flow_val = stua_nil; \
13588 return a; \
13589 } \
13590 return stua_nil; \
13591 }
13592 case ST_as: stu__eval(stu__f[n+3]);
13593 STU__HANDLE_BREAK
13594 // fallthrough!
13595 case ST_while: a = stua_nil; stua_pushroot(a);
13596 while (stu__cond(stu__eval(stu__f[n+1]))) {
13597 stua_poproot();
13598 a = stu__eval(stu__f[n+2]);
13599 STU__HANDLE_BREAK
13600 stu__flow = FLOW_normal; // clear 'continue' flag
13601 stua_pushroot(a);
13602 if (stu__f[n+3]) stu__eval(stu__f[n+3]);
13603 STU__HANDLE_BREAK
13604 stu__flow = FLOW_normal; // clear 'continue' flag
13605 }
13606 stua_poproot();
13607 return a;
13608 case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break;
13609 case ST_continue:stu__flow = FLOW_continue; break;
13610 case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break;
13611 case ST__frame: return stu__f_obj;
13612 case '[': STU__EVAL2(a,b);
13613 if (stu__checkt(STU___dict, a))
13614 return stu__get(stu__pd(a), b, stua_nil);
13615 return stu__op(stu__f[n], a, b, stua_nil);
13616 case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break;
13617 n = stu__f[n+1];
13618 if (stu__f[n] == ST_id) {
13619 if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13620 if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a))
13621 return stua_error("Assignment to undefined variable");
13622 } else if (stu__f[n] == '[') {
13623 stua_pushroot(a);
13624 b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; }
13625 stua_pushroot(b);
13626 c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot();
13627 if (stu__flow) break;
13628 if (!stu__checkt(STU___dict, b)) return stua_nil;
13629 stu__set(stu__pd(b), c, a);
13630 } else {
13631 return stu__op(stu__f[n], stu__eval(n), a, stua_nil);
13632 }
13633 return a;
13634 case STU__defaultparm:
13635 a = stu__eval(stu__f[n+2]);
13636 stu__flow = FLOW_normal;
13637 if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13638 stu__size_allocs += 8;
13639 return stua_nil;
13640 case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable
13641 return a != STUA_NO_VALUE // else try stu__compile_global_scope variable
13642 ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil);
13643 case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13644 return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil);
13645 case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13646 return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil);
13647 case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13648 a = stu__cond(a); if (stu__flow) break;
13649 return a ? stua_true : stua_false;
13650 case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<);
13651 case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>);
13652 case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<);
13653 case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>);
13654 case '%': STU__I(%); case '^': STU__I(^);
13655 case ST_shru: STU__EVAL2(a,b);
13656 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag)
13657 return stu__makeint((unsigned) stu__int(a) >> stu__int(b));
13658 return stu__op(stu__f[n], a,b, stua_nil);
13659 case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13660 return a ? stu__eval(stu__f[n+2]) : a;
13661 case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13662 return a ? b : stu__eval(stu__f[n+2]);
13663 case'(':case':': STU__EVAL2(a,b);
13664 if (!stu__checkt(STU___function, a))
13665 return stu__op(stu__f[n], a,b, stua_nil);
13666 if (!stu__checkt(STU___dict, b))
13667 return stua_nil;
13668 if (stu__f[n] == ':')
13669 b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0);
13670 a = stu__funceval(a,b);
13671 return a;
13672 case '{' : {
13673 stua_dict *d;
13674 d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16);
13675 if (d == NULL)
13676 return stua_nil; // breakpoint fodder
13677 c = stu__makeobj(STU___dict, d, 32, 1);
13678 stua_pushroot(c);
13679 a = stu__f[n+1];
13680 for (b=0; b < a; ++b) {
13681 stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0]));
13682 stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]);
13683 stua_poproot();
13684 if (stu__flow) { stua_poproot(); return stua_nil; }
13685 stu__set(d, x, y);
13686 }
13687 stua_poproot();
13688 return c;
13689 }
13690 default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]];
13691 assert(0); /* NOTREACHED */ // internal error!
13692 }
13693 return stua_nil;
13694 }
13695
13696 int stb__stua_nesting;
13697 static stua_obj stu__funceval(stua_obj fo, stua_obj co)
13698 {
13699 stu__func *f = stu__pf(fo);
13700 stua_dict *context = stu__pd(co);
13701 int i,j;
13702 stua_obj p;
13703 short *tf = stu__f; // save previous function
13704 stua_dict *tc = stu__c;
13705
13706 if (stu__flow == FLOW_error) return stua_nil;
13707 assert(stu__flow == FLOW_normal);
13708
13709 stua_pushroot(fo);
13710 stua_pushroot(co);
13711 stu__consider_gc(stua_nil);
13712
13713 while ((stb_uint) f->closure_source > 4) {
13714 // add data from closure to context
13715 stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data);
13716 for (i=0; i < e->limit; ++i)
13717 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL)
13718 if (stb_idict_add(context, e->table[i].k, e->table[i].v))
13719 stu__size_allocs += 8;
13720 // use add so if it's already defined, we don't override it; that way
13721 // explicit parameters win over applied ones, and most recent applications
13722 // win over previous ones
13723 f = stu__pf(f->closure_source);
13724 }
13725
13726 for (j=0, i=0; i < f->num_param; ++i)
13727 // if it doesn't already exist, add it from the numbered parameters
13728 if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil)))
13729 ++j;
13730
13731 // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters
13732 // @TODO: ditto too few parameters
13733
13734 if (f->closure_source == 4)
13735 p = f->f.func(context);
13736 else {
13737 stu__f = f->code, stu__c = context;
13738 stu__f_obj = co;
13739 ++stb__stua_nesting;
13740 if (stu__f[1])
13741 p = stu__eval(stu__f[1]);
13742 else
13743 p = stua_nil;
13744 --stb__stua_nesting;
13745 stu__f = tf, stu__c = tc; // restore previous function
13746 if (stu__flow == FLOW_return) {
13747 stu__flow = FLOW_normal;
13748 p = stu__flow_val;
13749 stu__flow_val = stua_nil;
13750 }
13751 }
13752
13753 stua_poproot();
13754 stua_poproot();
13755
13756 return p;
13757 }
13758
13759 // Parser
13760
13761 static int stu__tok;
13762 static stua_obj stu__tokval;
13763
13764 static char *stu__curbuf, *stu__bufstart;
13765
13766 static stb_matcher *stu__lex_matcher;
13767
13768 static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals];
13769
13770 static void stu__nexttoken(void)
13771 {
13772 int len;
13773
13774 retry:
13775 stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len);
13776 if (stu__tok == 0)
13777 return;
13778 switch(stu__tok) {
13779 case ST_white : stu__curbuf += len; goto retry;
13780 case T__none : stu__tok = *stu__curbuf; break;
13781 case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break;
13782 case ST_id : stu__tokval = make_string(stu__curbuf, len); break;
13783 case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break;
13784 case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break;
13785 case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break;
13786 case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2];
13787 if (stu__curbuf[3] == 't') stu__tokval = '\t';
13788 if (stu__curbuf[3] == 'n') stu__tokval = '\n';
13789 if (stu__curbuf[3] == 'r') stu__tokval = '\r';
13790 stu__tokval = stu__makeint(stu__tokval);
13791 stu__tok = ST_number;
13792 break;
13793 }
13794 stu__curbuf += len;
13795 }
13796
13797 static struct { int stu__tok; char *regex; } stu__lexemes[] =
13798 {
13799 ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+",
13800 ST_id , "[_a-zA-Z][_a-zA-Z0-9]*",
13801 ST_hex , "0x[0-9a-fA-F]+",
13802 ST_decimal, "[0-9]+[0-9]*",
13803 ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?",
13804 ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?",
13805 ST_char , "c'(\\\\.|[^\\'])'",
13806 ST_string , "\"(\\\\.|[^\\\"\n\r])*\"",
13807 ST_string , "\'(\\\\.|[^\\\'\n\r])*\'",
13808
13809 #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d,
13810 stua_key4(if,then,else,elseif) stua_key4(while,do,for,in)
13811 stua_key4(func,var,let,break) stua_key4(nil,true,false,end)
13812 stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch)
13813
13814 ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=",
13815 ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=",
13816 ST_shru,">>>", ST_into, "=>",
13817 T__none, ".",
13818 };
13819
13820 typedef struct
13821 {
13822 stua_obj *data; // constants being compiled
13823 short *code; // code being compiled
13824 stua_dict *locals;
13825 short *non_local_refs;
13826 } stu__comp_func;
13827
13828 static stu__comp_func stu__pfunc;
13829 static stu__comp_func *func_stack = NULL;
13830 static void stu__push_func_comp(void)
13831 {
13832 stb_arr_push(func_stack, stu__pfunc);
13833 stu__pfunc.data = NULL;
13834 stu__pfunc.code = NULL;
13835 stu__pfunc.locals = stb_idict_new_size(16);
13836 stu__pfunc.non_local_refs = NULL;
13837 stb_arr_push(stu__pfunc.code, 0); // number of data items
13838 stb_arr_push(stu__pfunc.code, 1); // starting execution address
13839 }
13840
13841 static void stu__pop_func_comp(void)
13842 {
13843 stb_arr_free(stu__pfunc.code);
13844 stb_arr_free(stu__pfunc.data);
13845 stb_idict_destroy(stu__pfunc.locals);
13846 stb_arr_free(stu__pfunc.non_local_refs);
13847 stu__pfunc = stb_arr_pop(func_stack);
13848 }
13849
13850 // if an id is a reference to an outer lexical scope, this
13851 // function returns the "name" of it, and updates the stack
13852 // structures to make sure the names are propagated in.
13853 static int stu__nonlocal_id(stua_obj var_obj)
13854 {
13855 stua_obj dummy, var = var_obj;
13856 int i, n = stb_arr_len(func_stack), j,k;
13857 if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0;
13858 for (i=n-1; i > 1; --i) {
13859 if (stb_idict_get_flag(func_stack[i].locals, var, &dummy))
13860 break;
13861 }
13862 if (i <= 1) return 0; // stu__compile_global_scope
13863 j = i; // need to access variable from j'th frame
13864 for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i)
13865 if (stu__pfunc.non_local_refs[i] == j) return j-n;
13866 stb_arr_push(stu__pfunc.non_local_refs, j-n);
13867 // now make sure all the parents propagate it down
13868 for (k=n-1; k > 1; --k) {
13869 if (j-k >= 0) return j-n; // comes direct from this parent
13870 for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i)
13871 if (func_stack[k].non_local_refs[i] == j-k)
13872 return j-n;
13873 stb_arr_push(func_stack[k].non_local_refs, j-k);
13874 }
13875 assert (k != 1);
13876
13877 return j-n;
13878 }
13879
13880 static int stu__off(void) { return stb_arr_len(stu__pfunc.code); }
13881 static void stu__cc(int a)
13882 {
13883 assert(a >= -2000 && a < 5000);
13884 stb_arr_push(stu__pfunc.code, a);
13885 }
13886 static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; }
13887 static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; }
13888 static int stu__cc3(int a, int b, int c) {
13889 if (a == '=') assert(c != 0);
13890 stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; }
13891 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; }
13892
13893 static int stu__cdv(stua_obj p)
13894 {
13895 int i;
13896 assert(p != STUA_NO_VALUE);
13897 for (i=0; i < stb_arr_len(stu__pfunc.data); ++i)
13898 if (stu__pfunc.data[i] == p)
13899 break;
13900 if (i == stb_arr_len(stu__pfunc.data))
13901 stb_arr_push(stu__pfunc.data, p);
13902 return ~i;
13903 }
13904
13905 static int stu__cdt(void)
13906 {
13907 int z = stu__cdv(stu__tokval);
13908 stu__nexttoken();
13909 return z;
13910 }
13911
13912 static int stu__seq(int a, int b)
13913 {
13914 return !a ? b : !b ? a : stu__cc3(STU__seq, a,b);
13915 }
13916
13917 static char stu__comp_err_str[1024];
13918 static int stu__comp_err_line;
13919 static int stu__err(char *str, ...)
13920 {
13921 va_list v;
13922 char *s = stu__bufstart;
13923 stu__comp_err_line = 1;
13924 while (s < stu__curbuf) {
13925 if (s[0] == '\n' || s[0] == '\r') {
13926 if (s[0]+s[1] == '\n' + '\r') ++s;
13927 ++stu__comp_err_line;
13928 }
13929 ++s;
13930 }
13931 va_start(v, str);
13932 vsprintf(stu__comp_err_str, str, v);
13933 va_end(v);
13934 return 0;
13935 }
13936
13937 static int stu__accept(int p)
13938 {
13939 if (stu__tok != p) return 0;
13940 stu__nexttoken();
13941 return 1;
13942 }
13943
13944 static int stu__demand(int p)
13945 {
13946 if (stu__accept(p)) return 1;
13947 return stu__err("Didn't find expected stu__tok");
13948 }
13949
13950 static int stu__demandv(int p, stua_obj *val)
13951 {
13952 if (stu__tok == p || p==0) {
13953 *val = stu__tokval;
13954 stu__nexttoken();
13955 return 1;
13956 } else
13957 return 0;
13958 }
13959
13960 static int stu__expr(int p);
13961 int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); }
13962 static int stu__statements(int once, int as);
13963
13964 static int stu__parse_if(void) // parse both ST_if and ST_elseif
13965 {
13966 int b,c,a;
13967 a = stu__nexpr(1); if (!a) return 0;
13968 if (!stu__demand(ST_then)) return stu__err("expecting THEN");
13969 b = stu__statements(0,0); if (!b) return 0;
13970 if (b == 1) b = -1;
13971
13972 if (stu__tok == ST_elseif) {
13973 return stu__parse_if();
13974 } else if (stu__accept(ST_else)) {
13975 c = stu__statements(0,0); if (!c) return 0;
13976 if (!stu__demand(ST_end)) return stu__err("expecting END after else clause");
13977 return stu__cc4(ST_else, a, b, c);
13978 } else {
13979 if (!stu__demand(ST_end)) return stu__err("expecting END in if statement");
13980 return stu__cc3(ST_if, a, b);
13981 }
13982 }
13983
13984 int stu__varinit(int z, int in_globals)
13985 {
13986 int a,b;
13987 stu__nexttoken();
13988 while (stu__demandv(ST_id, &b)) {
13989 if (!stb_idict_add(stu__pfunc.locals, b, 1))
13990 if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr);
13991 if (stu__accept('=')) {
13992 a = stu__expr(1); if (!a) return 0;
13993 } else
13994 a = stu__cdv(stua_nil);
13995 z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a));
13996 if (!stu__accept(',')) break;
13997 }
13998 return z;
13999 }
14000
14001 static int stu__compile_unary(int z, int outparm, int require_inparm)
14002 {
14003 int op = stu__tok, a, b;
14004 stu__nexttoken();
14005 if (outparm) {
14006 if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) {
14007 a = stu__expr(1); if (!a) return 0;
14008 } else
14009 a = stu__cdv(stua_nil);
14010 b = stu__cc2(op, a);
14011 } else
14012 b = stu__cc1(op);
14013 return stu__seq(z,b);
14014 }
14015
14016 static int stu__assign(void)
14017 {
14018 int z;
14019 stu__accept(ST_let);
14020 z = stu__expr(1); if (!z) return 0;
14021 if (stu__accept('=')) {
14022 int y,p = (z >= 0 ? stu__pfunc.code[z] : 0);
14023 if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment");
14024 y = stu__assign(); if (!y) return 0;
14025 z = stu__cc3('=', z, y);
14026 }
14027 return z;
14028 }
14029
14030 static int stu__statements(int once, int stop_while)
14031 {
14032 int a,b, c, z=0;
14033 for(;;) {
14034 switch (stu__tok) {
14035 case ST_if : a = stu__parse_if(); if (!a) return 0;
14036 z = stu__seq(z, a);
14037 break;
14038 case ST_while : if (stop_while) return (z ? z:1);
14039 a = stu__nexpr(1); if (!a) return 0;
14040 if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0;
14041 if (!stu__demand(ST_do)) return stu__err("expecting DO");
14042 b = stu__statements(0,0); if (!b) return 0;
14043 if (!stu__demand(ST_end)) return stu__err("expecting END");
14044 if (b == 1) b = -1;
14045 z = stu__seq(z, stu__cc4(ST_while, a, b, c));
14046 break;
14047 case ST_repeat : stu__nexttoken();
14048 c = stu__statements(0,1); if (!c) return 0;
14049 if (!stu__demand(ST_while)) return stu__err("expecting WHILE");
14050 a = stu__expr(1); if (!a) return 0;
14051 if (!stu__demand(ST_do)) return stu__err("expecting DO");
14052 b = stu__statements(0,0); if (!b) return 0;
14053 if (!stu__demand(ST_end)) return stu__err("expecting END");
14054 if (b == 1) b = -1;
14055 z = stu__seq(z, stu__cc4(ST_as, a, b, c));
14056 break;
14057 case ST_catch : a = stu__nexpr(1); if (!a) return 0;
14058 z = stu__seq(z, stu__cc2(ST_catch, a));
14059 break;
14060 case ST_var : z = stu__varinit(z,0); break;
14061 case ST_return : z = stu__compile_unary(z,1,1); break;
14062 case ST_continue:z = stu__compile_unary(z,0,0); break;
14063 case ST_break : z = stu__compile_unary(z,1,0); break;
14064 case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block");
14065 a = stu__nexpr(99);
14066 b = (a >= 0? stu__pfunc.code[a] : 0);
14067 if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>");
14068 z = stu__cc3('=', a, z);
14069 break;
14070 default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1);
14071 a = stu__assign(); if (!a) return 0;
14072 stu__accept(';');
14073 if (stu__tok && !stu__end[stu__tok]) {
14074 if (a < 0)
14075 return stu__err("Constant has no effect");
14076 if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=')
14077 return stu__err("Expression has no effect");
14078 }
14079 z = stu__seq(z, a);
14080 break;
14081 }
14082 if (!z) return 0;
14083 stu__accept(';');
14084 if (once && stu__tok != ST_into) return z;
14085 }
14086 }
14087
14088 static int stu__postexpr(int z, int p);
14089 static int stu__dictdef(int end, int *count)
14090 {
14091 int z,n=0,i,flags=0;
14092 short *dict=NULL;
14093 stu__nexttoken();
14094 while (stu__tok != end) {
14095 if (stu__tok == ST_id) {
14096 stua_obj id = stu__tokval;
14097 stu__nexttoken();
14098 if (stu__tok == '=') {
14099 flags |= 1;
14100 stb_arr_push(dict, stu__cdv(id));
14101 z = stu__nexpr(1); if (!z) return 0;
14102 } else {
14103 z = stu__cc2(ST_id, stu__cdv(id));
14104 z = stu__postexpr(z,1); if (!z) return 0;
14105 flags |= 2;
14106 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
14107 }
14108 } else {
14109 z = stu__expr(1); if (!z) return 0;
14110 flags |= 2;
14111 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
14112 }
14113 if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;}
14114 stb_arr_push(dict, z);
14115 if (!stu__accept(',')) break;
14116 }
14117 if (!stu__demand(end))
14118 return stu__err(end == ')' ? "Expecting ) at end of function call"
14119 : "Expecting } at end of dictionary definition");
14120 z = stu__cc2('{', stb_arr_len(dict)/2);
14121 for (i=0; i < stb_arr_len(dict); ++i)
14122 stu__cc(dict[i]);
14123 if (count) *count = n;
14124 done:
14125 stb_arr_free(dict);
14126 return z;
14127 }
14128
14129 static int stu__comp_id(void)
14130 {
14131 int z,d;
14132 d = stu__nonlocal_id(stu__tokval);
14133 if (d == 0)
14134 return z = stu__cc2(ST_id, stu__cdt());
14135 // access a non-local frame by naming it with the appropriate int
14136 assert(d < 0);
14137 z = stu__cdv(d); // relative frame # is the 'variable' in our local frame
14138 z = stu__cc2(ST_id, z); // now access that dictionary
14139 return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir
14140 }
14141
14142 static stua_obj stu__funcdef(stua_obj *id, stua_obj *func);
14143 static int stu__expr(int p)
14144 {
14145 int z;
14146 // unary
14147 switch (stu__tok) {
14148 case ST_number: z = stu__cdt(); break;
14149 case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C
14150 case ST_id : z = stu__comp_id(); break;
14151 case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break;
14152 case ST_func : z = stu__funcdef(NULL,NULL); break;
14153 case ST_if : z = stu__parse_if(); break;
14154 case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break;
14155 case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break;
14156 case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break;
14157 case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break;
14158 case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break;
14159 case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break;
14160 case '{' : z = stu__dictdef('}', NULL); break;
14161 default : return stu__err("Unexpected token");
14162 case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )");
14163 }
14164 return stu__postexpr(z,p);
14165 }
14166
14167 static int stu__postexpr(int z, int p)
14168 {
14169 int q;
14170 // postfix
14171 while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') {
14172 if (stu__accept('.')) {
14173 // MUST be followed by a plain identifier! use [] for other stuff
14174 if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead");
14175 z = stu__cc3('[', z, stu__cdv(stu__tokval));
14176 stu__nexttoken();
14177 } else if (stu__accept('[')) {
14178 while (stu__tok != ']') {
14179 int r = stu__expr(1); if (!r) return 0;
14180 z = stu__cc3('[', z, r);
14181 if (!stu__accept(',')) break;
14182 }
14183 if (!stu__demand(']')) return stu__err("Expecting ]");
14184 } else {
14185 int n, p = stu__dictdef(')', &n); if (!p) return 0;
14186 #if 0 // this is incorrect!
14187 if (z > 0 && stu__pfunc.code[z] == ST_id) {
14188 stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil);
14189 if (stu__checkt(STU___function, q))
14190 if ((stu__pf(q))->num_param != n)
14191 return stu__err("Incorrect number of parameters");
14192 }
14193 #endif
14194 z = stu__cc3('(', z, p);
14195 }
14196 }
14197 // binop - this implementation taken from lcc
14198 for (q=stu__prec[stu__tok]; q >= p; --q) {
14199 while (stu__prec[stu__tok] == q) {
14200 int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0;
14201 z = stu__cc3(o,z,y);
14202 }
14203 }
14204 return z;
14205 }
14206
14207 static stua_obj stu__finish_func(stua_obj *param, int start)
14208 {
14209 int n, size;
14210 stu__func *f = (stu__func *) malloc(sizeof(*f));
14211 f->closure_source = 0;
14212 f->num_param = stb_arr_len(param);
14213 f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param));
14214 size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8;
14215 f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data));
14216 f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data));
14217 memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code));
14218 f->code[1] = start;
14219 f->code[0] = stb_arr_len(stu__pfunc.data);
14220 for (n=0; n < f->code[0]; ++n)
14221 ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n];
14222 return stu__makeobj(STU___function, f, size, 0);
14223 }
14224
14225 static int stu__funcdef(stua_obj *id, stua_obj *result)
14226 {
14227 int n,z=0,i,q;
14228 stua_obj *param = NULL;
14229 short *nonlocal;
14230 stua_obj v,f=stua_nil;
14231 assert(stu__tok == ST_func);
14232 stu__nexttoken();
14233 if (id) {
14234 if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name");
14235 } else
14236 stu__accept(ST_id);
14237 if (!stu__demand('(')) return stu__err("Expecting ( for function parameter");
14238 stu__push_func_comp();
14239 while (stu__tok != ')') {
14240 if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; }
14241 stb_idict_add(stu__pfunc.locals, v, 1);
14242 if (stu__tok == '=') {
14243 n = stu__nexpr(1); if (!n) { z=0; goto done; }
14244 z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n));
14245 } else
14246 stb_arr_push(param, v);
14247 if (!stu__accept(',')) break;
14248 }
14249 if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; }
14250 n = stu__statements(0,0); if (!n) { z=0; goto done; }
14251 if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; }
14252 if (n == 1) n = 0;
14253 n = stu__seq(z,n);
14254 f = stu__finish_func(param, n);
14255 if (result) { *result = f; z=1; stu__pop_func_comp(); }
14256 else {
14257 nonlocal = stu__pfunc.non_local_refs;
14258 stu__pfunc.non_local_refs = NULL;
14259 stu__pop_func_comp();
14260 z = stu__cdv(f);
14261 if (nonlocal) { // build a closure with references to the needed frames
14262 short *initcode = NULL;
14263 for (i=0; i < stb_arr_len(nonlocal); ++i) {
14264 int k = nonlocal[i], p;
14265 stb_arr_push(initcode, stu__cdv(k));
14266 if (k == -1) p = stu__cc1(ST__frame);
14267 else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); }
14268 stb_arr_push(initcode, p);
14269 }
14270 q = stu__cc2('{', stb_arr_len(nonlocal));
14271 for (i=0; i < stb_arr_len(initcode); ++i)
14272 stu__cc(initcode[i]);
14273 z = stu__cc3('+', z, q);
14274 stb_arr_free(initcode);
14275 }
14276 stb_arr_free(nonlocal);
14277 }
14278 done:
14279 stb_arr_free(param);
14280 if (!z) stu__pop_func_comp();
14281 return z;
14282 }
14283
14284 static int stu__compile_global_scope(void)
14285 {
14286 stua_obj o;
14287 int z=0;
14288
14289 stu__push_func_comp();
14290 while (stu__tok != 0) {
14291 if (stu__tok == ST_func) {
14292 stua_obj id, f;
14293 if (!stu__funcdef(&id,&f))
14294 goto error;
14295 stu__set(stu__globaldict, id, f);
14296 } else if (stu__tok == ST_var) {
14297 z = stu__varinit(z,1); if (!z) goto error;
14298 } else {
14299 int y = stu__statements(1,0); if (!y) goto error;
14300 z = stu__seq(z,y);
14301 }
14302 stu__accept(';');
14303 }
14304 o = stu__finish_func(NULL, z);
14305 stu__pop_func_comp();
14306
14307 o = stu__funceval(o, stua_globals); // initialize stu__globaldict
14308 if (stu__flow == FLOW_error)
14309 printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr);
14310 return 1;
14311 error:
14312 stu__pop_func_comp();
14313 return 0;
14314 }
14315
14316 stua_obj stu__myprint(stua_dict *context)
14317 {
14318 stua_obj x = stu__get(context, stua_string("x"), stua_nil);
14319 if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x));
14320 else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x));
14321 else {
14322 stu__wrapper *s = stu__pw(x);
14323 if (s->type == STU___string || s->type == STU___error)
14324 printf("%s", s->ptr);
14325 else if (s->type == STU___dict) printf("{{dictionary}}");
14326 else if (s->type == STU___function) printf("[[function]]");
14327 else
14328 printf("[[ERROR:%s]]", s->ptr);
14329 }
14330 return x;
14331 }
14332
14333 void stua_init(void)
14334 {
14335 if (!stu__globaldict) {
14336 int i;
14337 stua_obj s;
14338 stu__func *f;
14339
14340 stu__prec[ST_and] = stu__prec[ST_or] = 1;
14341 stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] =
14342 stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2;
14343 stu__prec[':'] = 3;
14344 stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4;
14345 stu__prec['+'] = stu__prec['-'] = 5;
14346 stu__prec['*'] = stu__prec['/'] = stu__prec['%'] =
14347 stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6;
14348
14349 stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1;
14350 stu__end[ST_do] = stu__end[ST_elseif] = 1;
14351
14352 stu__float_init();
14353 stu__lex_matcher = stb_lex_matcher();
14354 for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i)
14355 stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok);
14356
14357 stu__globaldict = stb_idict_new_size(64);
14358 stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0);
14359 stu__strings = stb_sdict_new(0);
14360
14361 stu__curbuf = stu__bufstart = "func _print(x) end\n"
14362 "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n";
14363 stu__nexttoken();
14364 if (!stu__compile_global_scope())
14365 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14366
14367 s = stu__get(stu__globaldict, stua_string("_print"), stua_nil);
14368 if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) {
14369 f = stu__pf(s);
14370 free(f->f.store);
14371 f->closure_source = 4;
14372 f->f.func = stu__myprint;
14373 f->code = NULL;
14374 }
14375 }
14376 }
14377
14378 void stua_uninit(void)
14379 {
14380 if (stu__globaldict) {
14381 stb_idict_remove_all(stu__globaldict);
14382 stb_arr_setlen(stu__gc_root_stack, 0);
14383 stua_gc(1);
14384 stb_idict_destroy(stu__globaldict);
14385 stb_sdict_delete(stu__strings);
14386 stb_matcher_free(stu__lex_matcher);
14387 stb_arr_free(stu__gc_ptrlist);
14388 stb_arr_free(func_stack);
14389 stb_arr_free(stu__gc_root_stack);
14390 stu__globaldict = NULL;
14391 }
14392 }
14393
14394 void stua_run_script(char *s)
14395 {
14396 stua_init();
14397
14398 stu__curbuf = stu__bufstart = s;
14399 stu__nexttoken();
14400
14401 stu__flow = FLOW_normal;
14402
14403 if (!stu__compile_global_scope())
14404 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14405 stua_gc(1);
14406 }
14407 #endif // STB_DEFINE
14408 #endif // STB_STUA
14409
14410 #undef STB_EXTERN
14411 #endif // STB_INCLUDE_STB_H
14412
14413 /*
14414 ------------------------------------------------------------------------------
14415 This software is available under 2 licenses -- choose whichever you prefer.
14416 ------------------------------------------------------------------------------
14417 ALTERNATIVE A - MIT License
14418 Copyright (c) 2017 Sean Barrett
14419 Permission is hereby granted, free of charge, to any person obtaining a copy of
14420 this software and associated documentation files (the "Software"), to deal in
14421 the Software without restriction, including without limitation the rights to
14422 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14423 of the Software, and to permit persons to whom the Software is furnished to do
14424 so, subject to the following conditions:
14425 The above copyright notice and this permission notice shall be included in all
14426 copies or substantial portions of the Software.
14427 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14428 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14429 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14430 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14431 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14432 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
14433 SOFTWARE.
14434 ------------------------------------------------------------------------------
14435 ALTERNATIVE B - Public Domain (www.unlicense.org)
14436 This is free and unencumbered software released into the public domain.
14437 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
14438 software, either in source code form or as a compiled binary, for any purpose,
14439 commercial or non-commercial, and by any means.
14440 In jurisdictions that recognize copyright laws, the author or authors of this
14441 software dedicate any and all copyright interest in the software to the public
14442 domain. We make this dedication for the benefit of the public at large and to
14443 the detriment of our heirs and successors. We intend this dedication to be an
14444 overt act of relinquishment in perpetuity of all present and future rights to
14445 this software under copyright law.
14446 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14447 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14448 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14449 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
14450 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
14451 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14452 ------------------------------------------------------------------------------
14453 */
14454