comments updated
[henge/apc.git] / stb / stb.h
1 /* stb.h - v2.28 - 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.28 various new functionality
29 2.27 test _WIN32 not WIN32 in STB_THREADS
30 2.26 various warning & bugfixes
31 2.25 various warning & bugfixes
32 2.24 various warning & bugfixes
33 2.23 fix 2.22
34 2.22 64-bit fixes from '!='; fix stb_sdict_copy() to have preferred name
35 2.21 utf-8 decoder rejects "overlong" encodings; attempted 64-bit improvements
36 2.20 fix to hash "copy" function--reported by someone with handle "!="
37 2.19 ???
38 2.18 stb_readdir_subdirs_mask
39 2.17 stb_cfg_dir
40 2.16 fix stb_bgio_, add stb_bgio_stat(); begin a streaming wrapper
41 2.15 upgraded hash table template to allow:
42 - aggregate keys (explicit comparison func for EMPTY and DEL keys)
43 - "static" implementations (so they can be culled if unused)
44 2.14 stb_mprintf
45 2.13 reduce identifiable strings in STB_NO_STB_STRINGS
46 2.12 fix STB_ONLY -- lots of uint32s, TRUE/FALSE things had crept in
47 2.11 fix bug in stb_dirtree_get() which caused "c://path" sorts of stuff
48 2.10 STB_F(), STB_I() inline constants (also KI,KU,KF,KD)
49 2.09 stb_box_face_vertex_axis_side
50 2.08 bugfix stb_trimwhite()
51 2.07 colored printing in windows (why are we in 1985?)
52 2.06 comparison functions are now functions-that-return-functions and
53 accept a struct-offset as a parameter (not thread-safe)
54 2.05 compile and pass tests under Linux (but no threads); thread cleanup
55 2.04 stb_cubic_bezier_1d, smoothstep, avoid dependency on registry
56 2.03 ?
57 2.02 remove integrated documentation
58 2.01 integrate various fixes; stb_force_uniprocessor
59 2.00 revised stb_dupe to use multiple hashes
60 1.99 stb_charcmp
61 1.98 stb_arr_deleten, stb_arr_insertn
62 1.97 fix stb_newell_normal()
63 1.96 stb_hash_number()
64 1.95 hack stb__rec_max; clean up recursion code to use new functions
65 1.94 stb_dirtree; rename stb_extra to stb_ptrmap
66 1.93 stb_sem_new() API cleanup (no blockflag-starts blocked; use 'extra')
67 1.92 stb_threadqueue--multi reader/writer queue, fixed size or resizeable
68 1.91 stb_bgio_* for reading disk asynchronously
69 1.90 stb_mutex uses CRITICAL_REGION; new stb_sync primitive for thread
70 joining; workqueue supports stb_sync instead of stb_semaphore
71 1.89 support ';' in constant-string wildcards; stb_mutex wrapper (can
72 implement with EnterCriticalRegion eventually)
73 1.88 portable threading API (only for win32 so far); worker thread queue
74 1.87 fix wildcard handling in stb_readdir_recursive
75 1.86 support ';' in wildcards
76 1.85 make stb_regex work with non-constant strings;
77 beginnings of stb_introspect()
78 1.84 (forgot to make notes)
79 1.83 whoops, stb_keep_if_different wasn't deleting the temp file
80 1.82 bring back stb_compress from stb_file.h for cmirror
81 1.81 various bugfixes, STB_FASTMALLOC_INIT inits FASTMALLOC in release
82 1.80 stb_readdir returns utf8; write own utf8-utf16 because lib was wrong
83 1.79 stb_write
84 1.78 calloc() support for malloc wrapper, STB_FASTMALLOC
85 1.77 STB_FASTMALLOC
86 1.76 STB_STUA - Lua-like language; (stb_image, stb_csample, stb_bilinear)
87 1.75 alloc/free array of blocks; stb_hheap bug; a few stb_ps_ funcs;
88 hash*getkey, hash*copy; stb_bitset; stb_strnicmp; bugfix stb_bst
89 1.74 stb_replaceinplace; use stdlib C function to convert utf8 to UTF-16
90 1.73 fix performance bug & leak in stb_ischar (C++ port lost a 'static')
91 1.72 remove stb_block, stb_block_manager, stb_decompress (to stb_file.h)
92 1.71 stb_trimwhite, stb_tokens_nested, etc.
93 1.70 back out 1.69 because it might problemize mixed builds; stb_filec()
94 1.69 (stb_file returns 'char *' in C++)
95 1.68 add a special 'tree root' data type for stb_bst; stb_arr_end
96 1.67 full C++ port. (stb_block_manager)
97 1.66 stb_newell_normal
98 1.65 stb_lex_item_wild -- allow wildcard items which MUST match entirely
99 1.64 stb_data
100 1.63 stb_log_name
101 1.62 stb_define_sort; C++ cleanup
102 1.61 stb_hash_fast -- Paul Hsieh's hash function (beats Bob Jenkins'?)
103 1.60 stb_delete_directory_recursive
104 1.59 stb_readdir_recursive
105 1.58 stb_bst variant with parent pointer for O(1) iteration, not O(log N)
106 1.57 replace LCG random with Mersenne Twister (found a public domain one)
107 1.56 stb_perfect_hash, stb_ischar, stb_regex
108 1.55 new stb_bst API allows multiple BSTs per node (e.g. secondary keys)
109 1.54 bugfix: stb_define_hash, stb_wildmatch, regexp
110 1.53 stb_define_hash; recoded stb_extra, stb_sdict use it
111 1.52 stb_rand_define, stb_bst, stb_reverse
112 1.51 fix 'stb_arr_setlen(NULL, 0)'
113 1.50 stb_wordwrap
114 1.49 minor improvements to enable the scripting language
115 1.48 better approach for stb_arr using stb_malloc; more invasive, clearer
116 1.47 stb_lex (lexes stb.h at 1.5ML/s on 3Ghz P4; 60/70% of optimal/flex)
117 1.46 stb_wrapper_*, STB_MALLOC_WRAPPER
118 1.45 lightly tested DFA acceleration of regexp searching
119 1.44 wildcard matching & searching; regexp matching & searching
120 1.43 stb_temp
121 1.42 allow stb_arr to use stb_malloc/realloc; note this is global
122 1.41 make it compile in C++; (disable stb_arr in C++)
123 1.40 stb_dupe tweak; stb_swap; stb_substr
124 1.39 stb_dupe; improve stb_file_max to be less stupid
125 1.38 stb_sha1_file: generate sha1 for file, even > 4GB
126 1.37 stb_file_max; partial support for utf8 filenames in Windows
127 1.36 remove STB__NO_PREFIX - poor interaction with IDE, not worth it
128 streamline stb_arr to make it separately publishable
129 1.35 bugfixes for stb_sdict, stb_malloc(0), stristr
130 1.34 (streaming interfaces for stb_compress)
131 1.33 stb_alloc; bug in stb_getopt; remove stb_overflow
132 1.32 (stb_compress returns, smaller&faster; encode window & 64-bit len)
133 1.31 stb_prefix_count
134 1.30 (STB__NO_PREFIX - remove stb_ prefixes for personal projects)
135 1.29 stb_fput_varlen64, etc.
136 1.28 stb_sha1
137 1.27 ?
138 1.26 stb_extra
139 1.25 ?
140 1.24 stb_copyfile
141 1.23 stb_readdir
142 1.22 ?
143 1.21 ?
144 1.20 ?
145 1.19 ?
146 1.18 ?
147 1.17 ?
148 1.16 ?
149 1.15 stb_fixpath, stb_splitpath, stb_strchr2
150 1.14 stb_arr
151 1.13 ?stb, stb_log, stb_fatal
152 1.12 ?stb_hash2
153 1.11 miniML
154 1.10 stb_crc32, stb_adler32
155 1.09 stb_sdict
156 1.08 stb_bitreverse, stb_ispow2, stb_big32
157 stb_fopen, stb_fput_varlen, stb_fput_ranged
158 stb_fcmp, stb_feq
159 1.07 (stb_encompress)
160 1.06 stb_compress
161 1.05 stb_tokens, (stb_hheap)
162 1.04 stb_rand
163 1.03 ?(s-strings)
164 1.02 ?stb_filelen, stb_tokens
165 1.01 stb_tolower
166 1.00 stb_hash, stb_intcmp
167 stb_file, stb_stringfile, stb_fgets
168 stb_prefix, stb_strlower, stb_strtok
169 stb_image
170 (stb_array), (stb_arena)
171
172 Parenthesized items have since been removed.
173
174 LICENSE
175
176 This software is dual-licensed to the public domain and under the following
177 license: you are granted a perpetual, irrevocable license to copy, modify,
178 publish, and distribute this file as you see fit.
179
180 CREDITS
181
182 Written by Sean Barrett.
183
184 Fixes:
185 Philipp Wiesemann
186 Robert Nix
187 r-lyeh
188 blackpawn
189 Mojofreem@github
190 Ryan Whitworth
191 Vincent Isambart
192 Mike Sartain
193 Eugene Opalev
194 Tim Sjostrand
195 */
196
197 #ifndef STB__INCLUDE_STB_H
198 #define STB__INCLUDE_STB_H
199
200 #define STB_VERSION 1
201
202 #ifdef STB_INTROSPECT
203 #define STB_DEFINE
204 #endif
205
206 #ifdef STB_DEFINE_THREADS
207 #ifndef STB_DEFINE
208 #define STB_DEFINE
209 #endif
210 #ifndef STB_THREADS
211 #define STB_THREADS
212 #endif
213 #endif
214
215 #if defined(_WIN32) && !defined(__MINGW32__)
216 #ifndef _CRT_SECURE_NO_WARNINGS
217 #define _CRT_SECURE_NO_WARNINGS
218 #endif
219 #ifndef _CRT_NONSTDC_NO_DEPRECATE
220 #define _CRT_NONSTDC_NO_DEPRECATE
221 #endif
222 #ifndef _CRT_NON_CONFORMING_SWPRINTFS
223 #define _CRT_NON_CONFORMING_SWPRINTFS
224 #endif
225 #if !defined(_MSC_VER) || _MSC_VER > 1700
226 #include <intrin.h> // _BitScanReverse
227 #endif
228 #endif
229
230 #include <stdlib.h> // stdlib could have min/max
231 #include <stdio.h> // need FILE
232 #include <string.h> // stb_define_hash needs memcpy/memset
233 #include <time.h> // stb_dirtree
234 #ifdef __MINGW32__
235 #include <fcntl.h> // O_RDWR
236 #endif
237
238 #ifdef STB_PERSONAL
239 typedef int Bool;
240 #define False 0
241 #define True 1
242 #endif
243
244 #ifdef STB_MALLOC_WRAPPER_PAGED
245 #define STB_MALLOC_WRAPPER_DEBUG
246 #endif
247 #ifdef STB_MALLOC_WRAPPER_DEBUG
248 #define STB_MALLOC_WRAPPER
249 #endif
250 #ifdef STB_MALLOC_WRAPPER_FASTMALLOC
251 #define STB_FASTMALLOC
252 #define STB_MALLOC_WRAPPER
253 #endif
254
255 #ifdef STB_FASTMALLOC
256 #ifndef _WIN32
257 #undef STB_FASTMALLOC
258 #endif
259 #endif
260
261 #ifdef STB_DEFINE
262 #include <assert.h>
263 #include <stdarg.h>
264 #include <stddef.h>
265 #include <ctype.h>
266 #include <math.h>
267 #ifndef _WIN32
268 #include <unistd.h>
269 #else
270 #include <io.h> // _mktemp
271 #include <direct.h> // _rmdir
272 #endif
273 #include <sys/types.h> // stat()/_stat()
274 #include <sys/stat.h> // stat()/_stat()
275 #endif
276
277 #define stb_min(a,b) ((a) < (b) ? (a) : (b))
278 #define stb_max(a,b) ((a) > (b) ? (a) : (b))
279
280 #ifndef STB_ONLY
281 #if !defined(__cplusplus) && !defined(min) && !defined(max)
282 #define min(x,y) stb_min(x,y)
283 #define max(x,y) stb_max(x,y)
284 #endif
285
286 #ifndef M_PI
287 #define M_PI 3.14159265358979323846f
288 #endif
289
290 #ifndef TRUE
291 #define TRUE 1
292 #define FALSE 0
293 #endif
294
295 #ifndef deg2rad
296 #define deg2rad(a) ((a)*(M_PI/180))
297 #endif
298 #ifndef rad2deg
299 #define rad2deg(a) ((a)*(180/M_PI))
300 #endif
301
302 #ifndef swap
303 #ifndef __cplusplus
304 #define swap(TYPE,a,b) \
305 do { TYPE stb__t; stb__t = (a); (a) = (b); (b) = stb__t; } while (0)
306 #endif
307 #endif
308
309 typedef unsigned char uint8 ;
310 typedef signed char int8 ;
311 typedef unsigned short uint16;
312 typedef signed short int16;
313 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
314 typedef unsigned long uint32;
315 typedef signed long int32;
316 #else
317 typedef unsigned int uint32;
318 typedef signed int int32;
319 #endif
320
321 typedef unsigned char uchar ;
322 typedef unsigned short ushort;
323 typedef unsigned int uint ;
324 typedef unsigned long ulong ;
325
326 // produce compile errors if the sizes aren't right
327 typedef char stb__testsize16[sizeof(int16)==2];
328 typedef char stb__testsize32[sizeof(int32)==4];
329 #endif
330
331 #ifndef STB_TRUE
332 #define STB_TRUE 1
333 #define STB_FALSE 0
334 #endif
335
336 // if we're STB_ONLY, can't rely on uint32 or even uint, so all the
337 // variables we'll use herein need typenames prefixed with 'stb':
338 typedef unsigned char stb_uchar;
339 typedef unsigned char stb_uint8;
340 typedef unsigned int stb_uint;
341 typedef unsigned short stb_uint16;
342 typedef short stb_int16;
343 typedef signed char stb_int8;
344 #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
345 typedef unsigned long stb_uint32;
346 typedef long stb_int32;
347 #else
348 typedef unsigned int stb_uint32;
349 typedef int stb_int32;
350 #endif
351 typedef char stb__testsize2_16[sizeof(stb_uint16)==2 ? 1 : -1];
352 typedef char stb__testsize2_32[sizeof(stb_uint32)==4 ? 1 : -1];
353
354 #ifdef _MSC_VER
355 typedef unsigned __int64 stb_uint64;
356 typedef __int64 stb_int64;
357 #define STB_IMM_UINT64(literalui64) (literalui64##ui64)
358 #define STB_IMM_INT64(literali64) (literali64##i64)
359 #else
360 // ??
361 typedef unsigned long long stb_uint64;
362 typedef long long stb_int64;
363 #define STB_IMM_UINT64(literalui64) (literalui64##ULL)
364 #define STB_IMM_INT64(literali64) (literali64##LL)
365 #endif
366 typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1];
367
368 // add platform-specific ways of checking for sizeof(char*) == 8,
369 // and make those define STB_PTR64
370 #if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) || defined(__LP64__)
371 #define STB_PTR64
372 #endif
373
374 #ifdef STB_PTR64
375 typedef char stb__testsize2_ptr[sizeof(char *) == 8];
376 typedef stb_uint64 stb_uinta;
377 typedef stb_int64 stb_inta;
378 #else
379 typedef char stb__testsize2_ptr[sizeof(char *) == 4];
380 typedef stb_uint32 stb_uinta;
381 typedef stb_int32 stb_inta;
382 #endif
383 typedef char stb__testsize2_uinta[sizeof(stb_uinta)==sizeof(char*) ? 1 : -1];
384
385 // if so, we should define an int type that is the pointer size. until then,
386 // we'll have to make do with this (which is not the same at all!)
387
388 typedef union
389 {
390 unsigned int i;
391 void * p;
392 } stb_uintptr;
393
394
395 #ifdef __cplusplus
396 #define STB_EXTERN extern "C"
397 #else
398 #define STB_EXTERN extern
399 #endif
400
401 // check for well-known debug defines
402 #if defined(DEBUG) || defined(_DEBUG) || defined(DBG)
403 #ifndef NDEBUG
404 #define STB_DEBUG
405 #endif
406 #endif
407
408 #ifdef STB_DEBUG
409 #include <assert.h>
410 #endif
411
412
413 STB_EXTERN void stb_wrapper_malloc(void *newp, int sz, char *file, int line);
414 STB_EXTERN void stb_wrapper_free(void *oldp, char *file, int line);
415 STB_EXTERN void stb_wrapper_realloc(void *oldp, void *newp, int sz, char *file, int line);
416 STB_EXTERN void stb_wrapper_calloc(size_t num, size_t sz, char *file, int line);
417 STB_EXTERN void stb_wrapper_listall(void (*func)(void *ptr, int sz, char *file, int line));
418 STB_EXTERN void stb_wrapper_dump(char *filename);
419 STB_EXTERN int stb_wrapper_allocsize(void *oldp);
420 STB_EXTERN void stb_wrapper_check(void *oldp);
421
422 #ifdef STB_DEFINE
423 // this is a special function used inside malloc wrapper
424 // to do allocations that aren't tracked (to avoid
425 // reentrancy). Of course if someone _else_ wraps realloc,
426 // this breaks, but if they're doing that AND the malloc
427 // wrapper they need to explicitly check for reentrancy.
428 //
429 // only define realloc_raw() and we do realloc(NULL,sz)
430 // for malloc() and realloc(p,0) for free().
431 static void * stb__realloc_raw(void *p, int sz)
432 {
433 if (p == NULL) return malloc(sz);
434 if (sz == 0) { free(p); return NULL; }
435 return realloc(p,sz);
436 }
437 #endif
438
439 #ifdef _WIN32
440 STB_EXTERN void * stb_smalloc(size_t sz);
441 STB_EXTERN void stb_sfree(void *p);
442 STB_EXTERN void * stb_srealloc(void *p, size_t sz);
443 STB_EXTERN void * stb_scalloc(size_t n, size_t sz);
444 STB_EXTERN char * stb_sstrdup(char *s);
445 #endif
446
447 #ifdef STB_FASTMALLOC
448 #define malloc stb_smalloc
449 #define free stb_sfree
450 #define realloc stb_srealloc
451 #define strdup stb_sstrdup
452 #define calloc stb_scalloc
453 #endif
454
455 #ifndef STB_MALLOC_ALLCHECK
456 #define stb__check(p) 1
457 #else
458 #ifndef STB_MALLOC_WRAPPER
459 #error STB_MALLOC_ALLCHECK requires STB_MALLOC_WRAPPER
460 #else
461 #define stb__check(p) stb_mcheck(p)
462 #endif
463 #endif
464
465 #ifdef STB_MALLOC_WRAPPER
466 STB_EXTERN void * stb__malloc(int, char *, int);
467 STB_EXTERN void * stb__realloc(void *, int, char *, int);
468 STB_EXTERN void * stb__calloc(size_t n, size_t s, char *, int);
469 STB_EXTERN void stb__free(void *, char *file, int);
470 STB_EXTERN char * stb__strdup(char *s, char *file, int);
471 STB_EXTERN void stb_malloc_checkall(void);
472 STB_EXTERN void stb_malloc_check_counter(int init_delay, int rep_delay);
473 #ifndef STB_MALLOC_WRAPPER_DEBUG
474 #define stb_mcheck(p) 1
475 #else
476 STB_EXTERN int stb_mcheck(void *);
477 #endif
478
479
480 #ifdef STB_DEFINE
481
482 #ifdef STB_MALLOC_WRAPPER_DEBUG
483 #define STB__PAD 32
484 #define STB__BIAS 16
485 #define STB__SIG 0x51b01234
486 #define STB__FIXSIZE(sz) (((sz+3) & ~3) + STB__PAD)
487 #define STB__ptr(x,y) ((char *) (x) + (y))
488 #else
489 #define STB__ptr(x,y) (x)
490 #define STB__FIXSIZE(sz) (sz)
491 #endif
492
493 #ifdef STB_MALLOC_WRAPPER_DEBUG
494 int stb_mcheck(void *p)
495 {
496 unsigned int sz;
497 if (p == NULL) return 1;
498 p = ((char *) p) - STB__BIAS;
499 sz = * (unsigned int *) p;
500 assert(* (unsigned int *) STB__ptr(p,4) == STB__SIG);
501 assert(* (unsigned int *) STB__ptr(p,8) == STB__SIG);
502 assert(* (unsigned int *) STB__ptr(p,12) == STB__SIG);
503 assert(* (unsigned int *) STB__ptr(p,sz-4) == STB__SIG+1);
504 assert(* (unsigned int *) STB__ptr(p,sz-8) == STB__SIG+1);
505 assert(* (unsigned int *) STB__ptr(p,sz-12) == STB__SIG+1);
506 assert(* (unsigned int *) STB__ptr(p,sz-16) == STB__SIG+1);
507 stb_wrapper_check(STB__ptr(p, STB__BIAS));
508 return 1;
509 }
510
511 static void stb__check2(void *p, int sz, char *file, int line)
512 {
513 stb_mcheck(p);
514 }
515
516 void stb_malloc_checkall(void)
517 {
518 stb_wrapper_listall(stb__check2);
519 }
520 #else
521 void stb_malloc_checkall(void) { }
522 #endif
523
524 static int stb__malloc_wait=(1 << 30), stb__malloc_next_wait = (1 << 30), stb__malloc_iter;
525 void stb_malloc_check_counter(int init_delay, int rep_delay)
526 {
527 stb__malloc_wait = init_delay;
528 stb__malloc_next_wait = rep_delay;
529 }
530
531 void stb_mcheck_all(void)
532 {
533 #ifdef STB_MALLOC_WRAPPER_DEBUG
534 ++stb__malloc_iter;
535 if (--stb__malloc_wait <= 0) {
536 stb_malloc_checkall();
537 stb__malloc_wait = stb__malloc_next_wait;
538 }
539 #endif
540 }
541
542 #ifdef STB_MALLOC_WRAPPER_PAGED
543 #define STB__WINDOWS_PAGE (1 << 12)
544 #ifndef _WINDOWS_
545 STB_EXTERN __declspec(dllimport) void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
546 STB_EXTERN __declspec(dllimport) int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
547 #endif
548 #endif
549
550 static void *stb__malloc_final(int sz)
551 {
552 #ifdef STB_MALLOC_WRAPPER_PAGED
553 int aligned = (sz + STB__WINDOWS_PAGE - 1) & ~(STB__WINDOWS_PAGE-1);
554 char *p = VirtualAlloc(NULL, aligned + STB__WINDOWS_PAGE, 0x2000, 0x04); // RESERVE, READWRITE
555 if (p == NULL) return p;
556 VirtualAlloc(p, aligned, 0x1000, 0x04); // COMMIT, READWRITE
557 return p;
558 #else
559 return malloc(sz);
560 #endif
561 }
562
563 static void stb__free_final(void *p)
564 {
565 #ifdef STB_MALLOC_WRAPPER_PAGED
566 VirtualFree(p, 0, 0x8000); // RELEASE
567 #else
568 free(p);
569 #endif
570 }
571
572 int stb__malloc_failure;
573 static void *stb__realloc_final(void *p, int sz, int old_sz)
574 {
575 #ifdef STB_MALLOC_WRAPPER_PAGED
576 void *q = stb__malloc_final(sz);
577 if (q == NULL)
578 return ++stb__malloc_failure, q;
579 // @TODO: deal with p being smaller!
580 memcpy(q, p, sz < old_sz ? sz : old_sz);
581 stb__free_final(p);
582 return q;
583 #else
584 return realloc(p,sz);
585 #endif
586 }
587
588 void stb__free(void *p, char *file, int line)
589 {
590 stb_mcheck_all();
591 if (!p) return;
592 #ifdef STB_MALLOC_WRAPPER_DEBUG
593 stb_mcheck(p);
594 #endif
595 stb_wrapper_free(p,file,line);
596 #ifdef STB_MALLOC_WRAPPER_DEBUG
597 p = STB__ptr(p,-STB__BIAS);
598 * (unsigned int *) STB__ptr(p,0) = 0xdeadbeef;
599 * (unsigned int *) STB__ptr(p,4) = 0xdeadbeef;
600 * (unsigned int *) STB__ptr(p,8) = 0xdeadbeef;
601 * (unsigned int *) STB__ptr(p,12) = 0xdeadbeef;
602 #endif
603 stb__free_final(p);
604 }
605
606 void * stb__malloc(int sz, char *file, int line)
607 {
608 void *p;
609 stb_mcheck_all();
610 if (sz == 0) return NULL;
611 p = stb__malloc_final(STB__FIXSIZE(sz));
612 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
613 if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
614 if (p == NULL) {
615 ++stb__malloc_failure;
616 #ifdef STB_MALLOC_WRAPPER_DEBUG
617 stb_malloc_checkall();
618 #endif
619 return p;
620 }
621 #ifdef STB_MALLOC_WRAPPER_DEBUG
622 * (int *) STB__ptr(p,0) = STB__FIXSIZE(sz);
623 * (unsigned int *) STB__ptr(p,4) = STB__SIG;
624 * (unsigned int *) STB__ptr(p,8) = STB__SIG;
625 * (unsigned int *) STB__ptr(p,12) = STB__SIG;
626 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-4) = STB__SIG+1;
627 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-8) = STB__SIG+1;
628 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-12) = STB__SIG+1;
629 * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-16) = STB__SIG+1;
630 p = STB__ptr(p, STB__BIAS);
631 #endif
632 stb_wrapper_malloc(p,sz,file,line);
633 return p;
634 }
635
636 void * stb__realloc(void *p, int sz, char *file, int line)
637 {
638 void *q;
639
640 stb_mcheck_all();
641 if (p == NULL) return stb__malloc(sz,file,line);
642 if (sz == 0 ) { stb__free(p,file,line); return NULL; }
643
644 #ifdef STB_MALLOC_WRAPPER_DEBUG
645 stb_mcheck(p);
646 p = STB__ptr(p,-STB__BIAS);
647 #endif
648 #ifdef STB_MALLOC_WRAPPER_PAGED
649 {
650 int n = stb_wrapper_allocsize(STB__ptr(p,STB__BIAS));
651 if (!n)
652 stb_wrapper_check(STB__ptr(p,STB__BIAS));
653 q = stb__realloc_final(p, STB__FIXSIZE(sz), STB__FIXSIZE(n));
654 }
655 #else
656 q = realloc(p, STB__FIXSIZE(sz));
657 #endif
658 if (q == NULL)
659 return ++stb__malloc_failure, q;
660 #ifdef STB_MALLOC_WRAPPER_DEBUG
661 * (int *) STB__ptr(q,0) = STB__FIXSIZE(sz);
662 * (unsigned int *) STB__ptr(q,4) = STB__SIG;
663 * (unsigned int *) STB__ptr(q,8) = STB__SIG;
664 * (unsigned int *) STB__ptr(q,12) = STB__SIG;
665 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-4) = STB__SIG+1;
666 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-8) = STB__SIG+1;
667 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-12) = STB__SIG+1;
668 * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-16) = STB__SIG+1;
669
670 q = STB__ptr(q, STB__BIAS);
671 p = STB__ptr(p, STB__BIAS);
672 #endif
673 stb_wrapper_realloc(p,q,sz,file,line);
674 return q;
675 }
676
677 STB_EXTERN int stb_log2_ceil(unsigned int);
678 static void *stb__calloc(size_t n, size_t sz, char *file, int line)
679 {
680 void *q;
681 stb_mcheck_all();
682 if (n == 0 || sz == 0) return NULL;
683 if (stb_log2_ceil(n) + stb_log2_ceil(sz) >= 32) return NULL;
684 q = stb__malloc(n*sz, file, line);
685 if (q) memset(q, 0, n*sz);
686 return q;
687 }
688
689 char * stb__strdup(char *s, char *file, int line)
690 {
691 char *p;
692 stb_mcheck_all();
693 p = stb__malloc(strlen(s)+1, file, line);
694 if (!p) return p;
695 strcpy(p, s);
696 return p;
697 }
698 #endif // STB_DEFINE
699
700 #ifdef STB_FASTMALLOC
701 #undef malloc
702 #undef realloc
703 #undef free
704 #undef strdup
705 #undef calloc
706 #endif
707
708 // include everything that might define these, BEFORE making macros
709 #include <stdlib.h>
710 #include <string.h>
711 #include <malloc.h>
712
713 #define malloc(s) stb__malloc ( s, __FILE__, __LINE__)
714 #define realloc(p,s) stb__realloc(p,s, __FILE__, __LINE__)
715 #define calloc(n,s) stb__calloc (n,s, __FILE__, __LINE__)
716 #define free(p) stb__free (p, __FILE__, __LINE__)
717 #define strdup(p) stb__strdup (p, __FILE__, __LINE__)
718
719 #endif
720
721 //////////////////////////////////////////////////////////////////////////////
722 //
723 // Windows pretty display
724 //
725
726 STB_EXTERN void stbprint(const char *fmt, ...);
727 STB_EXTERN char *stb_sprintf(const char *fmt, ...);
728 STB_EXTERN char *stb_mprintf(const char *fmt, ...);
729 STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...);
730 STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v);
731
732 #ifdef STB_DEFINE
733
734 int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v)
735 {
736 int res;
737 #ifdef _WIN32
738 // Could use "_vsnprintf_s(s, n, _TRUNCATE, fmt, v)" ?
739 res = _vsnprintf(s,n,fmt,v);
740 #else
741 res = vsnprintf(s,n,fmt,v);
742 #endif
743 if (n) s[n-1] = 0;
744 // Unix returns length output would require, Windows returns negative when truncated.
745 return (res >= (int) n || res < 0) ? -1 : res;
746 }
747
748 int stb_snprintf(char *s, size_t n, const char *fmt, ...)
749 {
750 int res;
751 va_list v;
752 va_start(v,fmt);
753 res = stb_vsnprintf(s, n, fmt, v);
754 va_end(v);
755 return res;
756 }
757
758 char *stb_sprintf(const char *fmt, ...)
759 {
760 static char buffer[1024];
761 va_list v;
762 va_start(v,fmt);
763 stb_vsnprintf(buffer,1024,fmt,v);
764 va_end(v);
765 return buffer;
766 }
767
768 char *stb_mprintf(const char *fmt, ...)
769 {
770 static char buffer[1024];
771 va_list v;
772 va_start(v,fmt);
773 stb_vsnprintf(buffer,1024,fmt,v);
774 va_end(v);
775 return strdup(buffer);
776 }
777
778 #ifdef _WIN32
779
780 #ifndef _WINDOWS_
781 STB_EXTERN __declspec(dllimport) int __stdcall WriteConsoleA(void *, const void *, unsigned int, unsigned int *, void *);
782 STB_EXTERN __declspec(dllimport) void * __stdcall GetStdHandle(unsigned int);
783 STB_EXTERN __declspec(dllimport) int __stdcall SetConsoleTextAttribute(void *, unsigned short);
784 #endif
785
786 static void stb__print_one(void *handle, char *s, int len)
787 {
788 if (len)
789 if (WriteConsoleA(handle, s, len, NULL,NULL))
790 fwrite(s, 1, len, stdout); // if it fails, maybe redirected, so do normal
791 }
792
793 static void stb__print(char *s)
794 {
795 void *handle = GetStdHandle((unsigned int) -11); // STD_OUTPUT_HANDLE
796 int pad=0; // number of padding characters to add
797
798 char *t = s;
799 while (*s) {
800 int lpad;
801 while (*s && *s != '{') {
802 if (pad) {
803 if (*s == '\r' || *s == '\n')
804 pad = 0;
805 else if (s[0] == ' ' && s[1] == ' ') {
806 stb__print_one(handle, t, s-t);
807 t = s;
808 while (pad) {
809 stb__print_one(handle, t, 1);
810 --pad;
811 }
812 }
813 }
814 ++s;
815 }
816 if (!*s) break;
817 stb__print_one(handle, t, s-t);
818 if (s[1] == '{') {
819 ++s;
820 continue;
821 }
822
823 if (s[1] == '#') {
824 t = s+3;
825 if (isxdigit(s[2]))
826 if (isdigit(s[2]))
827 SetConsoleTextAttribute(handle, s[2] - '0');
828 else
829 SetConsoleTextAttribute(handle, tolower(s[2]) - 'a' + 10);
830 else {
831 SetConsoleTextAttribute(handle, 0x0f);
832 t=s+2;
833 }
834 } else if (s[1] == '!') {
835 SetConsoleTextAttribute(handle, 0x0c);
836 t = s+2;
837 } else if (s[1] == '@') {
838 SetConsoleTextAttribute(handle, 0x09);
839 t = s+2;
840 } else if (s[1] == '$') {
841 SetConsoleTextAttribute(handle, 0x0a);
842 t = s+2;
843 } else {
844 SetConsoleTextAttribute(handle, 0x08); // 0,7,8,15 => shades of grey
845 t = s+1;
846 }
847
848 lpad = (t-s);
849 s = t;
850 while (*s && *s != '}') ++s;
851 if (!*s) break;
852 stb__print_one(handle, t, s-t);
853 if (s[1] == '}') {
854 t = s+2;
855 } else {
856 pad += 1+lpad;
857 t = s+1;
858 }
859 s=t;
860 SetConsoleTextAttribute(handle, 0x07);
861 }
862 stb__print_one(handle, t, s-t);
863 SetConsoleTextAttribute(handle, 0x07);
864 }
865
866 void stbprint(const char *fmt, ...)
867 {
868 int res;
869 char buffer[1024];
870 char *tbuf = buffer;
871 va_list v;
872
873 va_start(v,fmt);
874 res = stb_vsnprintf(buffer, sizeof(buffer), fmt, v);
875 va_end(v);
876
877 if (res < 0) {
878 tbuf = (char *) malloc(16384);
879 va_start(v,fmt);
880 res = _vsnprintf(tbuf,16384, fmt, v);
881 va_end(v);
882 tbuf[16383] = 0;
883 }
884
885 stb__print(tbuf);
886
887 if (tbuf != buffer)
888 free(tbuf);
889 }
890
891 #else // _WIN32
892 void stbprint(const char *fmt, ...)
893 {
894 va_list v;
895 va_start(v,fmt);
896 vprintf(fmt,v);
897 va_end(v);
898 }
899 #endif // _WIN32
900 #endif // STB_DEFINE
901
902
903
904 //////////////////////////////////////////////////////////////////////////////
905 //
906 // Windows UTF8 filename handling
907 //
908 // Windows stupidly treats 8-bit filenames as some dopey code page,
909 // rather than utf-8. If we want to use utf8 filenames, we have to
910 // convert them to WCHAR explicitly and call WCHAR versions of the
911 // file functions. So, ok, we do.
912
913
914 #ifdef _WIN32
915 #define stb__fopen(x,y) _wfopen((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
916 #define stb__windows(x,y) x
917 #else
918 #define stb__fopen(x,y) fopen(x,y)
919 #define stb__windows(x,y) y
920 #endif
921
922
923 typedef unsigned short stb__wchar;
924
925 STB_EXTERN stb__wchar * stb_from_utf8(stb__wchar *buffer, char *str, int n);
926 STB_EXTERN char * stb_to_utf8 (char *buffer, stb__wchar *str, int n);
927
928 STB_EXTERN stb__wchar *stb__from_utf8(char *str);
929 STB_EXTERN stb__wchar *stb__from_utf8_alt(char *str);
930 STB_EXTERN char *stb__to_utf8(stb__wchar *str);
931
932
933 #ifdef STB_DEFINE
934 stb__wchar * stb_from_utf8(stb__wchar *buffer, char *ostr, int n)
935 {
936 unsigned char *str = (unsigned char *) ostr;
937 stb_uint32 c;
938 int i=0;
939 --n;
940 while (*str) {
941 if (i >= n)
942 return NULL;
943 if (!(*str & 0x80))
944 buffer[i++] = *str++;
945 else if ((*str & 0xe0) == 0xc0) {
946 if (*str < 0xc2) return NULL;
947 c = (*str++ & 0x1f) << 6;
948 if ((*str & 0xc0) != 0x80) return NULL;
949 buffer[i++] = c + (*str++ & 0x3f);
950 } else if ((*str & 0xf0) == 0xe0) {
951 if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return NULL;
952 if (*str == 0xed && str[1] > 0x9f) return NULL; // str[1] < 0x80 is checked below
953 c = (*str++ & 0x0f) << 12;
954 if ((*str & 0xc0) != 0x80) return NULL;
955 c += (*str++ & 0x3f) << 6;
956 if ((*str & 0xc0) != 0x80) return NULL;
957 buffer[i++] = c + (*str++ & 0x3f);
958 } else if ((*str & 0xf8) == 0xf0) {
959 if (*str > 0xf4) return NULL;
960 if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return NULL;
961 if (*str == 0xf4 && str[1] > 0x8f) return NULL; // str[1] < 0x80 is checked below
962 c = (*str++ & 0x07) << 18;
963 if ((*str & 0xc0) != 0x80) return NULL;
964 c += (*str++ & 0x3f) << 12;
965 if ((*str & 0xc0) != 0x80) return NULL;
966 c += (*str++ & 0x3f) << 6;
967 if ((*str & 0xc0) != 0x80) return NULL;
968 c += (*str++ & 0x3f);
969 // utf-8 encodings of values used in surrogate pairs are invalid
970 if ((c & 0xFFFFF800) == 0xD800) return NULL;
971 if (c >= 0x10000) {
972 c -= 0x10000;
973 if (i + 2 > n) return NULL;
974 buffer[i++] = 0xD800 | (0x3ff & (c >> 10));
975 buffer[i++] = 0xDC00 | (0x3ff & (c ));
976 }
977 } else
978 return NULL;
979 }
980 buffer[i] = 0;
981 return buffer;
982 }
983
984 char * stb_to_utf8(char *buffer, stb__wchar *str, int n)
985 {
986 int i=0;
987 --n;
988 while (*str) {
989 if (*str < 0x80) {
990 if (i+1 > n) return NULL;
991 buffer[i++] = (char) *str++;
992 } else if (*str < 0x800) {
993 if (i+2 > n) return NULL;
994 buffer[i++] = 0xc0 + (*str >> 6);
995 buffer[i++] = 0x80 + (*str & 0x3f);
996 str += 1;
997 } else if (*str >= 0xd800 && *str < 0xdc00) {
998 stb_uint32 c;
999 if (i+4 > n) return NULL;
1000 c = ((str[0] - 0xd800) << 10) + ((str[1]) - 0xdc00) + 0x10000;
1001 buffer[i++] = 0xf0 + (c >> 18);
1002 buffer[i++] = 0x80 + ((c >> 12) & 0x3f);
1003 buffer[i++] = 0x80 + ((c >> 6) & 0x3f);
1004 buffer[i++] = 0x80 + ((c ) & 0x3f);
1005 str += 2;
1006 } else if (*str >= 0xdc00 && *str < 0xe000) {
1007 return NULL;
1008 } else {
1009 if (i+3 > n) return NULL;
1010 buffer[i++] = 0xe0 + (*str >> 12);
1011 buffer[i++] = 0x80 + ((*str >> 6) & 0x3f);
1012 buffer[i++] = 0x80 + ((*str ) & 0x3f);
1013 str += 1;
1014 }
1015 }
1016 buffer[i] = 0;
1017 return buffer;
1018 }
1019
1020 stb__wchar *stb__from_utf8(char *str)
1021 {
1022 static stb__wchar buffer[4096];
1023 return stb_from_utf8(buffer, str, 4096);
1024 }
1025
1026 stb__wchar *stb__from_utf8_alt(char *str)
1027 {
1028 static stb__wchar buffer[64];
1029 return stb_from_utf8(buffer, str, 64);
1030 }
1031
1032 char *stb__to_utf8(stb__wchar *str)
1033 {
1034 static char buffer[4096];
1035 return stb_to_utf8(buffer, str, 4096);
1036 }
1037
1038 #endif
1039
1040 //////////////////////////////////////////////////////////////////////////////
1041 //
1042 // Miscellany
1043 //
1044
1045 STB_EXTERN void stb_fatal(char *fmt, ...);
1046 STB_EXTERN void stb_(char *fmt, ...);
1047 STB_EXTERN void stb_append_to_file(char *file, char *fmt, ...);
1048 STB_EXTERN void stb_log(int active);
1049 STB_EXTERN void stb_log_fileline(int active);
1050 STB_EXTERN void stb_log_name(char *filename);
1051
1052 STB_EXTERN void stb_swap(void *p, void *q, size_t sz);
1053 STB_EXTERN void *stb_copy(void *p, size_t sz);
1054 STB_EXTERN void stb_pointer_array_free(void *p, int len);
1055 STB_EXTERN void **stb_array_block_alloc(int count, int blocksize);
1056
1057 #define stb_arrcount(x) (sizeof(x)/sizeof((x)[0]))
1058
1059
1060 STB_EXTERN int stb__record_fileline(char *f, int n);
1061
1062 #ifdef STB_DEFINE
1063
1064 static char *stb__file;
1065 static int stb__line;
1066
1067 int stb__record_fileline(char *f, int n)
1068 {
1069 stb__file = f;
1070 stb__line = n;
1071 return 0;
1072 }
1073
1074 void stb_fatal(char *s, ...)
1075 {
1076 va_list a;
1077 if (stb__file)
1078 fprintf(stderr, "[%s:%d] ", stb__file, stb__line);
1079 va_start(a,s);
1080 fputs("Fatal error: ", stderr);
1081 vfprintf(stderr, s, a);
1082 va_end(a);
1083 fputs("\n", stderr);
1084 #ifdef STB_DEBUG
1085 #ifdef _MSC_VER
1086 #ifndef STB_PTR64
1087 __asm int 3; // trap to debugger!
1088 #else
1089 __debugbreak();
1090 #endif
1091 #else
1092 __builtin_trap();
1093 #endif
1094 #endif
1095 exit(1);
1096 }
1097
1098 static int stb__log_active=1, stb__log_fileline=1;
1099
1100 void stb_log(int active)
1101 {
1102 stb__log_active = active;
1103 }
1104
1105 void stb_log_fileline(int active)
1106 {
1107 stb__log_fileline = active;
1108 }
1109
1110 #ifdef STB_NO_STB_STRINGS
1111 char *stb__log_filename = "temp.log";
1112 #else
1113 char *stb__log_filename = "stb.log";
1114 #endif
1115
1116 void stb_log_name(char *s)
1117 {
1118 stb__log_filename = s;
1119 }
1120
1121 void stb_(char *s, ...)
1122 {
1123 if (stb__log_active) {
1124 FILE *f = fopen(stb__log_filename, "a");
1125 if (f) {
1126 va_list a;
1127 if (stb__log_fileline && stb__file)
1128 fprintf(f, "[%s:%4d] ", stb__file, stb__line);
1129 va_start(a,s);
1130 vfprintf(f, s, a);
1131 va_end(a);
1132 fputs("\n", f);
1133 fclose(f);
1134 }
1135 }
1136 }
1137
1138 void stb_append_to_file(char *filename, char *s, ...)
1139 {
1140 FILE *f = fopen(filename, "a");
1141 if (f) {
1142 va_list a;
1143 va_start(a,s);
1144 vfprintf(f, s, a);
1145 va_end(a);
1146 fputs("\n", f);
1147 fclose(f);
1148 }
1149 }
1150
1151
1152 typedef struct { char d[4]; } stb__4;
1153 typedef struct { char d[8]; } stb__8;
1154
1155 // optimize the small cases, though you shouldn't be calling this for those!
1156 void stb_swap(void *p, void *q, size_t sz)
1157 {
1158 char buffer[256];
1159 if (p == q) return;
1160 if (sz == 4) {
1161 stb__4 temp = * ( stb__4 *) p;
1162 * (stb__4 *) p = * ( stb__4 *) q;
1163 * (stb__4 *) q = temp;
1164 return;
1165 } else if (sz == 8) {
1166 stb__8 temp = * ( stb__8 *) p;
1167 * (stb__8 *) p = * ( stb__8 *) q;
1168 * (stb__8 *) q = temp;
1169 return;
1170 }
1171
1172 while (sz > sizeof(buffer)) {
1173 stb_swap(p, q, sizeof(buffer));
1174 p = (char *) p + sizeof(buffer);
1175 q = (char *) q + sizeof(buffer);
1176 sz -= sizeof(buffer);
1177 }
1178
1179 memcpy(buffer, p , sz);
1180 memcpy(p , q , sz);
1181 memcpy(q , buffer, sz);
1182 }
1183
1184 void *stb_copy(void *p, size_t sz)
1185 {
1186 void *q = malloc(sz);
1187 memcpy(q, p, sz);
1188 return q;
1189 }
1190
1191 void stb_pointer_array_free(void *q, int len)
1192 {
1193 void **p = (void **) q;
1194 int i;
1195 for (i=0; i < len; ++i)
1196 free(p[i]);
1197 }
1198
1199 void **stb_array_block_alloc(int count, int blocksize)
1200 {
1201 int i;
1202 char *p = (char *) malloc(sizeof(void *) * count + count * blocksize);
1203 void **q;
1204 if (p == NULL) return NULL;
1205 q = (void **) p;
1206 p += sizeof(void *) * count;
1207 for (i=0; i < count; ++i)
1208 q[i] = p + i * blocksize;
1209 return q;
1210 }
1211 #endif
1212
1213 #ifdef STB_DEBUG
1214 // tricky hack to allow recording FILE,LINE even in varargs functions
1215 #define STB__RECORD_FILE(x) (stb__record_fileline(__FILE__, __LINE__),(x))
1216 #define stb_log STB__RECORD_FILE(stb_log)
1217 #define stb_ STB__RECORD_FILE(stb_)
1218 #ifndef STB_FATAL_CLEAN
1219 #define stb_fatal STB__RECORD_FILE(stb_fatal)
1220 #endif
1221 #define STB__DEBUG(x) x
1222 #else
1223 #define STB__DEBUG(x)
1224 #endif
1225
1226 //////////////////////////////////////////////////////////////////////////////
1227 //
1228 // stb_temp
1229 //
1230
1231 #define stb_temp(block, sz) stb__temp(block, sizeof(block), (sz))
1232
1233 STB_EXTERN void * stb__temp(void *b, int b_sz, int want_sz);
1234 STB_EXTERN void stb_tempfree(void *block, void *ptr);
1235
1236 #ifdef STB_DEFINE
1237
1238 void * stb__temp(void *b, int b_sz, int want_sz)
1239 {
1240 if (b_sz >= want_sz)
1241 return b;
1242 else
1243 return malloc(want_sz);
1244 }
1245
1246 void stb_tempfree(void *b, void *p)
1247 {
1248 if (p != b)
1249 free(p);
1250 }
1251 #endif
1252
1253
1254 //////////////////////////////////////////////////////////////////////////////
1255 //
1256 // math/sampling operations
1257 //
1258
1259
1260 #define stb_lerp(t,a,b) ( (a) + (t) * (float) ((b)-(a)) )
1261 #define stb_unlerp(t,a,b) ( ((t) - (a)) / (float) ((b) - (a)) )
1262
1263 #define stb_clamp(x,xmin,xmax) ((x) < (xmin) ? (xmin) : (x) > (xmax) ? (xmax) : (x))
1264
1265 STB_EXTERN void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize);
1266 STB_EXTERN int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis);
1267 STB_EXTERN void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt);
1268
1269 STB_EXTERN int stb_float_eq(float x, float y, float delta, int max_ulps);
1270 STB_EXTERN int stb_is_prime(unsigned int m);
1271 STB_EXTERN unsigned int stb_power_of_two_nearest_prime(int n);
1272
1273 STB_EXTERN float stb_smoothstep(float t);
1274 STB_EXTERN float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3);
1275
1276 STB_EXTERN double stb_linear_remap(double x, double a, double b,
1277 double c, double d);
1278
1279 #ifdef STB_DEFINE
1280 float stb_smoothstep(float t)
1281 {
1282 return (3 - 2*t)*(t*t);
1283 }
1284
1285 float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3)
1286 {
1287 float it = 1-t;
1288 return it*it*it*p0 + 3*it*it*t*p1 + 3*it*t*t*p2 + t*t*t*p3;
1289 }
1290
1291 void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize)
1292 {
1293 int i,j;
1294 float p;
1295 normal[0] = normal[1] = normal[2] = 0;
1296 for (i=num_vert-1,j=0; j < num_vert; i=j++) {
1297 float *u = vert[i];
1298 float *v = vert[j];
1299 normal[0] += (u[1] - v[1]) * (u[2] + v[2]);
1300 normal[1] += (u[2] - v[2]) * (u[0] + v[0]);
1301 normal[2] += (u[0] - v[0]) * (u[1] + v[1]);
1302 }
1303 if (normalize) {
1304 p = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
1305 p = (float) (1.0 / sqrt(p));
1306 normal[0] *= p;
1307 normal[1] *= p;
1308 normal[2] *= p;
1309 }
1310 }
1311
1312 int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis)
1313 {
1314 static int box_vertices[6][4][3] =
1315 {
1316 { { 1,1,1 }, { 1,0,1 }, { 1,0,0 }, { 1,1,0 } },
1317 { { 0,0,0 }, { 0,0,1 }, { 0,1,1 }, { 0,1,0 } },
1318 { { 0,0,0 }, { 0,1,0 }, { 1,1,0 }, { 1,0,0 } },
1319 { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 } },
1320 { { 1,1,1 }, { 0,1,1 }, { 0,0,1 }, { 1,0,1 } },
1321 { { 1,1,1 }, { 1,1,0 }, { 0,1,0 }, { 0,1,1 } },
1322 };
1323 assert(face_number >= 0 && face_number < 6);
1324 assert(vertex_number >= 0 && vertex_number < 4);
1325 assert(axis >= 0 && axis < 3);
1326 return box_vertices[face_number][vertex_number][axis];
1327 }
1328
1329 void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt)
1330 {
1331 float sign = 1, p, cp = *curpos;
1332 if (cp == target_pos) return;
1333 if (target_pos < cp) {
1334 target_pos = -target_pos;
1335 cp = -cp;
1336 sign = -1;
1337 }
1338 // first decelerate
1339 if (cp < 0) {
1340 p = cp + deacc * dt;
1341 if (p > 0) {
1342 p = 0;
1343 dt = dt - cp / deacc;
1344 if (dt < 0) dt = 0;
1345 } else {
1346 dt = 0;
1347 }
1348 cp = p;
1349 }
1350 // now accelerate
1351 p = cp + acc*dt;
1352 if (p > target_pos) p = target_pos;
1353 *curpos = p * sign;
1354 // @TODO: testing
1355 }
1356
1357 float stb_quadratic_controller(float target_pos, float curpos, float maxvel, float maxacc, float dt, float *curvel)
1358 {
1359 return 0; // @TODO
1360 }
1361
1362 int stb_float_eq(float x, float y, float delta, int max_ulps)
1363 {
1364 if (fabs(x-y) <= delta) return 1;
1365 if (abs(*(int *)&x - *(int *)&y) <= max_ulps) return 1;
1366 return 0;
1367 }
1368
1369 int stb_is_prime(unsigned int m)
1370 {
1371 unsigned int i,j;
1372 if (m < 2) return 0;
1373 if (m == 2) return 1;
1374 if (!(m & 1)) return 0;
1375 if (m % 3 == 0) return (m == 3);
1376 for (i=5; (j=i*i), j <= m && j > i; i += 6) {
1377 if (m % i == 0) return 0;
1378 if (m % (i+2) == 0) return 0;
1379 }
1380 return 1;
1381 }
1382
1383 unsigned int stb_power_of_two_nearest_prime(int n)
1384 {
1385 static signed char tab[32] = { 0,0,0,0,1,0,-1,0,1,-1,-1,3,-1,0,-1,2,1,
1386 0,2,0,-1,-4,-1,5,-1,18,-2,15,2,-1,2,0 };
1387 if (!tab[0]) {
1388 int i;
1389 for (i=0; i < 32; ++i)
1390 tab[i] = (1 << i) + 2*tab[i] - 1;
1391 tab[1] = 2;
1392 tab[0] = 1;
1393 }
1394 if (n >= 32) return 0xfffffffb;
1395 return tab[n];
1396 }
1397
1398 double stb_linear_remap(double x, double x_min, double x_max,
1399 double out_min, double out_max)
1400 {
1401 return stb_lerp(stb_unlerp(x,x_min,x_max),out_min,out_max);
1402 }
1403 #endif
1404
1405 // create a macro so it's faster, but you can get at the function pointer
1406 #define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d)
1407
1408
1409 //////////////////////////////////////////////////////////////////////////////
1410 //
1411 // bit operations
1412 //
1413
1414 #define stb_big32(c) (((c)[0]<<24) + (c)[1]*65536 + (c)[2]*256 + (c)[3])
1415 #define stb_little32(c) (((c)[3]<<24) + (c)[2]*65536 + (c)[1]*256 + (c)[0])
1416 #define stb_big16(c) ((c)[0]*256 + (c)[1])
1417 #define stb_little16(c) ((c)[1]*256 + (c)[0])
1418
1419 STB_EXTERN int stb_bitcount(unsigned int a);
1420 STB_EXTERN unsigned int stb_bitreverse8(unsigned char n);
1421 STB_EXTERN unsigned int stb_bitreverse(unsigned int n);
1422
1423 STB_EXTERN int stb_is_pow2(unsigned int n);
1424 STB_EXTERN int stb_log2_ceil(unsigned int n);
1425 STB_EXTERN int stb_log2_floor(unsigned int n);
1426
1427 STB_EXTERN int stb_lowbit8(unsigned int n);
1428 STB_EXTERN int stb_highbit8(unsigned int n);
1429
1430 #ifdef STB_DEFINE
1431 int stb_bitcount(unsigned int a)
1432 {
1433 a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
1434 a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
1435 a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
1436 a = (a + (a >> 8)); // max 16 per 8 bits
1437 a = (a + (a >> 16)); // max 32 per 8 bits
1438 return a & 0xff;
1439 }
1440
1441 unsigned int stb_bitreverse8(unsigned char n)
1442 {
1443 n = ((n & 0xAA) >> 1) + ((n & 0x55) << 1);
1444 n = ((n & 0xCC) >> 2) + ((n & 0x33) << 2);
1445 return (unsigned char) ((n >> 4) + (n << 4));
1446 }
1447
1448 unsigned int stb_bitreverse(unsigned int n)
1449 {
1450 n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
1451 n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
1452 n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
1453 n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
1454 return (n >> 16) | (n << 16);
1455 }
1456
1457 int stb_is_pow2(unsigned int n)
1458 {
1459 return (n & (n-1)) == 0;
1460 }
1461
1462 // tricky use of 4-bit table to identify 5 bit positions (note the '-1')
1463 // 3-bit table would require another tree level; 5-bit table wouldn't save one
1464 #if defined(_WIN32) && !defined(__MINGW32__)
1465 #pragma warning(push)
1466 #pragma warning(disable: 4035) // disable warning about no return value
1467 int stb_log2_floor(unsigned int n)
1468 {
1469 #if _MSC_VER > 1700
1470 unsigned long i;
1471 _BitScanReverse(&i, n);
1472 return i != 0 ? i : -1;
1473 #else
1474 __asm {
1475 bsr eax,n
1476 jnz done
1477 mov eax,-1
1478 }
1479 done:;
1480 #endif
1481 }
1482 #pragma warning(pop)
1483 #else
1484 int stb_log2_floor(unsigned int n)
1485 {
1486 static signed char log2_4[16] = { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3 };
1487
1488 // 2 compares if n < 16, 3 compares otherwise
1489 if (n < (1U << 14))
1490 if (n < (1U << 4)) return 0 + log2_4[n ];
1491 else if (n < (1U << 9)) return 5 + log2_4[n >> 5];
1492 else return 10 + log2_4[n >> 10];
1493 else if (n < (1U << 24))
1494 if (n < (1U << 19)) return 15 + log2_4[n >> 15];
1495 else return 20 + log2_4[n >> 20];
1496 else if (n < (1U << 29)) return 25 + log2_4[n >> 25];
1497 else return 30 + log2_4[n >> 30];
1498 }
1499 #endif
1500
1501 // define ceil from floor
1502 int stb_log2_ceil(unsigned int n)
1503 {
1504 if (stb_is_pow2(n)) return stb_log2_floor(n);
1505 else return 1 + stb_log2_floor(n);
1506 }
1507
1508 int stb_highbit8(unsigned int n)
1509 {
1510 return stb_log2_ceil(n&255);
1511 }
1512
1513 int stb_lowbit8(unsigned int n)
1514 {
1515 static signed char lowbit4[16] = { -1,0,1,0, 2,0,1,0, 3,0,1,0, 2,0,1,0 };
1516 int k = lowbit4[n & 15];
1517 if (k >= 0) return k;
1518 k = lowbit4[(n >> 4) & 15];
1519 if (k >= 0) return k+4;
1520 return k;
1521 }
1522 #endif
1523
1524
1525
1526 //////////////////////////////////////////////////////////////////////////////
1527 //
1528 // qsort Compare Routines
1529 //
1530
1531 #ifdef _WIN32
1532 #define stb_stricmp(a,b) stricmp(a,b)
1533 #define stb_strnicmp(a,b,n) strnicmp(a,b,n)
1534 #else
1535 #define stb_stricmp(a,b) strcasecmp(a,b)
1536 #define stb_strnicmp(a,b,n) strncasecmp(a,b,n)
1537 #endif
1538
1539
1540 STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b);
1541 STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b);
1542 STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b);
1543 STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b);
1544 STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b);
1545 STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b);
1546
1547 #ifdef STB_DEFINE
1548 static int stb__intcmpoffset, stb__charcmpoffset, stb__strcmpoffset;
1549 static int stb__floatcmpoffset, stb__doublecmpoffset;
1550
1551 int stb__intcmp(const void *a, const void *b)
1552 {
1553 const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
1554 const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
1555 return p < q ? -1 : p > q;
1556 }
1557
1558 int stb__charcmp(const void *a, const void *b)
1559 {
1560 const int p = *(const unsigned char *) ((const char *) a + stb__charcmpoffset);
1561 const int q = *(const unsigned char *) ((const char *) b + stb__charcmpoffset);
1562 return p < q ? -1 : p > q;
1563 }
1564
1565 int stb__floatcmp(const void *a, const void *b)
1566 {
1567 const float p = *(const float *) ((const char *) a + stb__floatcmpoffset);
1568 const float q = *(const float *) ((const char *) b + stb__floatcmpoffset);
1569 return p < q ? -1 : p > q;
1570 }
1571
1572 int stb__doublecmp(const void *a, const void *b)
1573 {
1574 const double p = *(const double *) ((const char *) a + stb__doublecmpoffset);
1575 const double q = *(const double *) ((const char *) b + stb__doublecmpoffset);
1576 return p < q ? -1 : p > q;
1577 }
1578
1579 int stb__qsort_strcmp(const void *a, const void *b)
1580 {
1581 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1582 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1583 return strcmp(p,q);
1584 }
1585
1586 int stb__qsort_stricmp(const void *a, const void *b)
1587 {
1588 const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
1589 const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
1590 return stb_stricmp(p,q);
1591 }
1592
1593 int (*stb_intcmp(int offset))(const void *, const void *)
1594 {
1595 stb__intcmpoffset = offset;
1596 return &stb__intcmp;
1597 }
1598
1599 int (*stb_charcmp(int offset))(const void *, const void *)
1600 {
1601 stb__charcmpoffset = offset;
1602 return &stb__charcmp;
1603 }
1604
1605 int (*stb_qsort_strcmp(int offset))(const void *, const void *)
1606 {
1607 stb__strcmpoffset = offset;
1608 return &stb__qsort_strcmp;
1609 }
1610
1611 int (*stb_qsort_stricmp(int offset))(const void *, const void *)
1612 {
1613 stb__strcmpoffset = offset;
1614 return &stb__qsort_stricmp;
1615 }
1616
1617 int (*stb_floatcmp(int offset))(const void *, const void *)
1618 {
1619 stb__floatcmpoffset = offset;
1620 return &stb__floatcmp;
1621 }
1622
1623 int (*stb_doublecmp(int offset))(const void *, const void *)
1624 {
1625 stb__doublecmpoffset = offset;
1626 return &stb__doublecmp;
1627 }
1628
1629 #endif
1630
1631 //////////////////////////////////////////////////////////////////////////////
1632 //
1633 // Binary Search Toolkit
1634 //
1635
1636 typedef struct
1637 {
1638 int minval, maxval, guess;
1639 int mode, step;
1640 } stb_search;
1641
1642 STB_EXTERN int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest);
1643 STB_EXTERN int stb_search_open(stb_search *s, int minv, int find_smallest);
1644 STB_EXTERN int stb_probe(stb_search *s, int compare, int *result); // return 0 when done
1645
1646 #ifdef STB_DEFINE
1647 enum
1648 {
1649 STB_probe_binary_smallest,
1650 STB_probe_binary_largest,
1651 STB_probe_open_smallest,
1652 STB_probe_open_largest,
1653 };
1654
1655 static int stb_probe_guess(stb_search *s, int *result)
1656 {
1657 switch(s->mode) {
1658 case STB_probe_binary_largest:
1659 if (s->minval == s->maxval) {
1660 *result = s->minval;
1661 return 0;
1662 }
1663 assert(s->minval < s->maxval);
1664 // if a < b, then a < p <= b
1665 s->guess = s->minval + (((unsigned) s->maxval - s->minval + 1) >> 1);
1666 break;
1667
1668 case STB_probe_binary_smallest:
1669 if (s->minval == s->maxval) {
1670 *result = s->minval;
1671 return 0;
1672 }
1673 assert(s->minval < s->maxval);
1674 // if a < b, then a <= p < b
1675 s->guess = s->minval + (((unsigned) s->maxval - s->minval) >> 1);
1676 break;
1677 case STB_probe_open_smallest:
1678 case STB_probe_open_largest:
1679 s->guess = s->maxval; // guess the current maxval
1680 break;
1681 }
1682 *result = s->guess;
1683 return 1;
1684 }
1685
1686 int stb_probe(stb_search *s, int compare, int *result)
1687 {
1688 switch(s->mode) {
1689 case STB_probe_open_smallest:
1690 case STB_probe_open_largest: {
1691 if (compare <= 0) {
1692 // then it lies within minval & maxval
1693 if (s->mode == STB_probe_open_smallest)
1694 s->mode = STB_probe_binary_smallest;
1695 else
1696 s->mode = STB_probe_binary_largest;
1697 } else {
1698 // otherwise, we need to probe larger
1699 s->minval = s->maxval + 1;
1700 s->maxval = s->minval + s->step;
1701 s->step += s->step;
1702 }
1703 break;
1704 }
1705 case STB_probe_binary_smallest: {
1706 // if compare < 0, then s->minval <= a < p
1707 // if compare = 0, then s->minval <= a <= p
1708 // if compare > 0, then p < a <= s->maxval
1709 if (compare <= 0)
1710 s->maxval = s->guess;
1711 else
1712 s->minval = s->guess+1;
1713 break;
1714 }
1715 case STB_probe_binary_largest: {
1716 // if compare < 0, then s->minval <= a < p
1717 // if compare = 0, then p <= a <= s->maxval
1718 // if compare > 0, then p < a <= s->maxval
1719 if (compare < 0)
1720 s->maxval = s->guess-1;
1721 else
1722 s->minval = s->guess;
1723 break;
1724 }
1725 }
1726 return stb_probe_guess(s, result);
1727 }
1728
1729 int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest)
1730 {
1731 int r;
1732 if (maxv < minv) return minv-1;
1733 s->minval = minv;
1734 s->maxval = maxv;
1735 s->mode = find_smallest ? STB_probe_binary_smallest : STB_probe_binary_largest;
1736 stb_probe_guess(s, &r);
1737 return r;
1738 }
1739
1740 int stb_search_open(stb_search *s, int minv, int find_smallest)
1741 {
1742 int r;
1743 s->step = 4;
1744 s->minval = minv;
1745 s->maxval = minv+s->step;
1746 s->mode = find_smallest ? STB_probe_open_smallest : STB_probe_open_largest;
1747 stb_probe_guess(s, &r);
1748 return r;
1749 }
1750 #endif
1751
1752 //////////////////////////////////////////////////////////////////////////////
1753 //
1754 // String Processing
1755 //
1756
1757 #define stb_prefixi(s,t) (0==stb_strnicmp((s),(t),strlen(t)))
1758
1759 enum stb_splitpath_flag
1760 {
1761 STB_PATH = 1,
1762 STB_FILE = 2,
1763 STB_EXT = 4,
1764 STB_PATH_FILE = STB_PATH + STB_FILE,
1765 STB_FILE_EXT = STB_FILE + STB_EXT,
1766 STB_EXT_NO_PERIOD = 8,
1767 };
1768
1769 STB_EXTERN char * stb_skipwhite(char *s);
1770 STB_EXTERN char * stb_trimwhite(char *s);
1771 STB_EXTERN char * stb_skipnewline(char *s);
1772 STB_EXTERN char * stb_strncpy(char *s, char *t, int n);
1773 STB_EXTERN char * stb_substr(char *t, int n);
1774 STB_EXTERN char * stb_duplower(char *s);
1775 STB_EXTERN void stb_tolower (char *s);
1776 STB_EXTERN char * stb_strchr2 (char *s, char p1, char p2);
1777 STB_EXTERN char * stb_strrchr2(char *s, char p1, char p2);
1778 STB_EXTERN char * stb_strtok(char *output, char *src, char *delimit);
1779 STB_EXTERN char * stb_strtok_keep(char *output, char *src, char *delimit);
1780 STB_EXTERN char * stb_strtok_invert(char *output, char *src, char *allowed);
1781 STB_EXTERN char * stb_dupreplace(char *s, char *find, char *replace);
1782 STB_EXTERN void stb_replaceinplace(char *s, char *find, char *replace);
1783 STB_EXTERN char * stb_splitpath(char *output, char *src, int flag);
1784 STB_EXTERN char * stb_splitpathdup(char *src, int flag);
1785 STB_EXTERN char * stb_replacedir(char *output, char *src, char *dir);
1786 STB_EXTERN char * stb_replaceext(char *output, char *src, char *ext);
1787 STB_EXTERN void stb_fixpath(char *path);
1788 STB_EXTERN char * stb_shorten_path_readable(char *path, int max_len);
1789 STB_EXTERN int stb_suffix (char *s, char *t);
1790 STB_EXTERN int stb_suffixi(char *s, char *t);
1791 STB_EXTERN int stb_prefix (char *s, char *t);
1792 STB_EXTERN char * stb_strichr(char *s, char t);
1793 STB_EXTERN char * stb_stristr(char *s, char *t);
1794 STB_EXTERN int stb_prefix_count(char *s, char *t);
1795 STB_EXTERN char * stb_plural(int n); // "s" or ""
1796 STB_EXTERN size_t stb_strscpy(char *d, const char *s, size_t n);
1797
1798 STB_EXTERN char **stb_tokens(char *src, char *delimit, int *count);
1799 STB_EXTERN char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1800 STB_EXTERN char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
1801 STB_EXTERN char **stb_tokens_allowempty(char *src, char *delimit, int *count);
1802 STB_EXTERN char **stb_tokens_stripwhite(char *src, char *delimit, int *count);
1803 STB_EXTERN char **stb_tokens_withdelim(char *src, char *delimit, int *count);
1804 STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count);
1805 // with 'quoted', allow delimiters to appear inside quotation marks, and don't
1806 // strip whitespace inside them (and we delete the quotation marks unless they
1807 // appear back to back, in which case they're considered escaped)
1808
1809 #ifdef STB_DEFINE
1810
1811 size_t stb_strscpy(char *d, const char *s, size_t n)
1812 {
1813 size_t len = strlen(s);
1814 if (len >= n) {
1815 if (n) d[0] = 0;
1816 return 0;
1817 }
1818 strcpy(d,s);
1819 return len + 1;
1820 }
1821
1822 char *stb_plural(int n)
1823 {
1824 return n == 1 ? "" : "s";
1825 }
1826
1827 int stb_prefix(char *s, char *t)
1828 {
1829 while (*t)
1830 if (*s++ != *t++)
1831 return STB_FALSE;
1832 return STB_TRUE;
1833 }
1834
1835 int stb_prefix_count(char *s, char *t)
1836 {
1837 int c=0;
1838 while (*t) {
1839 if (*s++ != *t++)
1840 break;
1841 ++c;
1842 }
1843 return c;
1844 }
1845
1846 int stb_suffix(char *s, char *t)
1847 {
1848 size_t n = strlen(s);
1849 size_t m = strlen(t);
1850 if (m <= n)
1851 return 0 == strcmp(s+n-m, t);
1852 else
1853 return 0;
1854 }
1855
1856 int stb_suffixi(char *s, char *t)
1857 {
1858 size_t n = strlen(s);
1859 size_t m = strlen(t);
1860 if (m <= n)
1861 return 0 == stb_stricmp(s+n-m, t);
1862 else
1863 return 0;
1864 }
1865
1866 // originally I was using this table so that I could create known sentinel
1867 // values--e.g. change whitetable[0] to be true if I was scanning for whitespace,
1868 // and false if I was scanning for nonwhite. I don't appear to be using that
1869 // functionality anymore (I do for tokentable, though), so just replace it
1870 // with isspace()
1871 char *stb_skipwhite(char *s)
1872 {
1873 while (isspace((unsigned char) *s)) ++s;
1874 return s;
1875 }
1876
1877 char *stb_skipnewline(char *s)
1878 {
1879 if (s[0] == '\r' || s[0] == '\n') {
1880 if (s[0]+s[1] == '\r' + '\n') ++s;
1881 ++s;
1882 }
1883 return s;
1884 }
1885
1886 char *stb_trimwhite(char *s)
1887 {
1888 int i,n;
1889 s = stb_skipwhite(s);
1890 n = (int) strlen(s);
1891 for (i=n-1; i >= 0; --i)
1892 if (!isspace(s[i]))
1893 break;
1894 s[i+1] = 0;
1895 return s;
1896 }
1897
1898 char *stb_strncpy(char *s, char *t, int n)
1899 {
1900 strncpy(s,t,n);
1901 s[n-1] = 0;
1902 return s;
1903 }
1904
1905 char *stb_substr(char *t, int n)
1906 {
1907 char *a;
1908 int z = (int) strlen(t);
1909 if (z < n) n = z;
1910 a = (char *) malloc(n+1);
1911 strncpy(a,t,n);
1912 a[n] = 0;
1913 return a;
1914 }
1915
1916 char *stb_duplower(char *s)
1917 {
1918 char *p = strdup(s), *q = p;
1919 while (*q) {
1920 *q = tolower(*q);
1921 ++q;
1922 }
1923 return p;
1924 }
1925
1926 void stb_tolower(char *s)
1927 {
1928 while (*s) {
1929 *s = tolower(*s);
1930 ++s;
1931 }
1932 }
1933
1934 char *stb_strchr2(char *s, char x, char y)
1935 {
1936 for(; *s; ++s)
1937 if (*s == x || *s == y)
1938 return s;
1939 return NULL;
1940 }
1941
1942 char *stb_strrchr2(char *s, char x, char y)
1943 {
1944 char *r = NULL;
1945 for(; *s; ++s)
1946 if (*s == x || *s == y)
1947 r = s;
1948 return r;
1949 }
1950
1951 char *stb_strichr(char *s, char t)
1952 {
1953 if (tolower(t) == toupper(t))
1954 return strchr(s,t);
1955 return stb_strchr2(s, (char) tolower(t), (char) toupper(t));
1956 }
1957
1958 char *stb_stristr(char *s, char *t)
1959 {
1960 size_t n = strlen(t);
1961 char *z;
1962 if (n==0) return s;
1963 while ((z = stb_strichr(s, *t)) != NULL) {
1964 if (0==stb_strnicmp(z, t, n))
1965 return z;
1966 s = z+1;
1967 }
1968 return NULL;
1969 }
1970
1971 static char *stb_strtok_raw(char *output, char *src, char *delimit, int keep, int invert)
1972 {
1973 if (invert) {
1974 while (*src && strchr(delimit, *src) != NULL) {
1975 *output++ = *src++;
1976 }
1977 } else {
1978 while (*src && strchr(delimit, *src) == NULL) {
1979 *output++ = *src++;
1980 }
1981 }
1982 *output = 0;
1983 if (keep)
1984 return src;
1985 else
1986 return *src ? src+1 : src;
1987 }
1988
1989 char *stb_strtok(char *output, char *src, char *delimit)
1990 {
1991 return stb_strtok_raw(output, src, delimit, 0, 0);
1992 }
1993
1994 char *stb_strtok_keep(char *output, char *src, char *delimit)
1995 {
1996 return stb_strtok_raw(output, src, delimit, 1, 0);
1997 }
1998
1999 char *stb_strtok_invert(char *output, char *src, char *delimit)
2000 {
2001 return stb_strtok_raw(output, src, delimit, 1,1);
2002 }
2003
2004 static char **stb_tokens_raw(char *src_, char *delimit, int *count,
2005 int stripwhite, int allow_empty, char *start, char *end)
2006 {
2007 int nested = 0;
2008 unsigned char *src = (unsigned char *) src_;
2009 static char stb_tokentable[256]; // rely on static initializion to 0
2010 static char stable[256],etable[256];
2011 char *out;
2012 char **result;
2013 int num=0;
2014 unsigned char *s;
2015
2016 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 1;
2017 if (start) {
2018 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2019 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2020 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2021 }
2022 stable[0] = 1;
2023
2024 // two passes through: the first time, counting how many
2025 s = (unsigned char *) src;
2026 while (*s) {
2027 // state: just found delimiter
2028 // skip further delimiters
2029 if (!allow_empty) {
2030 stb_tokentable[0] = 0;
2031 while (stb_tokentable[*s])
2032 ++s;
2033 if (!*s) break;
2034 }
2035 ++num;
2036 // skip further non-delimiters
2037 stb_tokentable[0] = 1;
2038 if (stripwhite == 2) { // quoted strings
2039 while (!stb_tokentable[*s]) {
2040 if (*s != '"')
2041 ++s;
2042 else {
2043 ++s;
2044 if (*s == '"')
2045 ++s; // "" -> ", not start a string
2046 else {
2047 // begin a string
2048 while (*s) {
2049 if (s[0] == '"') {
2050 if (s[1] == '"') s += 2; // "" -> "
2051 else { ++s; break; } // terminating "
2052 } else
2053 ++s;
2054 }
2055 }
2056 }
2057 }
2058 } else
2059 while (nested || !stb_tokentable[*s]) {
2060 if (stable[*s]) {
2061 if (!*s) break;
2062 if (end ? etable[*s] : nested)
2063 --nested;
2064 else
2065 ++nested;
2066 }
2067 ++s;
2068 }
2069 if (allow_empty) {
2070 if (*s) ++s;
2071 }
2072 }
2073 // now num has the actual count... malloc our output structure
2074 // need space for all the strings: strings won't be any longer than
2075 // original input, since for every '\0' there's at least one delimiter
2076 result = (char **) malloc(sizeof(*result) * (num+1) + (s-src+1));
2077 if (result == NULL) return result;
2078 out = (char *) (result + (num+1));
2079 // second pass: copy out the data
2080 s = (unsigned char *) src;
2081 num = 0;
2082 nested = 0;
2083 while (*s) {
2084 char *last_nonwhite;
2085 // state: just found delimiter
2086 // skip further delimiters
2087 if (!allow_empty) {
2088 stb_tokentable[0] = 0;
2089 if (stripwhite)
2090 while (stb_tokentable[*s] || isspace(*s))
2091 ++s;
2092 else
2093 while (stb_tokentable[*s])
2094 ++s;
2095 } else if (stripwhite) {
2096 while (isspace(*s)) ++s;
2097 }
2098 if (!*s) break;
2099 // we're past any leading delimiters and whitespace
2100 result[num] = out;
2101 ++num;
2102 // copy non-delimiters
2103 stb_tokentable[0] = 1;
2104 last_nonwhite = out-1;
2105 if (stripwhite == 2) {
2106 while (!stb_tokentable[*s]) {
2107 if (*s != '"') {
2108 if (!isspace(*s)) last_nonwhite = out;
2109 *out++ = *s++;
2110 } else {
2111 ++s;
2112 if (*s == '"') {
2113 if (!isspace(*s)) last_nonwhite = out;
2114 *out++ = *s++; // "" -> ", not start string
2115 } else {
2116 // begin a quoted string
2117 while (*s) {
2118 if (s[0] == '"') {
2119 if (s[1] == '"') { *out++ = *s; s += 2; }
2120 else { ++s; break; } // terminating "
2121 } else
2122 *out++ = *s++;
2123 }
2124 last_nonwhite = out-1; // all in quotes counts as non-white
2125 }
2126 }
2127 }
2128 } else {
2129 while (nested || !stb_tokentable[*s]) {
2130 if (!isspace(*s)) last_nonwhite = out;
2131 if (stable[*s]) {
2132 if (!*s) break;
2133 if (end ? etable[*s] : nested)
2134 --nested;
2135 else
2136 ++nested;
2137 }
2138 *out++ = *s++;
2139 }
2140 }
2141
2142 if (stripwhite) // rewind to last non-whitespace char
2143 out = last_nonwhite+1;
2144 *out++ = '\0';
2145
2146 if (*s) ++s; // skip delimiter
2147 }
2148 s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 0;
2149 if (start) {
2150 s = (unsigned char *) start; while (*s) stable[*s++] = 1;
2151 s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
2152 s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
2153 }
2154 if (count != NULL) *count = num;
2155 result[num] = 0;
2156 return result;
2157 }
2158
2159 char **stb_tokens(char *src, char *delimit, int *count)
2160 {
2161 return stb_tokens_raw(src,delimit,count,0,0,0,0);
2162 }
2163
2164 char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2165 {
2166 return stb_tokens_raw(src,delimit,count,0,0,nest_in,nest_out);
2167 }
2168
2169 char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
2170 {
2171 return stb_tokens_raw(src,delimit,count,0,1,nest_in,nest_out);
2172 }
2173
2174 char **stb_tokens_allowempty(char *src, char *delimit, int *count)
2175 {
2176 return stb_tokens_raw(src,delimit,count,0,1,0,0);
2177 }
2178
2179 char **stb_tokens_stripwhite(char *src, char *delimit, int *count)
2180 {
2181 return stb_tokens_raw(src,delimit,count,1,1,0,0);
2182 }
2183
2184 char **stb_tokens_quoted(char *src, char *delimit, int *count)
2185 {
2186 return stb_tokens_raw(src,delimit,count,2,1,0,0);
2187 }
2188
2189 char *stb_dupreplace(char *src, char *find, char *replace)
2190 {
2191 size_t len_find = strlen(find);
2192 size_t len_replace = strlen(replace);
2193 int count = 0;
2194
2195 char *s,*p,*q;
2196
2197 s = strstr(src, find);
2198 if (s == NULL) return strdup(src);
2199 do {
2200 ++count;
2201 s = strstr(s + len_find, find);
2202 } while (s != NULL);
2203
2204 p = (char *) malloc(strlen(src) + count * (len_replace - len_find) + 1);
2205 if (p == NULL) return p;
2206 q = p;
2207 s = src;
2208 for (;;) {
2209 char *t = strstr(s, find);
2210 if (t == NULL) {
2211 strcpy(q,s);
2212 assert(strlen(p) == strlen(src) + count*(len_replace-len_find));
2213 return p;
2214 }
2215 memcpy(q, s, t-s);
2216 q += t-s;
2217 memcpy(q, replace, len_replace);
2218 q += len_replace;
2219 s = t + len_find;
2220 }
2221 }
2222
2223 void stb_replaceinplace(char *src, char *find, char *replace)
2224 {
2225 size_t len_find = strlen(find);
2226 size_t len_replace = strlen(replace);
2227 int delta;
2228
2229 char *s,*p,*q;
2230
2231 delta = len_replace - len_find;
2232 assert(delta <= 0);
2233 if (delta > 0) return;
2234
2235 p = strstr(src, find);
2236 if (p == NULL) return;
2237
2238 s = q = p;
2239 while (*s) {
2240 memcpy(q, replace, len_replace);
2241 p += len_find;
2242 q += len_replace;
2243 s = strstr(p, find);
2244 if (s == NULL) s = p + strlen(p);
2245 memmove(q, p, s-p);
2246 q += s-p;
2247 p = s;
2248 }
2249 *q = 0;
2250 }
2251
2252 void stb_fixpath(char *path)
2253 {
2254 for(; *path; ++path)
2255 if (*path == '\\')
2256 *path = '/';
2257 }
2258
2259 void stb__add_section(char *buffer, char *data, int curlen, int newlen)
2260 {
2261 if (newlen < curlen) {
2262 int z1 = newlen >> 1, z2 = newlen-z1;
2263 memcpy(buffer, data, z1-1);
2264 buffer[z1-1] = '.';
2265 buffer[z1-0] = '.';
2266 memcpy(buffer+z1+1, data+curlen-z2+1, z2-1);
2267 } else
2268 memcpy(buffer, data, curlen);
2269 }
2270
2271 char * stb_shorten_path_readable(char *path, int len)
2272 {
2273 static char buffer[1024];
2274 int n = strlen(path),n1,n2,r1,r2;
2275 char *s;
2276 if (n <= len) return path;
2277 if (len > 1024) return path;
2278 s = stb_strrchr2(path, '/', '\\');
2279 if (s) {
2280 n1 = s - path + 1;
2281 n2 = n - n1;
2282 ++s;
2283 } else {
2284 n1 = 0;
2285 n2 = n;
2286 s = path;
2287 }
2288 // now we need to reduce r1 and r2 so that they fit in len
2289 if (n1 < len>>1) {
2290 r1 = n1;
2291 r2 = len - r1;
2292 } else if (n2 < len >> 1) {
2293 r2 = n2;
2294 r1 = len - r2;
2295 } else {
2296 r1 = n1 * len / n;
2297 r2 = n2 * len / n;
2298 if (r1 < len>>2) r1 = len>>2, r2 = len-r1;
2299 if (r2 < len>>2) r2 = len>>2, r1 = len-r2;
2300 }
2301 assert(r1 <= n1 && r2 <= n2);
2302 if (n1)
2303 stb__add_section(buffer, path, n1, r1);
2304 stb__add_section(buffer+r1, s, n2, r2);
2305 buffer[len] = 0;
2306 return buffer;
2307 }
2308
2309 static char *stb__splitpath_raw(char *buffer, char *path, int flag)
2310 {
2311 int len=0,x,y, n = (int) strlen(path), f1,f2;
2312 char *s = stb_strrchr2(path, '/', '\\');
2313 char *t = strrchr(path, '.');
2314 if (s && t && t < s) t = NULL;
2315 if (s) ++s;
2316
2317 if (flag == STB_EXT_NO_PERIOD)
2318 flag |= STB_EXT;
2319
2320 if (!(flag & (STB_PATH | STB_FILE | STB_EXT))) return NULL;
2321
2322 f1 = s == NULL ? 0 : s-path; // start of filename
2323 f2 = t == NULL ? n : t-path; // just past end of filename
2324
2325 if (flag & STB_PATH) {
2326 x = 0; if (f1 == 0 && flag == STB_PATH) len=2;
2327 } else if (flag & STB_FILE) {
2328 x = f1;
2329 } else {
2330 x = f2;
2331 if (flag & STB_EXT_NO_PERIOD)
2332 if (buffer[x] == '.')
2333 ++x;
2334 }
2335
2336 if (flag & STB_EXT)
2337 y = n;
2338 else if (flag & STB_FILE)
2339 y = f2;
2340 else
2341 y = f1;
2342
2343 if (buffer == NULL) {
2344 buffer = (char *) malloc(y-x + len + 1);
2345 if (!buffer) return NULL;
2346 }
2347
2348 if (len) { strcpy(buffer, "./"); return buffer; }
2349 strncpy(buffer, path+x, y-x);
2350 buffer[y-x] = 0;
2351 return buffer;
2352 }
2353
2354 char *stb_splitpath(char *output, char *src, int flag)
2355 {
2356 return stb__splitpath_raw(output, src, flag);
2357 }
2358
2359 char *stb_splitpathdup(char *src, int flag)
2360 {
2361 return stb__splitpath_raw(NULL, src, flag);
2362 }
2363
2364 char *stb_replacedir(char *output, char *src, char *dir)
2365 {
2366 char buffer[4096];
2367 stb_splitpath(buffer, src, STB_FILE | STB_EXT);
2368 if (dir)
2369 sprintf(output, "%s/%s", dir, buffer);
2370 else
2371 strcpy(output, buffer);
2372 return output;
2373 }
2374
2375 char *stb_replaceext(char *output, char *src, char *ext)
2376 {
2377 char buffer[4096];
2378 stb_splitpath(buffer, src, STB_PATH | STB_FILE);
2379 if (ext)
2380 sprintf(output, "%s.%s", buffer, ext[0] == '.' ? ext+1 : ext);
2381 else
2382 strcpy(output, buffer);
2383 return output;
2384 }
2385 #endif
2386
2387 //////////////////////////////////////////////////////////////////////////////
2388 //
2389 // stb_alloc - hierarchical allocator
2390 //
2391 // inspired by http://swapped.cc/halloc
2392 //
2393 //
2394 // When you alloc a given block through stb_alloc, you have these choices:
2395 //
2396 // 1. does it have a parent?
2397 // 2. can it have children?
2398 // 3. can it be freed directly?
2399 // 4. is it transferrable?
2400 // 5. what is its alignment?
2401 //
2402 // Here are interesting combinations of those:
2403 //
2404 // children free transfer alignment
2405 // arena Y Y N n/a
2406 // no-overhead, chunked N N N normal
2407 // string pool alloc N N N 1
2408 // parent-ptr, chunked Y N N normal
2409 // low-overhead, unchunked N Y Y normal
2410 // general purpose alloc Y Y Y normal
2411 //
2412 // Unchunked allocations will probably return 16-aligned pointers. If
2413 // we 16-align the results, we have room for 4 pointers. For smaller
2414 // allocations that allow finer alignment, we can reduce the pointers.
2415 //
2416 // The strategy is that given a pointer, assuming it has a header (only
2417 // the no-overhead allocations have no header), we can determine the
2418 // type of the header fields, and the number of them, by stepping backwards
2419 // through memory and looking at the tags in the bottom bits.
2420 //
2421 // Implementation strategy:
2422 // chunked allocations come from the middle of chunks, and can't
2423 // be freed. thefore they do not need to be on a sibling chain.
2424 // they may need child pointers if they have children.
2425 //
2426 // chunked, with-children
2427 // void *parent;
2428 //
2429 // unchunked, no-children -- reduced storage
2430 // void *next_sibling;
2431 // void *prev_sibling_nextp;
2432 //
2433 // unchunked, general
2434 // void *first_child;
2435 // void *next_sibling;
2436 // void *prev_sibling_nextp;
2437 // void *chunks;
2438 //
2439 // so, if we code each of these fields with different bit patterns
2440 // (actually same one for next/prev/child), then we can identify which
2441 // each one is from the last field.
2442
2443 STB_EXTERN void stb_free(void *p);
2444 STB_EXTERN void *stb_malloc_global(size_t size);
2445 STB_EXTERN void *stb_malloc(void *context, size_t size);
2446 STB_EXTERN void *stb_malloc_nofree(void *context, size_t size);
2447 STB_EXTERN void *stb_malloc_leaf(void *context, size_t size);
2448 STB_EXTERN void *stb_malloc_raw(void *context, size_t size);
2449 STB_EXTERN void *stb_realloc(void *ptr, size_t newsize);
2450
2451 STB_EXTERN void stb_reassign(void *new_context, void *ptr);
2452 STB_EXTERN void stb_malloc_validate(void *p, void *parent);
2453
2454 extern int stb_alloc_chunk_size ;
2455 extern int stb_alloc_count_free ;
2456 extern int stb_alloc_count_alloc;
2457 extern int stb_alloc_alignment ;
2458
2459 #ifdef STB_DEFINE
2460
2461 int stb_alloc_chunk_size = 65536;
2462 int stb_alloc_count_free = 0;
2463 int stb_alloc_count_alloc = 0;
2464 int stb_alloc_alignment = -16;
2465
2466 typedef struct stb__chunk
2467 {
2468 struct stb__chunk *next;
2469 int data_left;
2470 int alloc;
2471 } stb__chunk;
2472
2473 typedef struct
2474 {
2475 void * next;
2476 void ** prevn;
2477 } stb__nochildren;
2478
2479 typedef struct
2480 {
2481 void ** prevn;
2482 void * child;
2483 void * next;
2484 stb__chunk *chunks;
2485 } stb__alloc;
2486
2487 typedef struct
2488 {
2489 stb__alloc *parent;
2490 } stb__chunked;
2491
2492 #define STB__PARENT 1
2493 #define STB__CHUNKS 2
2494
2495 typedef enum
2496 {
2497 STB__nochildren = 0,
2498 STB__chunked = STB__PARENT,
2499 STB__alloc = STB__CHUNKS,
2500
2501 STB__chunk_raw = 4,
2502 } stb__alloc_type;
2503
2504 // these functions set the bottom bits of a pointer efficiently
2505 #define STB__DECODE(x,v) ((void *) ((char *) (x) - (v)))
2506 #define STB__ENCODE(x,v) ((void *) ((char *) (x) + (v)))
2507
2508 #define stb__parent(z) (stb__alloc *) STB__DECODE((z)->parent, STB__PARENT)
2509 #define stb__chunks(z) (stb__chunk *) STB__DECODE((z)->chunks, STB__CHUNKS)
2510
2511 #define stb__setparent(z,p) (z)->parent = (stb__alloc *) STB__ENCODE((p), STB__PARENT)
2512 #define stb__setchunks(z,c) (z)->chunks = (stb__chunk *) STB__ENCODE((c), STB__CHUNKS)
2513
2514 static stb__alloc stb__alloc_global =
2515 {
2516 NULL,
2517 NULL,
2518 NULL,
2519 (stb__chunk *) STB__ENCODE(NULL, STB__CHUNKS)
2520 };
2521
2522 static stb__alloc_type stb__identify(void *p)
2523 {
2524 void **q = (void **) p;
2525 return (stb__alloc_type) ((stb_uinta) q[-1] & 3);
2526 }
2527
2528 static void *** stb__prevn(void *p)
2529 {
2530 if (stb__identify(p) == STB__alloc) {
2531 stb__alloc *s = (stb__alloc *) p - 1;
2532 return &s->prevn;
2533 } else {
2534 stb__nochildren *s = (stb__nochildren *) p - 1;
2535 return &s->prevn;
2536 }
2537 }
2538
2539 void stb_free(void *p)
2540 {
2541 if (p == NULL) return;
2542
2543 // count frees so that unit tests can see what's happening
2544 ++stb_alloc_count_free;
2545
2546 switch(stb__identify(p)) {
2547 case STB__chunked:
2548 // freeing a chunked-block with children does nothing;
2549 // they only get freed when the parent does
2550 // surely this is wrong, and it should free them immediately?
2551 // otherwise how are they getting put on the right chain?
2552 return;
2553 case STB__nochildren: {
2554 stb__nochildren *s = (stb__nochildren *) p - 1;
2555 // unlink from sibling chain
2556 *(s->prevn) = s->next;
2557 if (s->next)
2558 *stb__prevn(s->next) = s->prevn;
2559 free(s);
2560 return;
2561 }
2562 case STB__alloc: {
2563 stb__alloc *s = (stb__alloc *) p - 1;
2564 stb__chunk *c, *n;
2565 void *q;
2566
2567 // unlink from sibling chain, if any
2568 *(s->prevn) = s->next;
2569 if (s->next)
2570 *stb__prevn(s->next) = s->prevn;
2571
2572 // first free chunks
2573 c = (stb__chunk *) stb__chunks(s);
2574 while (c != NULL) {
2575 n = c->next;
2576 stb_alloc_count_free += c->alloc;
2577 free(c);
2578 c = n;
2579 }
2580
2581 // validating
2582 stb__setchunks(s,NULL);
2583 s->prevn = NULL;
2584 s->next = NULL;
2585
2586 // now free children
2587 while ((q = s->child) != NULL) {
2588 stb_free(q);
2589 }
2590
2591 // now free self
2592 free(s);
2593 return;
2594 }
2595 default:
2596 assert(0); /* NOTREACHED */
2597 }
2598 }
2599
2600 void stb_malloc_validate(void *p, void *parent)
2601 {
2602 if (p == NULL) return;
2603
2604 switch(stb__identify(p)) {
2605 case STB__chunked:
2606 return;
2607 case STB__nochildren: {
2608 stb__nochildren *n = (stb__nochildren *) p - 1;
2609 if (n->prevn)
2610 assert(*n->prevn == p);
2611 if (n->next) {
2612 assert(*stb__prevn(n->next) == &n->next);
2613 stb_malloc_validate(n, parent);
2614 }
2615 return;
2616 }
2617 case STB__alloc: {
2618 stb__alloc *s = (stb__alloc *) p - 1;
2619
2620 if (s->prevn)
2621 assert(*s->prevn == p);
2622
2623 if (s->child) {
2624 assert(*stb__prevn(s->child) == &s->child);
2625 stb_malloc_validate(s->child, p);
2626 }
2627
2628 if (s->next) {
2629 assert(*stb__prevn(s->next) == &s->next);
2630 stb_malloc_validate(s->next, parent);
2631 }
2632 return;
2633 }
2634 default:
2635 assert(0); /* NOTREACHED */
2636 }
2637 }
2638
2639 static void * stb__try_chunk(stb__chunk *c, int size, int align, int pre_align)
2640 {
2641 char *memblock = (char *) (c+1), *q;
2642 stb_inta iq;
2643 int start_offset;
2644
2645 // we going to allocate at the end of the chunk, not the start. confusing,
2646 // but it means we don't need both a 'limit' and a 'cur', just a 'cur'.
2647 // the block ends at: p + c->data_left
2648 // then we move back by size
2649 start_offset = c->data_left - size;
2650
2651 // now we need to check the alignment of that
2652 q = memblock + start_offset;
2653 iq = (stb_inta) q;
2654 assert(sizeof(q) == sizeof(iq));
2655
2656 // suppose align = 2
2657 // then we need to retreat iq far enough that (iq & (2-1)) == 0
2658 // to get (iq & (align-1)) = 0 requires subtracting (iq & (align-1))
2659
2660 start_offset -= iq & (align-1);
2661 assert(((stb_uinta) (memblock+start_offset) & (align-1)) == 0);
2662
2663 // now, if that + pre_align works, go for it!
2664 start_offset -= pre_align;
2665
2666 if (start_offset >= 0) {
2667 c->data_left = start_offset;
2668 return memblock + start_offset;
2669 }
2670
2671 return NULL;
2672 }
2673
2674 static void stb__sort_chunks(stb__alloc *src)
2675 {
2676 // of the first two chunks, put the chunk with more data left in it first
2677 stb__chunk *c = stb__chunks(src), *d;
2678 if (c == NULL) return;
2679 d = c->next;
2680 if (d == NULL) return;
2681 if (c->data_left > d->data_left) return;
2682
2683 c->next = d->next;
2684 d->next = c;
2685 stb__setchunks(src, d);
2686 }
2687
2688 static void * stb__alloc_chunk(stb__alloc *src, int size, int align, int pre_align)
2689 {
2690 void *p;
2691 stb__chunk *c = stb__chunks(src);
2692
2693 if (c && size <= stb_alloc_chunk_size) {
2694
2695 p = stb__try_chunk(c, size, align, pre_align);
2696 if (p) { ++c->alloc; return p; }
2697
2698 // try a second chunk to reduce wastage
2699 if (c->next) {
2700 p = stb__try_chunk(c->next, size, align, pre_align);
2701 if (p) { ++c->alloc; return p; }
2702
2703 // put the bigger chunk first, since the second will get buried
2704 // the upshot of this is that, until it gets allocated from, chunk #2
2705 // is always the largest remaining chunk. (could formalize
2706 // this with a heap!)
2707 stb__sort_chunks(src);
2708 c = stb__chunks(src);
2709 }
2710 }
2711
2712 // allocate a new chunk
2713 {
2714 stb__chunk *n;
2715
2716 int chunk_size = stb_alloc_chunk_size;
2717 // we're going to allocate a new chunk to put this in
2718 if (size > chunk_size)
2719 chunk_size = size;
2720
2721 assert(sizeof(*n) + pre_align <= 16);
2722
2723 // loop trying to allocate a large enough chunk
2724 // the loop is because the alignment may cause problems if it's big...
2725 // and we don't know what our chunk alignment is going to be
2726 while (1) {
2727 n = (stb__chunk *) malloc(16 + chunk_size);
2728 if (n == NULL) return NULL;
2729
2730 n->data_left = chunk_size - sizeof(*n);
2731
2732 p = stb__try_chunk(n, size, align, pre_align);
2733 if (p != NULL) {
2734 n->next = c;
2735 stb__setchunks(src, n);
2736
2737 // if we just used up the whole block immediately,
2738 // move the following chunk up
2739 n->alloc = 1;
2740 if (size == chunk_size)
2741 stb__sort_chunks(src);
2742
2743 return p;
2744 }
2745
2746 free(n);
2747 chunk_size += 16+align;
2748 }
2749 }
2750 }
2751
2752 static stb__alloc * stb__get_context(void *context)
2753 {
2754 if (context == NULL) {
2755 return &stb__alloc_global;
2756 } else {
2757 int u = stb__identify(context);
2758 // if context is chunked, grab parent
2759 if (u == STB__chunked) {
2760 stb__chunked *s = (stb__chunked *) context - 1;
2761 return stb__parent(s);
2762 } else {
2763 return (stb__alloc *) context - 1;
2764 }
2765 }
2766 }
2767
2768 static void stb__insert_alloc(stb__alloc *src, stb__alloc *s)
2769 {
2770 s->prevn = &src->child;
2771 s->next = src->child;
2772 src->child = s+1;
2773 if (s->next)
2774 *stb__prevn(s->next) = &s->next;
2775 }
2776
2777 static void stb__insert_nochild(stb__alloc *src, stb__nochildren *s)
2778 {
2779 s->prevn = &src->child;
2780 s->next = src->child;
2781 src->child = s+1;
2782 if (s->next)
2783 *stb__prevn(s->next) = &s->next;
2784 }
2785
2786 static void * malloc_base(void *context, size_t size, stb__alloc_type t, int align)
2787 {
2788 void *p;
2789
2790 stb__alloc *src = stb__get_context(context);
2791
2792 if (align <= 0) {
2793 // compute worst-case C packed alignment
2794 // e.g. a 24-byte struct is 8-aligned
2795 int align_proposed = 1 << stb_lowbit8(size);
2796
2797 if (align_proposed < 0)
2798 align_proposed = 4;
2799
2800 if (align_proposed == 0) {
2801 if (size == 0)
2802 align_proposed = 1;
2803 else
2804 align_proposed = 256;
2805 }
2806
2807 // a negative alignment means 'don't align any larger
2808 // than this'; so -16 means we align 1,2,4,8, or 16
2809
2810 if (align < 0) {
2811 if (align_proposed > -align)
2812 align_proposed = -align;
2813 }
2814
2815 align = align_proposed;
2816 }
2817
2818 assert(stb_is_pow2(align));
2819
2820 // don't cause misalignment when allocating nochildren
2821 if (t == STB__nochildren && align > 8)
2822 t = STB__alloc;
2823
2824 switch (t) {
2825 case STB__alloc: {
2826 stb__alloc *s = (stb__alloc *) malloc(size + sizeof(*s));
2827 if (s == NULL) return NULL;
2828 p = s+1;
2829 s->child = NULL;
2830 stb__insert_alloc(src, s);
2831
2832 stb__setchunks(s,NULL);
2833 break;
2834 }
2835
2836 case STB__nochildren: {
2837 stb__nochildren *s = (stb__nochildren *) malloc(size + sizeof(*s));
2838 if (s == NULL) return NULL;
2839 p = s+1;
2840 stb__insert_nochild(src, s);
2841 break;
2842 }
2843
2844 case STB__chunk_raw: {
2845 p = stb__alloc_chunk(src, size, align, 0);
2846 if (p == NULL) return NULL;
2847 break;
2848 }
2849
2850 case STB__chunked: {
2851 stb__chunked *s;
2852 if (align < sizeof(stb_uintptr)) align = sizeof(stb_uintptr);
2853 s = (stb__chunked *) stb__alloc_chunk(src, size, align, sizeof(*s));
2854 if (s == NULL) return NULL;
2855 stb__setparent(s, src);
2856 p = s+1;
2857 break;
2858 }
2859
2860 default: p = NULL; assert(0); /* NOTREACHED */
2861 }
2862
2863 ++stb_alloc_count_alloc;
2864 return p;
2865 }
2866
2867 void *stb_malloc_global(size_t size)
2868 {
2869 return malloc_base(NULL, size, STB__alloc, stb_alloc_alignment);
2870 }
2871
2872 void *stb_malloc(void *context, size_t size)
2873 {
2874 return malloc_base(context, size, STB__alloc, stb_alloc_alignment);
2875 }
2876
2877 void *stb_malloc_nofree(void *context, size_t size)
2878 {
2879 return malloc_base(context, size, STB__chunked, stb_alloc_alignment);
2880 }
2881
2882 void *stb_malloc_leaf(void *context, size_t size)
2883 {
2884 return malloc_base(context, size, STB__nochildren, stb_alloc_alignment);
2885 }
2886
2887 void *stb_malloc_raw(void *context, size_t size)
2888 {
2889 return malloc_base(context, size, STB__chunk_raw, stb_alloc_alignment);
2890 }
2891
2892 char *stb_malloc_string(void *context, size_t size)
2893 {
2894 return (char *) malloc_base(context, size, STB__chunk_raw, 1);
2895 }
2896
2897 void *stb_realloc(void *ptr, size_t newsize)
2898 {
2899 stb__alloc_type t;
2900
2901 if (ptr == NULL) return stb_malloc(NULL, newsize);
2902 if (newsize == 0) { stb_free(ptr); return NULL; }
2903
2904 t = stb__identify(ptr);
2905 assert(t == STB__alloc || t == STB__nochildren);
2906
2907 if (t == STB__alloc) {
2908 stb__alloc *s = (stb__alloc *) ptr - 1;
2909
2910 s = (stb__alloc *) realloc(s, newsize + sizeof(*s));
2911 if (s == NULL) return NULL;
2912
2913 ptr = s+1;
2914
2915 // update pointers
2916 (*s->prevn) = ptr;
2917 if (s->next)
2918 *stb__prevn(s->next) = &s->next;
2919
2920 if (s->child)
2921 *stb__prevn(s->child) = &s->child;
2922
2923 return ptr;
2924 } else {
2925 stb__nochildren *s = (stb__nochildren *) ptr - 1;
2926
2927 s = (stb__nochildren *) realloc(ptr, newsize + sizeof(s));
2928 if (s == NULL) return NULL;
2929
2930 // update pointers
2931 (*s->prevn) = s+1;
2932 if (s->next)
2933 *stb__prevn(s->next) = &s->next;
2934
2935 return s+1;
2936 }
2937 }
2938
2939 void *stb_realloc_c(void *context, void *ptr, size_t newsize)
2940 {
2941 if (ptr == NULL) return stb_malloc(context, newsize);
2942 if (newsize == 0) { stb_free(ptr); return NULL; }
2943 // @TODO: verify you haven't changed contexts
2944 return stb_realloc(ptr, newsize);
2945 }
2946
2947 void stb_reassign(void *new_context, void *ptr)
2948 {
2949 stb__alloc *src = stb__get_context(new_context);
2950
2951 stb__alloc_type t = stb__identify(ptr);
2952 assert(t == STB__alloc || t == STB__nochildren);
2953
2954 if (t == STB__alloc) {
2955 stb__alloc *s = (stb__alloc *) ptr - 1;
2956
2957 // unlink from old
2958 *(s->prevn) = s->next;
2959 if (s->next)
2960 *stb__prevn(s->next) = s->prevn;
2961
2962 stb__insert_alloc(src, s);
2963 } else {
2964 stb__nochildren *s = (stb__nochildren *) ptr - 1;
2965
2966 // unlink from old
2967 *(s->prevn) = s->next;
2968 if (s->next)
2969 *stb__prevn(s->next) = s->prevn;
2970
2971 stb__insert_nochild(src, s);
2972 }
2973 }
2974
2975 #endif
2976
2977
2978 //////////////////////////////////////////////////////////////////////////////
2979 //
2980 // stb_arr
2981 //
2982 // An stb_arr is directly useable as a pointer (use the actual type in your
2983 // definition), but when it resizes, it returns a new pointer and you can't
2984 // use the old one, so you have to be careful to copy-in-out as necessary.
2985 //
2986 // Use a NULL pointer as a 0-length array.
2987 //
2988 // float *my_array = NULL, *temp;
2989 //
2990 // // add elements on the end one at a time
2991 // stb_arr_push(my_array, 0.0f);
2992 // stb_arr_push(my_array, 1.0f);
2993 // stb_arr_push(my_array, 2.0f);
2994 //
2995 // assert(my_array[1] == 2.0f);
2996 //
2997 // // add an uninitialized element at the end, then assign it
2998 // *stb_arr_add(my_array) = 3.0f;
2999 //
3000 // // add three uninitialized elements at the end
3001 // temp = stb_arr_addn(my_array,3);
3002 // temp[0] = 4.0f;
3003 // temp[1] = 5.0f;
3004 // temp[2] = 6.0f;
3005 //
3006 // assert(my_array[5] == 5.0f);
3007 //
3008 // // remove the last one
3009 // stb_arr_pop(my_array);
3010 //
3011 // assert(stb_arr_len(my_array) == 6);
3012
3013
3014 #ifdef STB_MALLOC_WRAPPER
3015 #define STB__PARAMS , char *file, int line
3016 #define STB__ARGS , file, line
3017 #else
3018 #define STB__PARAMS
3019 #define STB__ARGS
3020 #endif
3021
3022 // calling this function allocates an empty stb_arr attached to p
3023 // (whereas NULL isn't attached to anything)
3024 STB_EXTERN void stb_arr_malloc(void **target, void *context);
3025
3026 // call this function with a non-NULL value to have all successive
3027 // stbs that are created be attached to the associated parent. Note
3028 // that once a given stb_arr is non-empty, it stays attached to its
3029 // current parent, even if you call this function again.
3030 // it turns the previous value, so you can restore it
3031 STB_EXTERN void* stb_arr_malloc_parent(void *p);
3032
3033 // simple functions written on top of other functions
3034 #define stb_arr_empty(a) ( stb_arr_len(a) == 0 )
3035 #define stb_arr_add(a) ( stb_arr_addn((a),1) )
3036 #define stb_arr_push(a,v) ( *stb_arr_add(a)=(v) )
3037
3038 typedef struct
3039 {
3040 int len, limit;
3041 int stb_malloc;
3042 unsigned int signature;
3043 } stb__arr;
3044
3045 #define stb_arr_signature 0x51bada7b // ends with 0123 in decimal
3046
3047 // access the header block stored before the data
3048 #define stb_arrhead(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3049 #define stb_arrhead2(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
3050
3051 #ifdef STB_DEBUG
3052 #define stb_arr_check(a) assert(!a || stb_arrhead(a)->signature == stb_arr_signature)
3053 #define stb_arr_check2(a) assert(!a || stb_arrhead2(a)->signature == stb_arr_signature)
3054 #else
3055 #define stb_arr_check(a) ((void) 0)
3056 #define stb_arr_check2(a) ((void) 0)
3057 #endif
3058
3059 // ARRAY LENGTH
3060
3061 // get the array length; special case if pointer is NULL
3062 #define stb_arr_len(a) (a ? stb_arrhead(a)->len : 0)
3063 #define stb_arr_len2(a) ((stb__arr *) (a) ? stb_arrhead2(a)->len : 0)
3064 #define stb_arr_lastn(a) (stb_arr_len(a)-1)
3065
3066 // check whether a given index is valid -- tests 0 <= i < stb_arr_len(a)
3067 #define stb_arr_valid(a,i) (a ? (int) (i) < stb_arrhead(a)->len : 0)
3068
3069 // change the array length so is is exactly N entries long, creating
3070 // uninitialized entries as needed
3071 #define stb_arr_setlen(a,n) \
3072 (stb__arr_setlen((void **) &(a), sizeof(a[0]), (n)))
3073
3074 // change the array length so that N is a valid index (that is, so
3075 // it is at least N entries long), creating uninitialized entries as needed
3076 #define stb_arr_makevalid(a,n) \
3077 (stb_arr_len(a) < (n)+1 ? stb_arr_setlen(a,(n)+1),(a) : (a))
3078
3079 // remove the last element of the array, returning it
3080 #define stb_arr_pop(a) ((stb_arr_check(a), (a))[--stb_arrhead(a)->len])
3081
3082 // access the last element in the array
3083 #define stb_arr_last(a) ((stb_arr_check(a), (a))[stb_arr_len(a)-1])
3084
3085 // is iterator at end of list?
3086 #define stb_arr_end(a,i) ((i) >= &(a)[stb_arr_len(a)])
3087
3088 // (internal) change the allocated length of the array
3089 #define stb_arr__grow(a,n) (stb_arr_check(a), stb_arrhead(a)->len += (n))
3090
3091 // add N new unitialized elements to the end of the array
3092 #define stb_arr__addn(a,n) /*lint --e(826)*/ \
3093 ((stb_arr_len(a)+(n) > stb_arrcurmax(a)) \
3094 ? (stb__arr_addlen((void **) &(a),sizeof(*a),(n)),0) \
3095 : ((stb_arr__grow(a,n), 0)))
3096
3097 // add N new unitialized elements to the end of the array, and return
3098 // a pointer to the first new one
3099 #define stb_arr_addn(a,n) (stb_arr__addn((a),n),(a)+stb_arr_len(a)-(n))
3100
3101 // add N new uninitialized elements starting at index 'i'
3102 #define stb_arr_insertn(a,i,n) (stb__arr_insertn((void **) &(a), sizeof(*a), i, n))
3103
3104 // insert an element at i
3105 #define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), i, 1), ((a)[i] = v))
3106
3107 // delete N elements from the middle starting at index 'i'
3108 #define stb_arr_deleten(a,i,n) (stb__arr_deleten((void **) &(a), sizeof(*a), i, n))
3109
3110 // delete the i'th element
3111 #define stb_arr_delete(a,i) stb_arr_deleten(a,i,1)
3112
3113 // delete the i'th element, swapping down from the end
3114 #define stb_arr_fastdelete(a,i) \
3115 (stb_swap(&a[i], &a[stb_arrhead(a)->len-1], sizeof(*a)), stb_arr_pop(a))
3116
3117
3118 // ARRAY STORAGE
3119
3120 // get the array maximum storage; special case if NULL
3121 #define stb_arrcurmax(a) (a ? stb_arrhead(a)->limit : 0)
3122 #define stb_arrcurmax2(a) (a ? stb_arrhead2(a)->limit : 0)
3123
3124 // set the maxlength of the array to n in anticipation of further growth
3125 #define stb_arr_setsize(a,n) (stb_arr_check(a), stb__arr_setsize((void **) &(a),sizeof((a)[0]),n))
3126
3127 // make sure maxlength is large enough for at least N new allocations
3128 #define stb_arr_atleast(a,n) (stb_arr_len(a)+(n) > stb_arrcurmax(a) \
3129 ? stb_arr_setsize((a), (n)) : 0)
3130
3131 // make a copy of a given array (copies contents via 'memcpy'!)
3132 #define stb_arr_copy(a) stb__arr_copy(a, sizeof((a)[0]))
3133
3134 // compute the storage needed to store all the elements of the array
3135 #define stb_arr_storage(a) (stb_arr_len(a) * sizeof((a)[0]))
3136
3137 #define stb_arr_for(v,arr) for((v)=(arr); (v) < (arr)+stb_arr_len(arr); ++(v))
3138
3139 // IMPLEMENTATION
3140
3141 STB_EXTERN void stb_arr_free_(void **p);
3142 STB_EXTERN void *stb__arr_copy_(void *p, int elem_size);
3143 STB_EXTERN void stb__arr_setsize_(void **p, int size, int limit STB__PARAMS);
3144 STB_EXTERN void stb__arr_setlen_(void **p, int size, int newlen STB__PARAMS);
3145 STB_EXTERN void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS);
3146 STB_EXTERN void stb__arr_deleten_(void **p, int size, int loc, int n STB__PARAMS);
3147 STB_EXTERN void stb__arr_insertn_(void **p, int size, int loc, int n STB__PARAMS);
3148
3149 #define stb_arr_free(p) stb_arr_free_((void **) &(p))
3150 #define stb__arr_copy stb__arr_copy_
3151
3152 #ifndef STB_MALLOC_WRAPPER
3153 #define stb__arr_setsize stb__arr_setsize_
3154 #define stb__arr_setlen stb__arr_setlen_
3155 #define stb__arr_addlen stb__arr_addlen_
3156 #define stb__arr_deleten stb__arr_deleten_
3157 #define stb__arr_insertn stb__arr_insertn_
3158 #else
3159 #define stb__arr_addlen(p,s,n) stb__arr_addlen_(p,s,n,__FILE__,__LINE__)
3160 #define stb__arr_setlen(p,s,n) stb__arr_setlen_(p,s,n,__FILE__,__LINE__)
3161 #define stb__arr_setsize(p,s,n) stb__arr_setsize_(p,s,n,__FILE__,__LINE__)
3162 #define stb__arr_deleten(p,s,i,n) stb__arr_deleten_(p,s,i,n,__FILE__,__LINE__)
3163 #define stb__arr_insertn(p,s,i,n) stb__arr_insertn_(p,s,i,n,__FILE__,__LINE__)
3164 #endif
3165
3166 #ifdef STB_DEFINE
3167 static void *stb__arr_context;
3168
3169 void *stb_arr_malloc_parent(void *p)
3170 {
3171 void *q = stb__arr_context;
3172 stb__arr_context = p;
3173 return q;
3174 }
3175
3176 void stb_arr_malloc(void **target, void *context)
3177 {
3178 stb__arr *q = (stb__arr *) stb_malloc(context, sizeof(*q));
3179 q->len = q->limit = 0;
3180 q->stb_malloc = 1;
3181 q->signature = stb_arr_signature;
3182 *target = (void *) (q+1);
3183 }
3184
3185 static void * stb__arr_malloc(int size)
3186 {
3187 if (stb__arr_context)
3188 return stb_malloc(stb__arr_context, size);
3189 return malloc(size);
3190 }
3191
3192 void * stb__arr_copy_(void *p, int elem_size)
3193 {
3194 stb__arr *q;
3195 if (p == NULL) return p;
3196 q = (stb__arr *) stb__arr_malloc(sizeof(*q) + elem_size * stb_arrhead2(p)->limit);
3197 stb_arr_check2(p);
3198 memcpy(q, stb_arrhead2(p), sizeof(*q) + elem_size * stb_arrhead2(p)->len);
3199 q->stb_malloc = !!stb__arr_context;
3200 return q+1;
3201 }
3202
3203 void stb_arr_free_(void **pp)
3204 {
3205 void *p = *pp;
3206 stb_arr_check2(p);
3207 if (p) {
3208 stb__arr *q = stb_arrhead2(p);
3209 if (q->stb_malloc)
3210 stb_free(q);
3211 else
3212 free(q);
3213 }
3214 *pp = NULL;
3215 }
3216
3217 static void stb__arrsize_(void **pp, int size, int limit, int len STB__PARAMS)
3218 {
3219 void *p = *pp;
3220 stb__arr *a;
3221 stb_arr_check2(p);
3222 if (p == NULL) {
3223 if (len == 0 && size == 0) return;
3224 a = (stb__arr *) stb__arr_malloc(sizeof(*a) + size*limit);
3225 a->limit = limit;
3226 a->len = len;
3227 a->stb_malloc = !!stb__arr_context;
3228 a->signature = stb_arr_signature;
3229 } else {
3230 a = stb_arrhead2(p);
3231 a->len = len;
3232 if (a->limit < limit) {
3233 void *p;
3234 if (a->limit >= 4 && limit < a->limit * 2)
3235 limit = a->limit * 2;
3236 if (a->stb_malloc)
3237 p = stb_realloc(a, sizeof(*a) + limit*size);
3238 else
3239 #ifdef STB_MALLOC_WRAPPER
3240 p = stb__realloc(a, sizeof(*a) + limit*size, file, line);
3241 #else
3242 p = realloc(a, sizeof(*a) + limit*size);
3243 #endif
3244 if (p) {
3245 a = (stb__arr *) p;
3246 a->limit = limit;
3247 } else {
3248 // throw an error!
3249 }
3250 }
3251 }
3252 a->len = stb_min(a->len, a->limit);
3253 *pp = a+1;
3254 }
3255
3256 void stb__arr_setsize_(void **pp, int size, int limit STB__PARAMS)
3257 {
3258 void *p = *pp;
3259 stb_arr_check2(p);
3260 stb__arrsize_(pp, size, limit, stb_arr_len2(p) STB__ARGS);
3261 }
3262
3263 void stb__arr_setlen_(void **pp, int size, int newlen STB__PARAMS)
3264 {
3265 void *p = *pp;
3266 stb_arr_check2(p);
3267 if (stb_arrcurmax2(p) < newlen || p == NULL) {
3268 stb__arrsize_(pp, size, newlen, newlen STB__ARGS);
3269 } else {
3270 stb_arrhead2(p)->len = newlen;
3271 }
3272 }
3273
3274 void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS)
3275 {
3276 stb__arr_setlen_(p, size, stb_arr_len2(*p) + addlen STB__ARGS);
3277 }
3278
3279 void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS)
3280 {
3281 void *p = *pp;
3282 if (n) {
3283 int z;
3284
3285 if (p == NULL) {
3286 stb__arr_addlen_(pp, size, n STB__ARGS);
3287 return;
3288 }
3289
3290 z = stb_arr_len2(p);
3291 stb__arr_addlen_(&p, size, n STB__ARGS);
3292 memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i));
3293 }
3294 *pp = p;
3295 }
3296
3297 void stb__arr_deleten_(void **pp, int size, int i, int n STB__PARAMS)
3298 {
3299 void *p = *pp;
3300 if (n) {
3301 memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n)));
3302 stb_arrhead2(p)->len -= n;
3303 }
3304 *pp = p;
3305 }
3306
3307 #endif
3308
3309 //////////////////////////////////////////////////////////////////////////////
3310 //
3311 // Hashing
3312 //
3313 // typical use for this is to make a power-of-two hash table.
3314 //
3315 // let N = size of table (2^n)
3316 // let H = stb_hash(str)
3317 // let S = stb_rehash(H) | 1
3318 //
3319 // then hash probe sequence P(i) for i=0..N-1
3320 // P(i) = (H + S*i) & (N-1)
3321 //
3322 // the idea is that H has 32 bits of hash information, but the
3323 // table has only, say, 2^20 entries so only uses 20 of the bits.
3324 // then by rehashing the original H we get 2^12 different probe
3325 // sequences for a given initial probe location. (So it's optimal
3326 // for 64K tables and its optimality decreases past that.)
3327 //
3328 // ok, so I've added something that generates _two separate_
3329 // 32-bit hashes simultaneously which should scale better to
3330 // very large tables.
3331
3332
3333 STB_EXTERN unsigned int stb_hash(char *str);
3334 STB_EXTERN unsigned int stb_hashptr(void *p);
3335 STB_EXTERN unsigned int stb_hashlen(char *str, int len);
3336 STB_EXTERN unsigned int stb_rehash_improved(unsigned int v);
3337 STB_EXTERN unsigned int stb_hash_fast(void *p, int len);
3338 STB_EXTERN unsigned int stb_hash2(char *str, unsigned int *hash2_ptr);
3339 STB_EXTERN unsigned int stb_hash_number(unsigned int hash);
3340
3341 #define stb_rehash(x) ((x) + ((x) >> 6) + ((x) >> 19))
3342
3343 #ifdef STB_DEFINE
3344 unsigned int stb_hash(char *str)
3345 {
3346 unsigned int hash = 0;
3347 while (*str)
3348 hash = (hash << 7) + (hash >> 25) + *str++;
3349 return hash + (hash >> 16);
3350 }
3351
3352 unsigned int stb_hashlen(char *str, int len)
3353 {
3354 unsigned int hash = 0;
3355 while (len-- > 0 && *str)
3356 hash = (hash << 7) + (hash >> 25) + *str++;
3357 return hash + (hash >> 16);
3358 }
3359
3360 unsigned int stb_hashptr(void *p)
3361 {
3362 unsigned int x = (unsigned int) p;
3363
3364 // typically lacking in low bits and high bits
3365 x = stb_rehash(x);
3366 x += x << 16;
3367
3368 // pearson's shuffle
3369 x ^= x << 3;
3370 x += x >> 5;
3371 x ^= x << 2;
3372 x += x >> 15;
3373 x ^= x << 10;
3374 return stb_rehash(x);
3375 }
3376
3377 unsigned int stb_rehash_improved(unsigned int v)
3378 {
3379 return stb_hashptr((void *)(size_t) v);
3380 }
3381
3382 unsigned int stb_hash2(char *str, unsigned int *hash2_ptr)
3383 {
3384 unsigned int hash1 = 0x3141592c;
3385 unsigned int hash2 = 0x77f044ed;
3386 while (*str) {
3387 hash1 = (hash1 << 7) + (hash1 >> 25) + *str;
3388 hash2 = (hash2 << 11) + (hash2 >> 21) + *str;
3389 ++str;
3390 }
3391 *hash2_ptr = hash2 + (hash1 >> 16);
3392 return hash1 + (hash2 >> 16);
3393 }
3394
3395 // Paul Hsieh hash
3396 #define stb__get16_slow(p) ((p)[0] + ((p)[1] << 8))
3397 #if defined(_MSC_VER)
3398 #define stb__get16(p) (*((unsigned short *) (p)))
3399 #else
3400 #define stb__get16(p) stb__get16_slow(p)
3401 #endif
3402
3403 unsigned int stb_hash_fast(void *p, int len)
3404 {
3405 unsigned char *q = (unsigned char *) p;
3406 unsigned int hash = len;
3407
3408 if (len <= 0 || q == NULL) return 0;
3409
3410 /* Main loop */
3411 if (((int) q & 1) == 0) {
3412 for (;len > 3; len -= 4) {
3413 unsigned int val;
3414 hash += stb__get16(q);
3415 val = (stb__get16(q+2) << 11);
3416 hash = (hash << 16) ^ hash ^ val;
3417 q += 4;
3418 hash += hash >> 11;
3419 }
3420 } else {
3421 for (;len > 3; len -= 4) {
3422 unsigned int val;
3423 hash += stb__get16_slow(q);
3424 val = (stb__get16_slow(q+2) << 11);
3425 hash = (hash << 16) ^ hash ^ val;
3426 q += 4;
3427 hash += hash >> 11;
3428 }
3429 }
3430
3431 /* Handle end cases */
3432 switch (len) {
3433 case 3: hash += stb__get16_slow(q);
3434 hash ^= hash << 16;
3435 hash ^= q[2] << 18;
3436 hash += hash >> 11;
3437 break;
3438 case 2: hash += stb__get16_slow(q);
3439 hash ^= hash << 11;
3440 hash += hash >> 17;
3441 break;
3442 case 1: hash += q[0];
3443 hash ^= hash << 10;
3444 hash += hash >> 1;
3445 break;
3446 case 0: break;
3447 }
3448
3449 /* Force "avalanching" of final 127 bits */
3450 hash ^= hash << 3;
3451 hash += hash >> 5;
3452 hash ^= hash << 4;
3453 hash += hash >> 17;
3454 hash ^= hash << 25;
3455 hash += hash >> 6;
3456
3457 return hash;
3458 }
3459
3460 unsigned int stb_hash_number(unsigned int hash)
3461 {
3462 hash ^= hash << 3;
3463 hash += hash >> 5;
3464 hash ^= hash << 4;
3465 hash += hash >> 17;
3466 hash ^= hash << 25;
3467 hash += hash >> 6;
3468 return hash;
3469 }
3470
3471 #endif
3472
3473 //////////////////////////////////////////////////////////////////////////////
3474 //
3475 // Perfect hashing for ints/pointers
3476 //
3477 // This is mainly useful for making faster pointer-indexed tables
3478 // that don't change frequently. E.g. for stb_ischar().
3479 //
3480
3481 typedef struct
3482 {
3483 stb_uint32 addend;
3484 stb_uint multiplicand;
3485 stb_uint b_mask;
3486 stb_uint8 small_bmap[16];
3487 stb_uint16 *large_bmap;
3488
3489 stb_uint table_mask;
3490 stb_uint32 *table;
3491 } stb_perfect;
3492
3493 STB_EXTERN int stb_perfect_create(stb_perfect *,unsigned int*,int n);
3494 STB_EXTERN void stb_perfect_destroy(stb_perfect *);
3495 STB_EXTERN int stb_perfect_hash(stb_perfect *, unsigned int x);
3496 extern int stb_perfect_hash_max_failures;
3497
3498 #ifdef STB_DEFINE
3499
3500 int stb_perfect_hash_max_failures;
3501
3502 int stb_perfect_hash(stb_perfect *p, unsigned int x)
3503 {
3504 stb_uint m = x * p->multiplicand;
3505 stb_uint y = x >> 16;
3506 stb_uint bv = (m >> 24) + y;
3507 stb_uint av = (m + y) >> 12;
3508 if (p->table == NULL) return -1; // uninitialized table fails
3509 bv &= p->b_mask;
3510 av &= p->table_mask;
3511 if (p->large_bmap)
3512 av ^= p->large_bmap[bv];
3513 else
3514 av ^= p->small_bmap[bv];
3515 return p->table[av] == x ? av : -1;
3516 }
3517
3518 static void stb__perfect_prehash(stb_perfect *p, stb_uint x, stb_uint16 *a, stb_uint16 *b)
3519 {
3520 stb_uint m = x * p->multiplicand;
3521 stb_uint y = x >> 16;
3522 stb_uint bv = (m >> 24) + y;
3523 stb_uint av = (m + y) >> 12;
3524 bv &= p->b_mask;
3525 av &= p->table_mask;
3526 *b = bv;
3527 *a = av;
3528 }
3529
3530 static unsigned long stb__perfect_rand(void)
3531 {
3532 static unsigned long stb__rand;
3533 stb__rand = stb__rand * 2147001325 + 715136305;
3534 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16));
3535 }
3536
3537 typedef struct {
3538 unsigned short count;
3539 unsigned short b;
3540 unsigned short map;
3541 unsigned short *entries;
3542 } stb__slot;
3543
3544 static int stb__slot_compare(const void *p, const void *q)
3545 {
3546 stb__slot *a = (stb__slot *) p;
3547 stb__slot *b = (stb__slot *) q;
3548 return a->count > b->count ? -1 : a->count < b->count; // sort large to small
3549 }
3550
3551 int stb_perfect_create(stb_perfect *p, unsigned int *v, int n)
3552 {
3553 unsigned int buffer1[64], buffer2[64], buffer3[64], buffer4[64], buffer5[32];
3554 unsigned short *as = (unsigned short *) stb_temp(buffer1, sizeof(*v)*n);
3555 unsigned short *bs = (unsigned short *) stb_temp(buffer2, sizeof(*v)*n);
3556 unsigned short *entries = (unsigned short *) stb_temp(buffer4, sizeof(*entries) * n);
3557 int size = 1 << stb_log2_ceil(n), bsize=8;
3558 int failure = 0,i,j,k;
3559
3560 assert(n <= 32768);
3561 p->large_bmap = NULL;
3562
3563 for(;;) {
3564 stb__slot *bcount = (stb__slot *) stb_temp(buffer3, sizeof(*bcount) * bsize);
3565 unsigned short *bloc = (unsigned short *) stb_temp(buffer5, sizeof(*bloc) * bsize);
3566 unsigned short *e;
3567 int bad=0;
3568
3569 p->addend = stb__perfect_rand();
3570 p->multiplicand = stb__perfect_rand() | 1;
3571 p->table_mask = size-1;
3572 p->b_mask = bsize-1;
3573 p->table = (stb_uint32 *) malloc(size * sizeof(*p->table));
3574
3575 for (i=0; i < bsize; ++i) {
3576 bcount[i].b = i;
3577 bcount[i].count = 0;
3578 bcount[i].map = 0;
3579 }
3580 for (i=0; i < n; ++i) {
3581 stb__perfect_prehash(p, v[i], as+i, bs+i);
3582 ++bcount[bs[i]].count;
3583 }
3584 qsort(bcount, bsize, sizeof(*bcount), stb__slot_compare);
3585 e = entries; // now setup up their entries index
3586 for (i=0; i < bsize; ++i) {
3587 bcount[i].entries = e;
3588 e += bcount[i].count;
3589 bcount[i].count = 0;
3590 bloc[bcount[i].b] = i;
3591 }
3592 // now fill them out
3593 for (i=0; i < n; ++i) {
3594 int b = bs[i];
3595 int w = bloc[b];
3596 bcount[w].entries[bcount[w].count++] = i;
3597 }
3598 stb_tempfree(buffer5,bloc);
3599 // verify
3600 for (i=0; i < bsize; ++i)
3601 for (j=0; j < bcount[i].count; ++j)
3602 assert(bs[bcount[i].entries[j]] == bcount[i].b);
3603 memset(p->table, 0, size*sizeof(*p->table));
3604
3605 // check if any b has duplicate a
3606 for (i=0; i < bsize; ++i) {
3607 if (bcount[i].count > 1) {
3608 for (j=0; j < bcount[i].count; ++j) {
3609 if (p->table[as[bcount[i].entries[j]]])
3610 bad = 1;
3611 p->table[as[bcount[i].entries[j]]] = 1;
3612 }
3613 for (j=0; j < bcount[i].count; ++j) {
3614 p->table[as[bcount[i].entries[j]]] = 0;
3615 }
3616 if (bad) break;
3617 }
3618 }
3619
3620 if (!bad) {
3621 // go through the bs and populate the table, first fit
3622 for (i=0; i < bsize; ++i) {
3623 if (bcount[i].count) {
3624 // go through the candidate table[b] values
3625 for (j=0; j < size; ++j) {
3626 // go through the a values and see if they fit
3627 for (k=0; k < bcount[i].count; ++k) {
3628 int a = as[bcount[i].entries[k]];
3629 if (p->table[(a^j)&p->table_mask]) {
3630 break; // fails
3631 }
3632 }
3633 // if succeeded, accept
3634 if (k == bcount[i].count) {
3635 bcount[i].map = j;
3636 for (k=0; k < bcount[i].count; ++k) {
3637 int a = as[bcount[i].entries[k]];
3638 p->table[(a^j)&p->table_mask] = 1;
3639 }
3640 break;
3641 }
3642 }
3643 if (j == size)
3644 break; // no match for i'th entry, so break out in failure
3645 }
3646 }
3647 if (i == bsize) {
3648 // success... fill out map
3649 if (bsize <= 16 && size <= 256) {
3650 p->large_bmap = NULL;
3651 for (i=0; i < bsize; ++i)
3652 p->small_bmap[bcount[i].b] = (stb_uint8) bcount[i].map;
3653 } else {
3654 p->large_bmap = (unsigned short *) malloc(sizeof(*p->large_bmap) * bsize);
3655 for (i=0; i < bsize; ++i)
3656 p->large_bmap[bcount[i].b] = bcount[i].map;
3657 }
3658
3659 // initialize table to v[0], so empty slots will fail
3660 for (i=0; i < size; ++i)
3661 p->table[i] = v[0];
3662
3663 for (i=0; i < n; ++i)
3664 if (p->large_bmap)
3665 p->table[as[i] ^ p->large_bmap[bs[i]]] = v[i];
3666 else
3667 p->table[as[i] ^ p->small_bmap[bs[i]]] = v[i];
3668
3669 // and now validate that none of them collided
3670 for (i=0; i < n; ++i)
3671 assert(stb_perfect_hash(p, v[i]) >= 0);
3672
3673 stb_tempfree(buffer3, bcount);
3674 break;
3675 }
3676 }
3677 free(p->table);
3678 p->table = NULL;
3679 stb_tempfree(buffer3, bcount);
3680
3681 ++failure;
3682 if (failure >= 4 && bsize < size) bsize *= 2;
3683 if (failure >= 8 && (failure & 3) == 0 && size < 4*n) {
3684 size *= 2;
3685 bsize *= 2;
3686 }
3687 if (failure == 6) {
3688 // make sure the input data is unique, so we don't infinite loop
3689 unsigned int *data = (unsigned int *) stb_temp(buffer3, n * sizeof(*data));
3690 memcpy(data, v, sizeof(*data) * n);
3691 qsort(data, n, sizeof(*data), stb_intcmp(0));
3692 for (i=1; i < n; ++i) {
3693 if (data[i] == data[i-1])
3694 size = 0; // size is return value, so 0 it
3695 }
3696 stb_tempfree(buffer3, data);
3697 if (!size) break;
3698 }
3699 }
3700
3701 if (failure > stb_perfect_hash_max_failures)
3702 stb_perfect_hash_max_failures = failure;
3703
3704 stb_tempfree(buffer1, as);
3705 stb_tempfree(buffer2, bs);
3706 stb_tempfree(buffer4, entries);
3707
3708 return size;
3709 }
3710
3711 void stb_perfect_destroy(stb_perfect *p)
3712 {
3713 if (p->large_bmap) free(p->large_bmap);
3714 if (p->table ) free(p->table);
3715 p->large_bmap = NULL;
3716 p->table = NULL;
3717 p->b_mask = 0;
3718 p->table_mask = 0;
3719 }
3720 #endif
3721
3722 //////////////////////////////////////////////////////////////////////////////
3723 //
3724 // Perfect hash clients
3725
3726 STB_EXTERN int stb_ischar(char s, char *set);
3727
3728 #ifdef STB_DEFINE
3729
3730 int stb_ischar(char c, char *set)
3731 {
3732 static unsigned char bit[8] = { 1,2,4,8,16,32,64,128 };
3733 static stb_perfect p;
3734 static unsigned char (*tables)[256];
3735 static char ** sets = NULL;
3736
3737 int z = stb_perfect_hash(&p, (int) set);
3738 if (z < 0) {
3739 int i,k,n,j,f;
3740 // special code that means free all existing data
3741 if (set == NULL) {
3742 stb_arr_free(sets);
3743 free(tables);
3744 tables = NULL;
3745 stb_perfect_destroy(&p);
3746 return 0;
3747 }
3748 stb_arr_push(sets, set);
3749 stb_perfect_destroy(&p);
3750 n = stb_perfect_create(&p, (unsigned int *) (char **) sets, stb_arr_len(sets));
3751 assert(n != 0);
3752 k = (n+7) >> 3;
3753 tables = (unsigned char (*)[256]) realloc(tables, sizeof(*tables) * k);
3754 memset(tables, 0, sizeof(*tables) * k);
3755 for (i=0; i < stb_arr_len(sets); ++i) {
3756 k = stb_perfect_hash(&p, (int) sets[i]);
3757 assert(k >= 0);
3758 n = k >> 3;
3759 f = bit[k&7];
3760 for (j=0; !j || sets[i][j]; ++j) {
3761 tables[n][(unsigned char) sets[i][j]] |= f;
3762 }
3763 }
3764 z = stb_perfect_hash(&p, (int) set);
3765 }
3766 return tables[z >> 3][(unsigned char) c] & bit[z & 7];
3767 }
3768
3769 #endif
3770
3771 //////////////////////////////////////////////////////////////////////////////
3772 //
3773 // Instantiated data structures
3774 //
3775 // This is an attempt to implement a templated data structure.
3776 //
3777 // Hash table: call stb_define_hash(TYPE,N,KEY,K1,K2,HASH,VALUE)
3778 // TYPE -- will define a structure type containing the hash table
3779 // N -- the name, will prefix functions named:
3780 // N create
3781 // N destroy
3782 // N get
3783 // N set, N add, N update,
3784 // N remove
3785 // KEY -- the type of the key. 'x == y' must be valid
3786 // K1,K2 -- keys never used by the app, used as flags in the hashtable
3787 // HASH -- a piece of code ending with 'return' that hashes key 'k'
3788 // VALUE -- the type of the value. 'x = y' must be valid
3789 //
3790 // Note that stb_define_hash_base can be used to define more sophisticated
3791 // hash tables, e.g. those that make copies of the key or use special
3792 // comparisons (e.g. strcmp).
3793
3794 #define STB_(prefix,name) stb__##prefix##name
3795 #define STB__(prefix,name) prefix##name
3796 #define STB__use(x) x
3797 #define STB__skip(x)
3798
3799 #define stb_declare_hash(PREFIX,TYPE,N,KEY,VALUE) \
3800 typedef struct stb__st_##TYPE TYPE;\
3801 PREFIX int STB__(N, init)(TYPE *h, int count);\
3802 PREFIX int STB__(N, memory_usage)(TYPE *h);\
3803 PREFIX TYPE * STB__(N, create)(void);\
3804 PREFIX TYPE * STB__(N, copy)(TYPE *h);\
3805 PREFIX void STB__(N, destroy)(TYPE *h);\
3806 PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v);\
3807 PREFIX VALUE STB__(N,get)(TYPE *a, KEY k);\
3808 PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v);\
3809 PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v);\
3810 PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v);\
3811 PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v);
3812
3813 #define STB_nocopy(x) (x)
3814 #define STB_nodelete(x) 0
3815 #define STB_nofields
3816 #define STB_nonullvalue(x)
3817 #define STB_nullvalue(x) x
3818 #define STB_safecompare(x) x
3819 #define STB_nosafe(x)
3820 #define STB_noprefix
3821
3822 #ifdef __GNUC__
3823 #define STB__nogcc(x)
3824 #else
3825 #define STB__nogcc(x) x
3826 #endif
3827
3828 #define stb_define_hash_base(PREFIX,TYPE,FIELDS,N,NC,LOAD_FACTOR, \
3829 KEY,EMPTY,DEL,COPY,DISPOSE,SAFE, \
3830 VCOMPARE,CCOMPARE,HASH, \
3831 VALUE,HASVNULL,VNULL) \
3832 \
3833 typedef struct \
3834 { \
3835 KEY k; \
3836 VALUE v; \
3837 } STB_(N,_hashpair); \
3838 \
3839 STB__nogcc( typedef struct stb__st_##TYPE TYPE; ) \
3840 struct stb__st_##TYPE { \
3841 FIELDS \
3842 STB_(N,_hashpair) *table; \
3843 unsigned int mask; \
3844 int count, limit; \
3845 int deleted; \
3846 \
3847 int delete_threshhold; \
3848 int grow_threshhold; \
3849 int shrink_threshhold; \
3850 unsigned char alloced, has_empty, has_del; \
3851 VALUE ev; VALUE dv; \
3852 }; \
3853 \
3854 static unsigned int STB_(N, hash)(KEY k) \
3855 { \
3856 HASH \
3857 } \
3858 \
3859 PREFIX int STB__(N, init)(TYPE *h, int count) \
3860 { \
3861 int i; \
3862 if (count < 4) count = 4; \
3863 h->limit = count; \
3864 h->count = 0; \
3865 h->mask = count-1; \
3866 h->deleted = 0; \
3867 h->grow_threshhold = (int) (count * LOAD_FACTOR); \
3868 h->has_empty = h->has_del = 0; \
3869 h->alloced = 0; \
3870 if (count <= 64) \
3871 h->shrink_threshhold = 0; \
3872 else \
3873 h->shrink_threshhold = (int) (count * (LOAD_FACTOR/2.25)); \
3874 h->delete_threshhold = (int) (count * (1-LOAD_FACTOR)/2); \
3875 h->table = (STB_(N,_hashpair)*) malloc(sizeof(h->table[0]) * count); \
3876 if (h->table == NULL) return 0; \
3877 /* ideally this gets turned into a memset32 automatically */ \
3878 for (i=0; i < count; ++i) \
3879 h->table[i].k = EMPTY; \
3880 return 1; \
3881 } \
3882 \
3883 PREFIX int STB__(N, memory_usage)(TYPE *h) \
3884 { \
3885 return sizeof(*h) + h->limit * sizeof(h->table[0]); \
3886 } \
3887 \
3888 PREFIX TYPE * STB__(N, create)(void) \
3889 { \
3890 TYPE *h = (TYPE *) malloc(sizeof(*h)); \
3891 if (h) { \
3892 if (STB__(N, init)(h, 16)) \
3893 h->alloced = 1; \
3894 else { free(h); h=NULL; } \
3895 } \
3896 return h; \
3897 } \
3898 \
3899 PREFIX void STB__(N, destroy)(TYPE *a) \
3900 { \
3901 int i; \
3902 for (i=0; i < a->limit; ++i) \
3903 if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k, DEL)) \
3904 DISPOSE(a->table[i].k); \
3905 free(a->table); \
3906 if (a->alloced) \
3907 free(a); \
3908 } \
3909 \
3910 static void STB_(N, rehash)(TYPE *a, int count); \
3911 \
3912 PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v) \
3913 { \
3914 unsigned int h = STB_(N, hash)(k); \
3915 unsigned int n = h & a->mask, s; \
3916 if (CCOMPARE(k,EMPTY)){ if (a->has_empty) *v = a->ev; return a->has_empty;}\
3917 if (CCOMPARE(k,DEL)) { if (a->has_del ) *v = a->dv; return a->has_del; }\
3918 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
3919 SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
3920 if (VCOMPARE(a->table[n].k,k)) { *v = a->table[n].v; return 1; } \
3921 s = stb_rehash(h) | 1; \
3922 for(;;) { \
3923 n = (n + s) & a->mask; \
3924 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
3925 SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
3926 if (VCOMPARE(a->table[n].k,k)) \
3927 { *v = a->table[n].v; return 1; } \
3928 } \
3929 } \
3930 \
3931 HASVNULL( \
3932 PREFIX VALUE STB__(N,get)(TYPE *a, KEY k) \
3933 { \
3934 VALUE v; \
3935 if (STB__(N,get_flag)(a,k,&v)) return v; \
3936 else return VNULL; \
3937 } \
3938 ) \
3939 \
3940 PREFIX int STB__(N,getkey)(TYPE *a, KEY k, KEY *kout) \
3941 { \
3942 unsigned int h = STB_(N, hash)(k); \
3943 unsigned int n = h & a->mask, s; \
3944 if (CCOMPARE(k,EMPTY)||CCOMPARE(k,DEL)) return 0; \
3945 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
3946 SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
3947 if (VCOMPARE(a->table[n].k,k)) { *kout = a->table[n].k; return 1; } \
3948 s = stb_rehash(h) | 1; \
3949 for(;;) { \
3950 n = (n + s) & a->mask; \
3951 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
3952 SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
3953 if (VCOMPARE(a->table[n].k,k)) \
3954 { *kout = a->table[n].k; return 1; } \
3955 } \
3956 } \
3957 \
3958 static int STB_(N,addset)(TYPE *a, KEY k, VALUE v, \
3959 int allow_new, int allow_old, int copy) \
3960 { \
3961 unsigned int h = STB_(N, hash)(k); \
3962 unsigned int n = h & a->mask; \
3963 int b = -1; \
3964 if (CCOMPARE(k,EMPTY)) { \
3965 if (a->has_empty ? allow_old : allow_new) { \
3966 n=a->has_empty; a->ev = v; a->has_empty = 1; return !n; \
3967 } else return 0; \
3968 } \
3969 if (CCOMPARE(k,DEL)) { \
3970 if (a->has_del ? allow_old : allow_new) { \
3971 n=a->has_del; a->dv = v; a->has_del = 1; return !n; \
3972 } else return 0; \
3973 } \
3974 if (!CCOMPARE(a->table[n].k, EMPTY)) { \
3975 unsigned int s; \
3976 if (CCOMPARE(a->table[n].k, DEL)) \
3977 b = n; \
3978 else if (VCOMPARE(a->table[n].k,k)) { \
3979 if (allow_old) \
3980 a->table[n].v = v; \
3981 return !allow_new; \
3982 } \
3983 s = stb_rehash(h) | 1; \
3984 for(;;) { \
3985 n = (n + s) & a->mask; \
3986 if (CCOMPARE(a->table[n].k, EMPTY)) break; \
3987 if (CCOMPARE(a->table[n].k, DEL)) { \
3988 if (b < 0) b = n; \
3989 } else if (VCOMPARE(a->table[n].k,k)) { \
3990 if (allow_old) \
3991 a->table[n].v = v; \
3992 return !allow_new; \
3993 } \
3994 } \
3995 } \
3996 if (!allow_new) return 0; \
3997 if (b < 0) b = n; else --a->deleted; \
3998 a->table[b].k = copy ? COPY(k) : k; \
3999 a->table[b].v = v; \
4000 ++a->count; \
4001 if (a->count > a->grow_threshhold) \
4002 STB_(N,rehash)(a, a->limit*2); \
4003 return 1; \
4004 } \
4005 \
4006 PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,1,1);}\
4007 PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,0,1);}\
4008 PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v){return STB_(N,addset)(a,k,v,0,1,1);}\
4009 \
4010 PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v) \
4011 { \
4012 unsigned int h = STB_(N, hash)(k); \
4013 unsigned int n = h & a->mask, s; \
4014 if (CCOMPARE(k,EMPTY)) { if (a->has_empty) { if(v)*v = a->ev; a->has_empty=0; return 1; } return 0; } \
4015 if (CCOMPARE(k,DEL)) { if (a->has_del ) { if(v)*v = a->dv; a->has_del =0; return 1; } return 0; } \
4016 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4017 if (SAFE(CCOMPARE(a->table[n].k,DEL) || ) !VCOMPARE(a->table[n].k,k)) { \
4018 s = stb_rehash(h) | 1; \
4019 for(;;) { \
4020 n = (n + s) & a->mask; \
4021 if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
4022 SAFE(if (CCOMPARE(a->table[n].k, DEL)) continue;) \
4023 if (VCOMPARE(a->table[n].k,k)) break; \
4024 } \
4025 } \
4026 DISPOSE(a->table[n].k); \
4027 a->table[n].k = DEL; \
4028 --a->count; \
4029 ++a->deleted; \
4030 if (v != NULL) \
4031 *v = a->table[n].v; \
4032 if (a->count < a->shrink_threshhold) \
4033 STB_(N, rehash)(a, a->limit >> 1); \
4034 else if (a->deleted > a->delete_threshhold) \
4035 STB_(N, rehash)(a, a->limit); \
4036 return 1; \
4037 } \
4038 \
4039 PREFIX TYPE * STB__(NC, copy)(TYPE *a) \
4040 { \
4041 int i; \
4042 TYPE *h = (TYPE *) malloc(sizeof(*h)); \
4043 if (!h) return NULL; \
4044 if (!STB__(N, init)(h, a->limit)) { free(h); return NULL; } \
4045 h->count = a->count; \
4046 h->deleted = a->deleted; \
4047 h->alloced = 1; \
4048 h->ev = a->ev; h->dv = a->dv; \
4049 h->has_empty = a->has_empty; h->has_del = a->has_del; \
4050 memcpy(h->table, a->table, h->limit * sizeof(h->table[0])); \
4051 for (i=0; i < a->limit; ++i) \
4052 if (!CCOMPARE(h->table[i].k,EMPTY) && !CCOMPARE(h->table[i].k,DEL)) \
4053 h->table[i].k = COPY(h->table[i].k); \
4054 return h; \
4055 } \
4056 \
4057 static void STB_(N, rehash)(TYPE *a, int count) \
4058 { \
4059 int i; \
4060 TYPE b; \
4061 STB__(N, init)(&b, count); \
4062 for (i=0; i < a->limit; ++i) \
4063 if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k,DEL)) \
4064 STB_(N,addset)(&b, a->table[i].k, a->table[i].v,1,1,0); \
4065 free(a->table); \
4066 a->table = b.table; \
4067 a->mask = b.mask; \
4068 a->count = b.count; \
4069 a->limit = b.limit; \
4070 a->deleted = b.deleted; \
4071 a->delete_threshhold = b.delete_threshhold; \
4072 a->grow_threshhold = b.grow_threshhold; \
4073 a->shrink_threshhold = b.shrink_threshhold; \
4074 }
4075
4076 #define STB_equal(a,b) ((a) == (b))
4077
4078 #define stb_define_hash(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE) \
4079 stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
4080 KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
4081 STB_equal,STB_equal,HASH, \
4082 VALUE,STB_nonullvalue,0)
4083
4084 #define stb_define_hash_vnull(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE,VNULL) \
4085 stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
4086 KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
4087 STB_equal,STB_equal,HASH, \
4088 VALUE,STB_nullvalue,VNULL)
4089
4090 //////////////////////////////////////////////////////////////////////////////
4091 //
4092 // stb_ptrmap
4093 //
4094 // An stb_ptrmap data structure is an O(1) hash table between pointers. One
4095 // application is to let you store "extra" data associated with pointers,
4096 // which is why it was originally called stb_extra.
4097
4098 stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *)
4099 stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32)
4100
4101 STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *));
4102 STB_EXTERN stb_ptrmap *stb_ptrmap_new(void);
4103
4104 STB_EXTERN stb_idict * stb_idict_new_size(int size);
4105 STB_EXTERN void stb_idict_remove_all(stb_idict *e);
4106
4107 #ifdef STB_DEFINE
4108
4109 #define STB_EMPTY ((void *) 2)
4110 #define STB_EDEL ((void *) 6)
4111
4112 stb_define_hash_base(STB_noprefix,stb_ptrmap, STB_nofields, stb_ptrmap_,stb_ptrmap_,0.85f,
4113 void *,STB_EMPTY,STB_EDEL,STB_nocopy,STB_nodelete,STB_nosafe,
4114 STB_equal,STB_equal,return stb_hashptr(k);,
4115 void *,STB_nullvalue,NULL)
4116
4117 stb_ptrmap *stb_ptrmap_new(void)
4118 {
4119 return stb_ptrmap_create();
4120 }
4121
4122 void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *))
4123 {
4124 int i;
4125 if (free_func)
4126 for (i=0; i < e->limit; ++i)
4127 if (e->table[i].k != STB_EMPTY && e->table[i].k != STB_EDEL) {
4128 if (free_func == free)
4129 free(e->table[i].v); // allow STB_MALLOC_WRAPPER to operate
4130 else
4131 free_func(e->table[i].v);
4132 }
4133 stb_ptrmap_destroy(e);
4134 }
4135
4136 // extra fields needed for stua_dict
4137 #define STB_IEMPTY ((int) 1)
4138 #define STB_IDEL ((int) 3)
4139 stb_define_hash_base(STB_noprefix, stb_idict, short type; short gc; STB_nofields, stb_idict_,stb_idict_,0.85f,
4140 stb_int32,STB_IEMPTY,STB_IDEL,STB_nocopy,STB_nodelete,STB_nosafe,
4141 STB_equal,STB_equal,
4142 return stb_rehash_improved(k);,stb_int32,STB_nonullvalue,0)
4143
4144 stb_idict * stb_idict_new_size(int size)
4145 {
4146 stb_idict *e = (stb_idict *) malloc(sizeof(*e));
4147 if (e) {
4148 if (!stb_is_pow2(size))
4149 size = 1 << stb_log2_ceil(size);
4150 stb_idict_init(e, size);
4151 e->alloced = 1;
4152 }
4153 return e;
4154 }
4155
4156 void stb_idict_remove_all(stb_idict *e)
4157 {
4158 int n;
4159 for (n=0; n < e->limit; ++n)
4160 e->table[n].k = STB_IEMPTY;
4161 e->has_empty = e->has_del = 0;
4162 }
4163 #endif
4164
4165 //////////////////////////////////////////////////////////////////////////////
4166 //
4167 // stb_sparse_ptr_matrix
4168 //
4169 // An stb_ptrmap data structure is an O(1) hash table storing an arbitrary
4170 // block of data for a given pair of pointers.
4171 //
4172 // If create=0, returns
4173
4174 typedef struct stb__st_stb_spmatrix stb_spmatrix;
4175
4176 STB_EXTERN stb_spmatrix * stb_sparse_ptr_matrix_new(int val_size);
4177 STB_EXTERN void stb_sparse_ptr_matrix_free(stb_spmatrix *z);
4178 STB_EXTERN void * stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create);
4179
4180 #ifdef STB_DEFINE
4181 typedef struct
4182 {
4183 void *a;
4184 void *b;
4185 } stb__ptrpair;
4186
4187 static stb__ptrpair stb__ptrpair_empty = { (void *) 1, (void *) 1 };
4188 static stb__ptrpair stb__ptrpair_del = { (void *) 2, (void *) 2 };
4189
4190 #define STB__equal_ptrpair(x,y) ((x).a == (y).a && (x).b == (y).b)
4191
4192 stb_define_hash_base(static, stb_spmatrix, int val_size; void *arena;, stb__spmatrix_,stb__spmatrix_, 0.85,
4193 stb__ptrpair, stb__ptrpair_empty, stb__ptrpair_del,
4194 STB_nocopy, STB_nodelete, STB_nosafe,
4195 STB__equal_ptrpair, STB__equal_ptrpair, return stb_rehash(stb_hashptr(k.a))+stb_hashptr(k.b);,
4196 void *, STB_nullvalue, 0)
4197
4198 stb_spmatrix *stb_sparse_ptr_matrix_new(int val_size)
4199 {
4200 stb_spmatrix *m = stb__spmatrix_create();
4201 if (m) m->val_size = val_size;
4202 if (m) m->arena = stb_malloc_global(1);
4203 return m;
4204 }
4205
4206 void stb_sparse_ptr_matrix_free(stb_spmatrix *z)
4207 {
4208 if (z->arena) stb_free(z->arena);
4209 stb__spmatrix_destroy(z);
4210 }
4211
4212 void *stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create)
4213 {
4214 stb__ptrpair t = { a,b };
4215 void *data = stb__spmatrix_get(z, t);
4216 if (!data && create) {
4217 data = stb_malloc_raw(z->arena, z->val_size);
4218 if (!data) return NULL;
4219 memset(data, 0, z->val_size);
4220 stb__spmatrix_add(z, t, data);
4221 }
4222 return data;
4223 }
4224 #endif
4225
4226
4227
4228 //////////////////////////////////////////////////////////////////////////////
4229 //
4230 // SDICT: Hash Table for Strings (symbol table)
4231 //
4232 // if "use_arena=1", then strings will be copied
4233 // into blocks and never freed until the sdict is freed;
4234 // otherwise they're malloc()ed and free()d on the fly.
4235 // (specify use_arena=1 if you never stb_sdict_remove)
4236
4237 stb_declare_hash(STB_EXTERN, stb_sdict, stb_sdict_, char *, void *)
4238
4239 STB_EXTERN stb_sdict * stb_sdict_new(int use_arena);
4240 STB_EXTERN stb_sdict * stb_sdict_copy(stb_sdict*);
4241 STB_EXTERN void stb_sdict_delete(stb_sdict *);
4242 STB_EXTERN void * stb_sdict_change(stb_sdict *, char *str, void *p);
4243 STB_EXTERN int stb_sdict_count(stb_sdict *d);
4244
4245 #define stb_sdict_for(d,i,q,z) \
4246 for(i=0; i < (d)->limit ? q=(d)->table[i].k,z=(d)->table[i].v,1 : 0; ++i) \
4247 if (q==NULL||q==(void *) 1);else // reversed makes macro friendly
4248
4249 #ifdef STB_DEFINE
4250
4251 #define STB_DEL ((void *) 1)
4252 #define STB_SDEL ((char *) 1)
4253
4254 #define stb_sdict__copy(x) \
4255 strcpy(a->arena ? stb_malloc_string(a->arena, strlen(x)+1) \
4256 : (char *) malloc(strlen(x)+1), x)
4257
4258 #define stb_sdict__dispose(x) if (!a->arena) free(x)
4259
4260 stb_define_hash_base(STB_noprefix, stb_sdict, void*arena;, stb_sdict_,stb_sdictinternal_, 0.85f,
4261 char *, NULL, STB_SDEL, stb_sdict__copy, stb_sdict__dispose,
4262 STB_safecompare, !strcmp, STB_equal, return stb_hash(k);,
4263 void *, STB_nullvalue, NULL)
4264
4265 int stb_sdict_count(stb_sdict *a)
4266 {
4267 return a->count;
4268 }
4269
4270 stb_sdict * stb_sdict_new(int use_arena)
4271 {
4272 stb_sdict *d = stb_sdict_create();
4273 if (d == NULL) return NULL;
4274 d->arena = use_arena ? stb_malloc_global(1) : NULL;
4275 return d;
4276 }
4277
4278 stb_sdict* stb_sdict_copy(stb_sdict *old)
4279 {
4280 stb_sdict *n;
4281 void *old_arena = old->arena;
4282 void *new_arena = old_arena ? stb_malloc_global(1) : NULL;
4283 old->arena = new_arena;
4284 n = stb_sdictinternal_copy(old);
4285 old->arena = old_arena;
4286 if (n)
4287 n->arena = new_arena;
4288 else if (new_arena)
4289 stb_free(new_arena);
4290 return n;
4291 }
4292
4293
4294 void stb_sdict_delete(stb_sdict *d)
4295 {
4296 if (d->arena)
4297 stb_free(d->arena);
4298 stb_sdict_destroy(d);
4299 }
4300
4301 void * stb_sdict_change(stb_sdict *d, char *str, void *p)
4302 {
4303 void *q = stb_sdict_get(d, str);
4304 stb_sdict_set(d, str, p);
4305 return q;
4306 }
4307 #endif
4308
4309 //////////////////////////////////////////////////////////////////////////////
4310 //
4311 // Instantiated data structures
4312 //
4313 // This is an attempt to implement a templated data structure.
4314 // What you do is define a struct foo, and then include several
4315 // pointer fields to struct foo in your struct. Then you call
4316 // the instantiator, which creates the functions that implement
4317 // the data structure. This requires massive undebuggable #defines,
4318 // so we limit the cases where we do this.
4319 //
4320 // AA tree is an encoding of a 2-3 tree whereas RB trees encode a 2-3-4 tree;
4321 // much simpler code due to fewer cases.
4322
4323 #define stb__bst_parent(x) x
4324 #define stb__bst_noparent(x)
4325
4326 #define stb_bst_fields(N) \
4327 *STB_(N,left), *STB_(N,right); \
4328 unsigned char STB_(N,level)
4329
4330 #define stb_bst_fields_parent(N) \
4331 *STB_(N,left), *STB_(N,right), *STB_(N,parent); \
4332 unsigned char STB_(N,level)
4333
4334 #define STB__level(N,x) ((x) ? (x)->STB_(N,level) : 0)
4335
4336 #define stb_bst_base(TYPE, N, TREE, M, compare, PAR) \
4337 \
4338 static int STB_(N,_compare)(TYPE *p, TYPE *q) \
4339 { \
4340 compare \
4341 } \
4342 \
4343 static void STB_(N,setleft)(TYPE *q, TYPE *v) \
4344 { \
4345 q->STB_(N,left) = v; \
4346 PAR(if (v) v->STB_(N,parent) = q;) \
4347 } \
4348 \
4349 static void STB_(N,setright)(TYPE *q, TYPE *v) \
4350 { \
4351 q->STB_(N,right) = v; \
4352 PAR(if (v) v->STB_(N,parent) = q;) \
4353 } \
4354 \
4355 static TYPE *STB_(N,skew)(TYPE *q) \
4356 { \
4357 if (q == NULL) return q; \
4358 if (q->STB_(N,left) \
4359 && q->STB_(N,left)->STB_(N,level) == q->STB_(N,level)) { \
4360 TYPE *p = q->STB_(N,left); \
4361 STB_(N,setleft)(q, p->STB_(N,right)); \
4362 STB_(N,setright)(p, q); \
4363 return p; \
4364 } \
4365 return q; \
4366 } \
4367 \
4368 static TYPE *STB_(N,split)(TYPE *p) \
4369 { \
4370 TYPE *q = p->STB_(N,right); \
4371 if (q && q->STB_(N,right) \
4372 && q->STB_(N,right)->STB_(N,level) == p->STB_(N,level)) { \
4373 STB_(N,setright)(p, q->STB_(N,left)); \
4374 STB_(N,setleft)(q,p); \
4375 ++q->STB_(N,level); \
4376 return q; \
4377 } \
4378 return p; \
4379 } \
4380 \
4381 TYPE *STB__(N,insert)(TYPE *tree, TYPE *item) \
4382 { \
4383 int c; \
4384 if (tree == NULL) { \
4385 item->STB_(N,left) = NULL; \
4386 item->STB_(N,right) = NULL; \
4387 item->STB_(N,level) = 1; \
4388 PAR(item->STB_(N,parent) = NULL;) \
4389 return item; \
4390 } \
4391 c = STB_(N,_compare)(item,tree); \
4392 if (c == 0) { \
4393 if (item != tree) { \
4394 STB_(N,setleft)(item, tree->STB_(N,left)); \
4395 STB_(N,setright)(item, tree->STB_(N,right)); \
4396 item->STB_(N,level) = tree->STB_(N,level); \
4397 PAR(item->STB_(N,parent) = NULL;) \
4398 } \
4399 return item; \
4400 } \
4401 if (c < 0) \
4402 STB_(N,setleft )(tree, STB__(N,insert)(tree->STB_(N,left), item)); \
4403 else \
4404 STB_(N,setright)(tree, STB__(N,insert)(tree->STB_(N,right), item)); \
4405 tree = STB_(N,skew)(tree); \
4406 tree = STB_(N,split)(tree); \
4407 PAR(tree->STB_(N,parent) = NULL;) \
4408 return tree; \
4409 } \
4410 \
4411 TYPE *STB__(N,remove)(TYPE *tree, TYPE *item) \
4412 { \
4413 static TYPE *delnode, *leaf, *restore; \
4414 if (tree == NULL) return NULL; \
4415 leaf = tree; \
4416 if (STB_(N,_compare)(item, tree) < 0) { \
4417 STB_(N,setleft)(tree, STB__(N,remove)(tree->STB_(N,left), item)); \
4418 } else { \
4419 TYPE *r; \
4420 delnode = tree; \
4421 r = STB__(N,remove)(tree->STB_(N,right), item); \
4422 /* maybe move 'leaf' up to this location */ \
4423 if (restore == tree) { tree = leaf; leaf = restore = NULL; } \
4424 STB_(N,setright)(tree,r); \
4425 assert(tree->STB_(N,right) != tree); \
4426 } \
4427 if (tree == leaf) { \
4428 if (delnode == item) { \
4429 tree = tree->STB_(N,right); \
4430 assert(leaf->STB_(N,left) == NULL); \
4431 /* move leaf (the right sibling) up to delnode */ \
4432 STB_(N,setleft )(leaf, item->STB_(N,left )); \
4433 STB_(N,setright)(leaf, item->STB_(N,right)); \
4434 leaf->STB_(N,level) = item->STB_(N,level); \
4435 if (leaf != item) \
4436 restore = delnode; \
4437 } \
4438 delnode = NULL; \
4439 } else { \
4440 if (STB__level(N,tree->STB_(N,left) ) < tree->STB_(N,level)-1 || \
4441 STB__level(N,tree->STB_(N,right)) < tree->STB_(N,level)-1) { \
4442 --tree->STB_(N,level); \
4443 if (STB__level(N,tree->STB_(N,right)) > tree->STB_(N,level)) \
4444 tree->STB_(N,right)->STB_(N,level) = tree->STB_(N,level); \
4445 tree = STB_(N,skew)(tree); \
4446 STB_(N,setright)(tree, STB_(N,skew)(tree->STB_(N,right))); \
4447 if (tree->STB_(N,right)) \
4448 STB_(N,setright)(tree->STB_(N,right), \
4449 STB_(N,skew)(tree->STB_(N,right)->STB_(N,right))); \
4450 tree = STB_(N,split)(tree); \
4451 if (tree->STB_(N,right)) \
4452 STB_(N,setright)(tree, STB_(N,split)(tree->STB_(N,right))); \
4453 } \
4454 } \
4455 PAR(if (tree) tree->STB_(N,parent) = NULL;) \
4456 return tree; \
4457 } \
4458 \
4459 TYPE *STB__(N,last)(TYPE *tree) \
4460 { \
4461 if (tree) \
4462 while (tree->STB_(N,right)) tree = tree->STB_(N,right); \
4463 return tree; \
4464 } \
4465 \
4466 TYPE *STB__(N,first)(TYPE *tree) \
4467 { \
4468 if (tree) \
4469 while (tree->STB_(N,left)) tree = tree->STB_(N,left); \
4470 return tree; \
4471 } \
4472 \
4473 TYPE *STB__(N,next)(TYPE *tree, TYPE *item) \
4474 { \
4475 TYPE *next = NULL; \
4476 if (item->STB_(N,right)) \
4477 return STB__(N,first)(item->STB_(N,right)); \
4478 PAR( \
4479 while(item->STB_(N,parent)) { \
4480 TYPE *up = item->STB_(N,parent); \
4481 if (up->STB_(N,left) == item) return up; \
4482 item = up; \
4483 } \
4484 return NULL; \
4485 ) \
4486 while (tree != item) { \
4487 if (STB_(N,_compare)(item, tree) < 0) { \
4488 next = tree; \
4489 tree = tree->STB_(N,left); \
4490 } else { \
4491 tree = tree->STB_(N,right); \
4492 } \
4493 } \
4494 return next; \
4495 } \
4496 \
4497 TYPE *STB__(N,prev)(TYPE *tree, TYPE *item) \
4498 { \
4499 TYPE *next = NULL; \
4500 if (item->STB_(N,left)) \
4501 return STB__(N,last)(item->STB_(N,left)); \
4502 PAR( \
4503 while(item->STB_(N,parent)) { \
4504 TYPE *up = item->STB_(N,parent); \
4505 if (up->STB_(N,right) == item) return up; \
4506 item = up; \
4507 } \
4508 return NULL; \
4509 ) \
4510 while (tree != item) { \
4511 if (STB_(N,_compare)(item, tree) < 0) { \
4512 tree = tree->STB_(N,left); \
4513 } else { \
4514 next = tree; \
4515 tree = tree->STB_(N,right); \
4516 } \
4517 } \
4518 return next; \
4519 } \
4520 \
4521 STB__DEBUG( \
4522 void STB__(N,_validate)(TYPE *tree, int root) \
4523 { \
4524 if (tree == NULL) return; \
4525 PAR(if(root) assert(tree->STB_(N,parent) == NULL);) \
4526 assert(STB__level(N,tree->STB_(N,left) ) == tree->STB_(N,level)-1); \
4527 assert(STB__level(N,tree->STB_(N,right)) <= tree->STB_(N,level)); \
4528 assert(STB__level(N,tree->STB_(N,right)) >= tree->STB_(N,level)-1); \
4529 if (tree->STB_(N,right)) { \
4530 assert(STB__level(N,tree->STB_(N,right)->STB_(N,right)) \
4531 != tree->STB_(N,level)); \
4532 PAR(assert(tree->STB_(N,right)->STB_(N,parent) == tree);) \
4533 } \
4534 PAR(if(tree->STB_(N,left)) assert(tree->STB_(N,left)->STB_(N,parent) == tree);) \
4535 STB__(N,_validate)(tree->STB_(N,left) ,0); \
4536 STB__(N,_validate)(tree->STB_(N,right),0); \
4537 } \
4538 ) \
4539 \
4540 typedef struct \
4541 { \
4542 TYPE *root; \
4543 } TREE; \
4544 \
4545 void STB__(M,Insert)(TREE *tree, TYPE *item) \
4546 { tree->root = STB__(N,insert)(tree->root, item); } \
4547 void STB__(M,Remove)(TREE *tree, TYPE *item) \
4548 { tree->root = STB__(N,remove)(tree->root, item); } \
4549 TYPE *STB__(M,Next)(TREE *tree, TYPE *item) \
4550 { return STB__(N,next)(tree->root, item); } \
4551 TYPE *STB__(M,Prev)(TREE *tree, TYPE *item) \
4552 { return STB__(N,prev)(tree->root, item); } \
4553 TYPE *STB__(M,First)(TREE *tree) { return STB__(N,first)(tree->root); } \
4554 TYPE *STB__(M,Last) (TREE *tree) { return STB__(N,last) (tree->root); } \
4555 void STB__(M,Init)(TREE *tree) { tree->root = NULL; }
4556
4557
4558 #define stb_bst_find(N,tree,fcompare) \
4559 { \
4560 int c; \
4561 while (tree != NULL) { \
4562 fcompare \
4563 if (c == 0) return tree; \
4564 if (c < 0) tree = tree->STB_(N,left); \
4565 else tree = tree->STB_(N,right); \
4566 } \
4567 return NULL; \
4568 }
4569
4570 #define stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,PAR) \
4571 stb_bst_base(TYPE,N,TREE,M, \
4572 VTYPE a = p->vfield; VTYPE b = q->vfield; return (compare);, PAR ) \
4573 \
4574 TYPE *STB__(N,find)(TYPE *tree, VTYPE a) \
4575 stb_bst_find(N,tree,VTYPE b = tree->vfield; c = (compare);) \
4576 TYPE *STB__(M,Find)(TREE *tree, VTYPE a) \
4577 { return STB__(N,find)(tree->root, a); }
4578
4579 #define stb_bst(TYPE,N,TREE,M,vfield,VTYPE,compare) \
4580 stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_noparent)
4581 #define stb_bst_parent(TYPE,N,TREE,M,vfield,VTYPE,compare) \
4582 stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_parent)
4583
4584
4585
4586 //////////////////////////////////////////////////////////////////////////////
4587 //
4588 // Pointer Nulling
4589 //
4590 // This lets you automatically NULL dangling pointers to "registered"
4591 // objects. Note that you have to make sure you call the appropriate
4592 // functions when you free or realloc blocks of memory that contain
4593 // pointers or pointer targets. stb.h can automatically do this for
4594 // stb_arr, or for all frees/reallocs if it's wrapping them.
4595 //
4596
4597 #ifdef STB_NPTR
4598
4599 STB_EXTERN void stb_nptr_set(void *address_of_pointer, void *value_to_write);
4600 STB_EXTERN void stb_nptr_didset(void *address_of_pointer);
4601
4602 STB_EXTERN void stb_nptr_didfree(void *address_being_freed, int len);
4603 STB_EXTERN void stb_nptr_free(void *address_being_freed, int len);
4604
4605 STB_EXTERN void stb_nptr_didrealloc(void *new_address, void *old_address, int len);
4606 STB_EXTERN void stb_nptr_recache(void); // recache all known pointers
4607 // do this after pointer sets outside your control, slow
4608
4609 #ifdef STB_DEFINE
4610 // for fast updating on free/realloc, we need to be able to find
4611 // all the objects (pointers and targets) within a given block;
4612 // this precludes hashing
4613
4614 // we use a three-level hierarchy of memory to minimize storage:
4615 // level 1: 65536 pointers to stb__memory_node (always uses 256 KB)
4616 // level 2: each stb__memory_node represents a 64K block of memory
4617 // with 256 stb__memory_leafs (worst case 64MB)
4618 // level 3: each stb__memory_leaf represents 256 bytes of memory
4619 // using a list of target locations and a list of pointers
4620 // (which are hopefully fairly short normally!)
4621
4622 // this approach won't work in 64-bit, which has a much larger address
4623 // space. need to redesign
4624
4625 #define STB__NPTR_ROOT_LOG2 16
4626 #define STB__NPTR_ROOT_NUM (1 << STB__NPTR_ROOT_LOG2)
4627 #define STB__NPTR_ROOT_SHIFT (32 - STB__NPTR_ROOT_LOG2)
4628
4629 #define STB__NPTR_NODE_LOG2 5
4630 #define STB__NPTR_NODE_NUM (1 << STB__NPTR_NODE_LOG2)
4631 #define STB__NPTR_NODE_MASK (STB__NPTR_NODE_NUM-1)
4632 #define STB__NPTR_NODE_SHIFT (STB__NPTR_ROOT_SHIFT - STB__NPTR_NODE_LOG2)
4633 #define STB__NPTR_NODE_OFFSET(x) (((x) >> STB__NPTR_NODE_SHIFT) & STB__NPTR_NODE_MASK)
4634
4635 typedef struct stb__st_nptr
4636 {
4637 void *ptr; // address of actual pointer
4638 struct stb__st_nptr *next; // next pointer with same target
4639 struct stb__st_nptr **prev; // prev pointer with same target, address of 'next' field (or first)
4640 struct stb__st_nptr *next_in_block;
4641 } stb__nptr;
4642
4643 typedef struct stb__st_nptr_target
4644 {
4645 void *ptr; // address of target
4646 stb__nptr *first; // address of first nptr pointing to this
4647 struct stb__st_nptr_target *next_in_block;
4648 } stb__nptr_target;
4649
4650 typedef struct
4651 {
4652 stb__nptr *pointers;
4653 stb__nptr_target *targets;
4654 } stb__memory_leaf;
4655
4656 typedef struct
4657 {
4658 stb__memory_leaf *children[STB__NPTR_NODE_NUM];
4659 } stb__memory_node;
4660
4661 stb__memory_node *stb__memtab_root[STB__NPTR_ROOT_NUM];
4662
4663 static stb__memory_leaf *stb__nptr_find_leaf(void *mem)
4664 {
4665 stb_uint32 address = (stb_uint32) mem;
4666 stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
4667 if (z)
4668 return z->children[STB__NPTR_NODE_OFFSET(address)];
4669 else
4670 return NULL;
4671 }
4672
4673 static void * stb__nptr_alloc(int size)
4674 {
4675 return stb__realloc_raw(0,size);
4676 }
4677
4678 static void stb__nptr_free(void *p)
4679 {
4680 stb__realloc_raw(p,0);
4681 }
4682
4683 static stb__memory_leaf *stb__nptr_make_leaf(void *mem)
4684 {
4685 stb_uint32 address = (stb_uint32) mem;
4686 stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
4687 stb__memory_leaf *f;
4688 if (!z) {
4689 int i;
4690 z = (stb__memory_node *) stb__nptr_alloc(sizeof(*stb__memtab_root[0]));
4691 stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT] = z;
4692 for (i=0; i < 256; ++i)
4693 z->children[i] = 0;
4694 }
4695 f = (stb__memory_leaf *) stb__nptr_alloc(sizeof(*f));
4696 z->children[STB__NPTR_NODE_OFFSET(address)] = f;
4697 f->pointers = NULL;
4698 f->targets = NULL;
4699 return f;
4700 }
4701
4702 static stb__nptr_target *stb__nptr_find_target(void *target, int force)
4703 {
4704 stb__memory_leaf *p = stb__nptr_find_leaf(target);
4705 if (p) {
4706 stb__nptr_target *t = p->targets;
4707 while (t) {
4708 if (t->ptr == target)
4709 return t;
4710 t = t->next_in_block;
4711 }
4712 }
4713 if (force) {
4714 stb__nptr_target *t = (stb__nptr_target*) stb__nptr_alloc(sizeof(*t));
4715 if (!p) p = stb__nptr_make_leaf(target);
4716 t->ptr = target;
4717 t->first = NULL;
4718 t->next_in_block = p->targets;
4719 p->targets = t;
4720 return t;
4721 } else
4722 return NULL;
4723 }
4724
4725 static stb__nptr *stb__nptr_find_pointer(void *ptr, int force)
4726 {
4727 stb__memory_leaf *p = stb__nptr_find_leaf(ptr);
4728 if (p) {
4729 stb__nptr *t = p->pointers;
4730 while (t) {
4731 if (t->ptr == ptr)
4732 return t;
4733 t = t->next_in_block;
4734 }
4735 }
4736 if (force) {
4737 stb__nptr *t = (stb__nptr *) stb__nptr_alloc(sizeof(*t));
4738 if (!p) p = stb__nptr_make_leaf(ptr);
4739 t->ptr = ptr;
4740 t->next = NULL;
4741 t->prev = NULL;
4742 t->next_in_block = p->pointers;
4743 p->pointers = t;
4744 return t;
4745 } else
4746 return NULL;
4747 }
4748
4749 void stb_nptr_set(void *address_of_pointer, void *value_to_write)
4750 {
4751 if (*(void **)address_of_pointer != value_to_write) {
4752 *(void **) address_of_pointer = value_to_write;
4753 stb_nptr_didset(address_of_pointer);
4754 }
4755 }
4756
4757 void stb_nptr_didset(void *address_of_pointer)
4758 {
4759 // first unlink from old chain
4760 void *new_address;
4761 stb__nptr *p = stb__nptr_find_pointer(address_of_pointer, 1); // force building if doesn't exist
4762 if (p->prev) { // if p->prev is NULL, we just built it, or it was NULL
4763 *(p->prev) = p->next;
4764 if (p->next) p->next->prev = p->prev;
4765 }
4766 // now add to new chain
4767 new_address = *(void **)address_of_pointer;
4768 if (new_address != NULL) {
4769 stb__nptr_target *t = stb__nptr_find_target(new_address, 1);
4770 p->next = t->first;
4771 if (p->next) p->next->prev = &p->next;
4772 p->prev = &t->first;
4773 t->first = p;
4774 } else {
4775 p->prev = NULL;
4776 p->next = NULL;
4777 }
4778 }
4779
4780 void stb__nptr_block(void *address, int len, void (*function)(stb__memory_leaf *f, int datum, void *start, void *end), int datum)
4781 {
4782 void *end_address = (void *) ((char *) address + len - 1);
4783 stb__memory_node *n;
4784 stb_uint32 start = (stb_uint32) address;
4785 stb_uint32 end = start + len - 1;
4786
4787 int b0 = start >> STB__NPTR_ROOT_SHIFT;
4788 int b1 = end >> STB__NPTR_ROOT_SHIFT;
4789 int b=b0,i,e0,e1;
4790
4791 e0 = STB__NPTR_NODE_OFFSET(start);
4792
4793 if (datum <= 0) {
4794 // first block
4795 n = stb__memtab_root[b0];
4796 if (n) {
4797 if (b0 != b1)
4798 e1 = STB__NPTR_NODE_NUM-1;
4799 else
4800 e1 = STB__NPTR_NODE_OFFSET(end);
4801 for (i=e0; i <= e1; ++i)
4802 if (n->children[i])
4803 function(n->children[i], datum, address, end_address);
4804 }
4805 if (b1 > b0) {
4806 // blocks other than the first and last block
4807 for (b=b0+1; b < b1; ++b) {
4808 n = stb__memtab_root[b];
4809 if (n)
4810 for (i=0; i <= STB__NPTR_NODE_NUM-1; ++i)
4811 if (n->children[i])
4812 function(n->children[i], datum, address, end_address);
4813 }
4814 // last block
4815 n = stb__memtab_root[b1];
4816 if (n) {
4817 e1 = STB__NPTR_NODE_OFFSET(end);
4818 for (i=0; i <= e1; ++i)
4819 if (n->children[i])
4820 function(n->children[i], datum, address, end_address);
4821 }
4822 }
4823 } else {
4824 if (b1 > b0) {
4825 // last block
4826 n = stb__memtab_root[b1];
4827 if (n) {
4828 e1 = STB__NPTR_NODE_OFFSET(end);
4829 for (i=e1; i >= 0; --i)
4830 if (n->children[i])
4831 function(n->children[i], datum, address, end_address);
4832 }
4833 // blocks other than the first and last block
4834 for (b=b1-1; b > b0; --b) {
4835 n = stb__memtab_root[b];
4836 if (n)
4837 for (i=STB__NPTR_NODE_NUM-1; i >= 0; --i)
4838 if (n->children[i])
4839 function(n->children[i], datum, address, end_address);
4840 }
4841 }
4842 // first block
4843 n = stb__memtab_root[b0];
4844 if (n) {
4845 if (b0 != b1)
4846 e1 = STB__NPTR_NODE_NUM-1;
4847 else
4848 e1 = STB__NPTR_NODE_OFFSET(end);
4849 for (i=e1; i >= e0; --i)
4850 if (n->children[i])
4851 function(n->children[i], datum, address, end_address);
4852 }
4853 }
4854 }
4855
4856 static void stb__nptr_delete_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
4857 {
4858 stb__nptr **p = &f->pointers;
4859 while (*p) {
4860 stb__nptr *n = *p;
4861 if (n->ptr >= start && n->ptr <= end) {
4862 // unlink
4863 if (n->prev) {
4864 *(n->prev) = n->next;
4865 if (n->next) n->next->prev = n->prev;
4866 }
4867 *p = n->next_in_block;
4868 stb__nptr_free(n);
4869 } else
4870 p = &(n->next_in_block);
4871 }
4872 }
4873
4874 static void stb__nptr_delete_targets(stb__memory_leaf *f, int offset, void *start, void *end)
4875 {
4876 stb__nptr_target **p = &f->targets;
4877 while (*p) {
4878 stb__nptr_target *n = *p;
4879 if (n->ptr >= start && n->ptr <= end) {
4880 // null pointers
4881 stb__nptr *z = n->first;
4882 while (z) {
4883 stb__nptr *y = z->next;
4884 z->prev = NULL;
4885 z->next = NULL;
4886 *(void **) z->ptr = NULL;
4887 z = y;
4888 }
4889 // unlink this target
4890 *p = n->next_in_block;
4891 stb__nptr_free(n);
4892 } else
4893 p = &(n->next_in_block);
4894 }
4895 }
4896
4897 void stb_nptr_didfree(void *address_being_freed, int len)
4898 {
4899 // step one: delete all pointers in this block
4900 stb__nptr_block(address_being_freed, len, stb__nptr_delete_pointers, 0);
4901 // step two: NULL all pointers to this block; do this second to avoid NULLing deleted pointers
4902 stb__nptr_block(address_being_freed, len, stb__nptr_delete_targets, 0);
4903 }
4904
4905 void stb_nptr_free(void *address_being_freed, int len)
4906 {
4907 free(address_being_freed);
4908 stb_nptr_didfree(address_being_freed, len);
4909 }
4910
4911 static void stb__nptr_move_targets(stb__memory_leaf *f, int offset, void *start, void *end)
4912 {
4913 stb__nptr_target **t = &f->targets;
4914 while (*t) {
4915 stb__nptr_target *n = *t;
4916 if (n->ptr >= start && n->ptr <= end) {
4917 stb__nptr *z;
4918 stb__memory_leaf *f;
4919 // unlink n
4920 *t = n->next_in_block;
4921 // update n to new address
4922 n->ptr = (void *) ((char *) n->ptr + offset);
4923 f = stb__nptr_find_leaf(n->ptr);
4924 if (!f) f = stb__nptr_make_leaf(n->ptr);
4925 n->next_in_block = f->targets;
4926 f->targets = n;
4927 // now go through all pointers and make them point here
4928 z = n->first;
4929 while (z) {
4930 *(void**) z->ptr = n->ptr;
4931 z = z->next;
4932 }
4933 } else
4934 t = &(n->next_in_block);
4935 }
4936 }
4937
4938 static void stb__nptr_move_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
4939 {
4940 stb__nptr **p = &f->pointers;
4941 while (*p) {
4942 stb__nptr *n = *p;
4943 if (n->ptr >= start && n->ptr <= end) {
4944 // unlink
4945 *p = n->next_in_block;
4946 n->ptr = (void *) ((int) n->ptr + offset);
4947 // move to new block
4948 f = stb__nptr_find_leaf(n->ptr);
4949 if (!f) f = stb__nptr_make_leaf(n->ptr);
4950 n->next_in_block = f->pointers;
4951 f->pointers = n;
4952 } else
4953 p = &(n->next_in_block);
4954 }
4955 }
4956
4957 void stb_nptr_realloc(void *new_address, void *old_address, int len)
4958 {
4959 if (new_address == old_address) return;
4960
4961 // have to move the pointers first, because moving the targets
4962 // requires writing to the pointers-to-the-targets, and if some of those moved too,
4963 // we need to make sure we don't write to the old memory
4964
4965 // step one: move all pointers within the block
4966 stb__nptr_block(old_address, len, stb__nptr_move_pointers, (char *) new_address - (char *) old_address);
4967 // step two: move all targets within the block
4968 stb__nptr_block(old_address, len, stb__nptr_move_targets, (char *) new_address - (char *) old_address);
4969 }
4970
4971 void stb_nptr_move(void *new_address, void *old_address)
4972 {
4973 stb_nptr_realloc(new_address, old_address, 1);
4974 }
4975
4976 void stb_nptr_recache(void)
4977 {
4978 int i,j;
4979 for (i=0; i < STB__NPTR_ROOT_NUM; ++i)
4980 if (stb__memtab_root[i])
4981 for (j=0; j < STB__NPTR_NODE_NUM; ++j)
4982 if (stb__memtab_root[i]->children[j]) {
4983 stb__nptr *p = stb__memtab_root[i]->children[j]->pointers;
4984 while (p) {
4985 stb_nptr_didset(p->ptr);
4986 p = p->next_in_block;
4987 }
4988 }
4989 }
4990
4991 #endif // STB_DEFINE
4992 #endif // STB_NPTR
4993
4994
4995 //////////////////////////////////////////////////////////////////////////////
4996 //
4997 // File Processing
4998 //
4999
5000
5001 #ifdef _MSC_VER
5002 #define stb_rename(x,y) _wrename((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
5003 #define stb_mktemp _mktemp
5004 #else
5005 #define stb_mktemp mktemp
5006 #define stb_rename rename
5007 #endif
5008
5009 STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
5010 STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
5011 STB_EXTERN int stb_size_varlen64(stb_uint64 v);
5012
5013
5014 #define stb_filec (char *) stb_file
5015 #define stb_fileu (unsigned char *) stb_file
5016 STB_EXTERN void * stb_file(char *filename, size_t *length);
5017 STB_EXTERN void * stb_file_max(char *filename, size_t *length);
5018 STB_EXTERN size_t stb_filelen(FILE *f);
5019 STB_EXTERN int stb_filewrite(char *filename, void *data, size_t length);
5020 STB_EXTERN int stb_filewritestr(char *filename, char *data);
5021 STB_EXTERN char ** stb_stringfile(char *filename, int *len);
5022 STB_EXTERN char ** stb_stringfile_trimmed(char *name, int *len, char comm);
5023 STB_EXTERN char * stb_fgets(char *buffer, int buflen, FILE *f);
5024 STB_EXTERN char * stb_fgets_malloc(FILE *f);
5025 STB_EXTERN int stb_fexists(char *filename);
5026 STB_EXTERN int stb_fcmp(char *s1, char *s2);
5027 STB_EXTERN int stb_feq(char *s1, char *s2);
5028 STB_EXTERN time_t stb_ftimestamp(char *filename);
5029
5030 STB_EXTERN int stb_fullpath(char *abs, int abs_size, char *rel);
5031 STB_EXTERN FILE * stb_fopen(char *filename, char *mode);
5032 STB_EXTERN int stb_fclose(FILE *f, int keep);
5033
5034 enum
5035 {
5036 stb_keep_no = 0,
5037 stb_keep_yes = 1,
5038 stb_keep_if_different = 2,
5039 };
5040
5041 STB_EXTERN int stb_copyfile(char *src, char *dest);
5042
5043 STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
5044 STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
5045 STB_EXTERN int stb_size_varlen64(stb_uint64 v);
5046
5047 STB_EXTERN void stb_fwrite32(FILE *f, stb_uint32 datum);
5048 STB_EXTERN void stb_fput_varlen (FILE *f, int v);
5049 STB_EXTERN void stb_fput_varlenu(FILE *f, unsigned int v);
5050 STB_EXTERN int stb_fget_varlen (FILE *f);
5051 STB_EXTERN stb_uint stb_fget_varlenu(FILE *f);
5052 STB_EXTERN void stb_fput_ranged (FILE *f, int v, int b, stb_uint n);
5053 STB_EXTERN int stb_fget_ranged (FILE *f, int b, stb_uint n);
5054 STB_EXTERN int stb_size_varlen (int v);
5055 STB_EXTERN int stb_size_varlenu(unsigned int v);
5056 STB_EXTERN int stb_size_ranged (int b, stb_uint n);
5057
5058 STB_EXTERN int stb_fread(void *data, size_t len, size_t count, void *f);
5059 STB_EXTERN int stb_fwrite(void *data, size_t len, size_t count, void *f);
5060
5061 #if 0
5062 typedef struct
5063 {
5064 FILE *base_file;
5065 char *buffer;
5066 int buffer_size;
5067 int buffer_off;
5068 int buffer_left;
5069 } STBF;
5070
5071 STB_EXTERN STBF *stb_tfopen(char *filename, char *mode);
5072 STB_EXTERN int stb_tfread(void *data, size_t len, size_t count, STBF *f);
5073 STB_EXTERN int stb_tfwrite(void *data, size_t len, size_t count, STBF *f);
5074 #endif
5075
5076 #ifdef STB_DEFINE
5077
5078 #if 0
5079 STBF *stb_tfopen(char *filename, char *mode)
5080 {
5081 STBF *z;
5082 FILE *f = fopen(filename, mode);
5083 if (!f) return NULL;
5084 z = (STBF *) malloc(sizeof(*z));
5085 if (!z) { fclose(f); return NULL; }
5086 z->base_file = f;
5087 if (!strcmp(mode, "rb") || !strcmp(mode, "wb")) {
5088 z->buffer_size = 4096;
5089 z->buffer_off = z->buffer_size;
5090 z->buffer_left = 0;
5091 z->buffer = malloc(z->buffer_size);
5092 if (!z->buffer) { free(z); fclose(f); return NULL; }
5093 } else {
5094 z->buffer = 0;
5095 z->buffer_size = 0;
5096 z->buffer_left = 0;
5097 }
5098 return z;
5099 }
5100
5101 int stb_tfread(void *data, size_t len, size_t count, STBF *f)
5102 {
5103 int total = len*count, done=0;
5104 if (!total) return 0;
5105 if (total <= z->buffer_left) {
5106 memcpy(data, z->buffer + z->buffer_off, total);
5107 z->buffer_off += total;
5108 z->buffer_left -= total;
5109 return count;
5110 } else {
5111 char *out = (char *) data;
5112
5113 // consume all buffered data
5114 memcpy(data, z->buffer + z->buffer_off, z->buffer_left);
5115 done = z->buffer_left;
5116 out += z->buffer_left;
5117 z->buffer_left=0;
5118
5119 if (total-done > (z->buffer_size >> 1)) {
5120 done += fread(out
5121 }
5122 }
5123 }
5124 #endif
5125
5126 void stb_fwrite32(FILE *f, stb_uint32 x)
5127 {
5128 fwrite(&x, 4, 1, f);
5129 }
5130
5131 #if defined(_MSC_VER) || defined(__MINGW32__)
5132 #define stb__stat _stat
5133 #else
5134 #define stb__stat stat
5135 #endif
5136
5137 int stb_fexists(char *filename)
5138 {
5139 struct stb__stat buf;
5140 return stb__windows(
5141 _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
5142 stat(filename,&buf)
5143 ) == 0;
5144 }
5145
5146 time_t stb_ftimestamp(char *filename)
5147 {
5148 struct stb__stat buf;
5149 if (stb__windows(
5150 _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
5151 stat(filename,&buf)
5152 ) == 0)
5153 {
5154 return buf.st_mtime;
5155 } else {
5156 return 0;
5157 }
5158 }
5159
5160 size_t stb_filelen(FILE *f)
5161 {
5162 size_t len, pos;
5163 pos = ftell(f);
5164 fseek(f, 0, SEEK_END);
5165 len = ftell(f);
5166 fseek(f, pos, SEEK_SET);
5167 return len;
5168 }
5169
5170 void *stb_file(char *filename, size_t *length)
5171 {
5172 FILE *f = stb__fopen(filename, "rb");
5173 char *buffer;
5174 size_t len, len2;
5175 if (!f) return NULL;
5176 len = stb_filelen(f);
5177 buffer = (char *) malloc(len+2); // nul + extra
5178 len2 = fread(buffer, 1, len, f);
5179 if (len2 == len) {
5180 if (length) *length = len;
5181 buffer[len] = 0;
5182 } else {
5183 free(buffer);
5184 buffer = NULL;
5185 }
5186 fclose(f);
5187 return buffer;
5188 }
5189
5190 int stb_filewrite(char *filename, void *data, size_t length)
5191 {
5192 FILE *f = stb_fopen(filename, "wb");
5193 if (f) {
5194 unsigned char *data_ptr = (unsigned char *) data;
5195 size_t remaining = length;
5196 while (remaining > 0) {
5197 size_t len2 = remaining > 65536 ? 65536 : remaining;
5198 size_t len3 = fwrite(data_ptr, 1, len2, f);
5199 if (len2 != len3) {
5200 fprintf(stderr, "Failed while writing %s\n", filename);
5201 break;
5202 }
5203 remaining -= len2;
5204 data_ptr += len2;
5205 }
5206 stb_fclose(f, stb_keep_if_different);
5207 }
5208 return f != NULL;
5209 }
5210
5211 int stb_filewritestr(char *filename, char *data)
5212 {
5213 return stb_filewrite(filename, data, strlen(data));
5214 }
5215
5216 void * stb_file_max(char *filename, size_t *length)
5217 {
5218 FILE *f = stb__fopen(filename, "rb");
5219 char *buffer;
5220 size_t len, maxlen;
5221 if (!f) return NULL;
5222 maxlen = *length;
5223 buffer = (char *) malloc(maxlen+1);
5224 len = fread(buffer, 1, maxlen, f);
5225 buffer[len] = 0;
5226 fclose(f);
5227 *length = len;
5228 return buffer;
5229 }
5230
5231 char ** stb_stringfile(char *filename, int *plen)
5232 {
5233 FILE *f = stb__fopen(filename, "rb");
5234 char *buffer, **list=NULL, *s;
5235 size_t len, count, i;
5236
5237 if (!f) return NULL;
5238 len = stb_filelen(f);
5239 buffer = (char *) malloc(len+1);
5240 len = fread(buffer, 1, len, f);
5241 buffer[len] = 0;
5242 fclose(f);
5243
5244 // two passes through: first time count lines, second time set them
5245 for (i=0; i < 2; ++i) {
5246 s = buffer;
5247 if (i == 1)
5248 list[0] = s;
5249 count = 1;
5250 while (*s) {
5251 if (*s == '\n' || *s == '\r') {
5252 // detect if both cr & lf are together
5253 int crlf = (s[0] + s[1]) == ('\n' + '\r');
5254 if (i == 1) *s = 0;
5255 if (crlf) ++s;
5256 if (s[1]) { // it's not over yet
5257 if (i == 1) list[count] = s+1;
5258 ++count;
5259 }
5260 }
5261 ++s;
5262 }
5263 if (i == 0) {
5264 list = (char **) malloc(sizeof(*list) * (count+1) + len+1);
5265 if (!list) return NULL;
5266 list[count] = 0;
5267 // recopy the file so there's just a single allocation to free
5268 memcpy(&list[count+1], buffer, len+1);
5269 free(buffer);
5270 buffer = (char *) &list[count+1];
5271 if (plen) *plen = count;
5272 }
5273 }
5274 return list;
5275 }
5276
5277 char ** stb_stringfile_trimmed(char *name, int *len, char comment)
5278 {
5279 int i,n,o=0;
5280 char **s = stb_stringfile(name, &n);
5281 if (s == NULL) return NULL;
5282 for (i=0; i < n; ++i) {
5283 char *p = stb_skipwhite(s[i]);
5284 if (*p && *p != comment)
5285 s[o++] = p;
5286 }
5287 s[o] = NULL;
5288 if (len) *len = o;
5289 return s;
5290 }
5291
5292 char * stb_fgets(char *buffer, int buflen, FILE *f)
5293 {
5294 char *p;
5295 buffer[0] = 0;
5296 p = fgets(buffer, buflen, f);
5297 if (p) {
5298 int n = strlen(p)-1;
5299 if (n >= 0)
5300 if (p[n] == '\n')
5301 p[n] = 0;
5302 }
5303 return p;
5304 }
5305
5306 char * stb_fgets_malloc(FILE *f)
5307 {
5308 // avoid reallocing for small strings
5309 char quick_buffer[800];
5310 quick_buffer[sizeof(quick_buffer)-2] = 0;
5311 if (!fgets(quick_buffer, sizeof(quick_buffer), f))
5312 return NULL;
5313
5314 if (quick_buffer[sizeof(quick_buffer)-2] == 0) {
5315 int n = strlen(quick_buffer);
5316 if (n > 0 && quick_buffer[n-1] == '\n')
5317 quick_buffer[n-1] = 0;
5318 return strdup(quick_buffer);
5319 } else {
5320 char *p;
5321 char *a = strdup(quick_buffer);
5322 int len = sizeof(quick_buffer)-1;
5323
5324 while (!feof(f)) {
5325 if (a[len-1] == '\n') break;
5326 a = (char *) realloc(a, len*2);
5327 p = &a[len];
5328 p[len-2] = 0;
5329 if (!fgets(p, len, f))
5330 break;
5331 if (p[len-2] == 0) {
5332 len += strlen(p);
5333 break;
5334 }
5335 len = len + (len-1);
5336 }
5337 if (a[len-1] == '\n')
5338 a[len-1] = 0;
5339 return a;
5340 }
5341 }
5342
5343 int stb_fullpath(char *abs, int abs_size, char *rel)
5344 {
5345 #ifdef _MSC_VER
5346 return _fullpath(abs, rel, abs_size) != NULL;
5347 #else
5348 if (rel[0] == '/' || rel[0] == '~') {
5349 if ((int) strlen(rel) >= abs_size)
5350 return 0;
5351 strcpy(abs,rel);
5352 return STB_TRUE;
5353 } else {
5354 int n;
5355 getcwd(abs, abs_size);
5356 n = strlen(abs);
5357 if (n+(int) strlen(rel)+2 <= abs_size) {
5358 abs[n] = '/';
5359 strcpy(abs+n+1, rel);
5360 return STB_TRUE;
5361 } else {
5362 return STB_FALSE;
5363 }
5364 }
5365 #endif
5366 }
5367
5368 static int stb_fcmp_core(FILE *f, FILE *g)
5369 {
5370 char buf1[1024],buf2[1024];
5371 int n1,n2, res=0;
5372
5373 while (1) {
5374 n1 = fread(buf1, 1, sizeof(buf1), f);
5375 n2 = fread(buf2, 1, sizeof(buf2), g);
5376 res = memcmp(buf1,buf2,stb_min(n1,n2));
5377 if (res)
5378 break;
5379 if (n1 != n2) {
5380 res = n1 < n2 ? -1 : 1;
5381 break;
5382 }
5383 if (n1 == 0)
5384 break;
5385 }
5386
5387 fclose(f);
5388 fclose(g);
5389 return res;
5390 }
5391
5392 int stb_fcmp(char *s1, char *s2)
5393 {
5394 FILE *f = stb__fopen(s1, "rb");
5395 FILE *g = stb__fopen(s2, "rb");
5396
5397 if (f == NULL || g == NULL) {
5398 if (f) fclose(f);
5399 if (g) {
5400 fclose(g);
5401 return STB_TRUE;
5402 }
5403 return f != NULL;
5404 }
5405
5406 return stb_fcmp_core(f,g);
5407 }
5408
5409 int stb_feq(char *s1, char *s2)
5410 {
5411 FILE *f = stb__fopen(s1, "rb");
5412 FILE *g = stb__fopen(s2, "rb");
5413
5414 if (f == NULL || g == NULL) {
5415 if (f) fclose(f);
5416 if (g) fclose(g);
5417 return f == g;
5418 }
5419
5420 // feq is faster because it shortcuts if they're different length
5421 if (stb_filelen(f) != stb_filelen(g)) {
5422 fclose(f);
5423 fclose(g);
5424 return 0;
5425 }
5426
5427 return !stb_fcmp_core(f,g);
5428 }
5429
5430 static stb_ptrmap *stb__files;
5431
5432 typedef struct
5433 {
5434 char *temp_name;
5435 char *name;
5436 int errors;
5437 } stb__file_data;
5438
5439 FILE * stb_fopen(char *filename, char *mode)
5440 {
5441 FILE *f;
5442 char name_full[4096];
5443 char temp_full[sizeof(name_full) + 12];
5444 int p;
5445 #ifdef _MSC_VER
5446 int j;
5447 #endif
5448 if (mode[0] != 'w' && !strchr(mode, '+'))
5449 return stb__fopen(filename, mode);
5450
5451 // save away the full path to the file so if the program
5452 // changes the cwd everything still works right! unix has
5453 // better ways to do this, but we have to work in windows
5454 name_full[0] = '\0'; // stb_fullpath reads name_full[0]
5455 if (stb_fullpath(name_full, sizeof(name_full), filename)==0)
5456 return 0;
5457
5458 // try to generate a temporary file in the same directory
5459 p = strlen(name_full)-1;
5460 while (p > 0 && name_full[p] != '/' && name_full[p] != '\\'
5461 && name_full[p] != ':' && name_full[p] != '~')
5462 --p;
5463 ++p;
5464
5465 memcpy(temp_full, name_full, p);
5466
5467 #ifdef _MSC_VER
5468 // try multiple times to make a temp file... just in
5469 // case some other process makes the name first
5470 for (j=0; j < 32; ++j) {
5471 strcpy(temp_full+p, "stmpXXXXXX");
5472 if (stb_mktemp(temp_full) == NULL)
5473 return 0;
5474
5475 f = fopen(temp_full, mode);
5476 if (f != NULL)
5477 break;
5478 }
5479 #else
5480 {
5481 strcpy(temp_full+p, "stmpXXXXXX");
5482 #ifdef __MINGW32__
5483 int fd = open(mktemp(temp_full), O_RDWR);
5484 #else
5485 int fd = mkstemp(temp_full);
5486 #endif
5487 if (fd == -1) return NULL;
5488 f = fdopen(fd, mode);
5489 if (f == NULL) {
5490 unlink(temp_full);
5491 close(fd);
5492 return NULL;
5493 }
5494 }
5495 #endif
5496 if (f != NULL) {
5497 stb__file_data *d = (stb__file_data *) malloc(sizeof(*d));
5498 if (!d) { assert(0); /* NOTREACHED */fclose(f); return NULL; }
5499 if (stb__files == NULL) stb__files = stb_ptrmap_create();
5500 d->temp_name = strdup(temp_full);
5501 d->name = strdup(name_full);
5502 d->errors = 0;
5503 stb_ptrmap_add(stb__files, f, d);
5504 return f;
5505 }
5506
5507 return NULL;
5508 }
5509
5510 int stb_fclose(FILE *f, int keep)
5511 {
5512 stb__file_data *d;
5513
5514 int ok = STB_FALSE;
5515 if (f == NULL) return 0;
5516
5517 if (ferror(f))
5518 keep = stb_keep_no;
5519
5520 fclose(f);
5521
5522 if (stb__files && stb_ptrmap_remove(stb__files, f, (void **) &d)) {
5523 if (stb__files->count == 0) {
5524 stb_ptrmap_destroy(stb__files);
5525 stb__files = NULL;
5526 }
5527 } else
5528 return STB_TRUE; // not special
5529
5530 if (keep == stb_keep_if_different) {
5531 // check if the files are identical
5532 if (stb_feq(d->name, d->temp_name)) {
5533 keep = stb_keep_no;
5534 ok = STB_TRUE; // report success if no change
5535 }
5536 }
5537
5538 if (keep != stb_keep_no) {
5539 if (stb_fexists(d->name) && remove(d->name)) {
5540 // failed to delete old, so don't keep new
5541 keep = stb_keep_no;
5542 } else {
5543 if (!stb_rename(d->temp_name, d->name))
5544 ok = STB_TRUE;
5545 else
5546 keep=stb_keep_no;
5547 }
5548 }
5549
5550 if (keep == stb_keep_no)
5551 remove(d->temp_name);
5552
5553 free(d->temp_name);
5554 free(d->name);
5555 free(d);
5556
5557 return ok;
5558 }
5559
5560 int stb_copyfile(char *src, char *dest)
5561 {
5562 char raw_buffer[1024];
5563 char *buffer;
5564 int buf_size = 65536;
5565
5566 FILE *f, *g;
5567
5568 // if file already exists at destination, do nothing
5569 if (stb_feq(src, dest)) return STB_TRUE;
5570
5571 // open file
5572 f = stb__fopen(src, "rb");
5573 if (f == NULL) return STB_FALSE;
5574
5575 // open file for writing
5576 g = stb__fopen(dest, "wb");
5577 if (g == NULL) {
5578 fclose(f);
5579 return STB_FALSE;
5580 }
5581
5582 buffer = (char *) malloc(buf_size);
5583 if (buffer == NULL) {
5584 buffer = raw_buffer;
5585 buf_size = sizeof(raw_buffer);
5586 }
5587
5588 while (!feof(f)) {
5589 int n = fread(buffer, 1, buf_size, f);
5590 if (n != 0)
5591 fwrite(buffer, 1, n, g);
5592 }
5593
5594 fclose(f);
5595 if (buffer != raw_buffer)
5596 free(buffer);
5597
5598 fclose(g);
5599 return STB_TRUE;
5600 }
5601
5602 // varlen:
5603 // v' = (v >> 31) + (v < 0 ? ~v : v)<<1; // small abs(v) => small v'
5604 // output v as big endian v'+k for v' <= k:
5605 // 1 byte : v' <= 0x00000080 ( -64 <= v < 64) 7 bits
5606 // 2 bytes: v' <= 0x00004000 (-8192 <= v < 8192) 14 bits
5607 // 3 bytes: v' <= 0x00200000 21 bits
5608 // 4 bytes: v' <= 0x10000000 28 bits
5609 // the number of most significant 1-bits in the first byte
5610 // equals the number of bytes after the first
5611
5612 #define stb__varlen_xform(v) (v<0 ? (~v << 1)+1 : (v << 1))
5613
5614 int stb_size_varlen(int v) { return stb_size_varlenu(stb__varlen_xform(v)); }
5615 int stb_size_varlenu(unsigned int v)
5616 {
5617 if (v < 0x00000080) return 1;
5618 if (v < 0x00004000) return 2;
5619 if (v < 0x00200000) return 3;
5620 if (v < 0x10000000) return 4;
5621 return 5;
5622 }
5623
5624 void stb_fput_varlen(FILE *f, int v) { stb_fput_varlenu(f, stb__varlen_xform(v)); }
5625
5626 void stb_fput_varlenu(FILE *f, unsigned int z)
5627 {
5628 if (z >= 0x10000000) fputc(0xF0,f);
5629 if (z >= 0x00200000) fputc((z < 0x10000000 ? 0xE0 : 0)+(z>>24),f);
5630 if (z >= 0x00004000) fputc((z < 0x00200000 ? 0xC0 : 0)+(z>>16),f);
5631 if (z >= 0x00000080) fputc((z < 0x00004000 ? 0x80 : 0)+(z>> 8),f);
5632 fputc(z,f);
5633 }
5634
5635 #define stb_fgetc(f) ((unsigned char) fgetc(f))
5636
5637 int stb_fget_varlen(FILE *f)
5638 {
5639 unsigned int z = stb_fget_varlenu(f);
5640 return (z & 1) ? ~(z>>1) : (z>>1);
5641 }
5642
5643 unsigned int stb_fget_varlenu(FILE *f)
5644 {
5645 unsigned int z;
5646 unsigned char d;
5647 d = stb_fgetc(f);
5648
5649 if (d >= 0x80) {
5650 if (d >= 0xc0) {
5651 if (d >= 0xe0) {
5652 if (d == 0xf0) z = stb_fgetc(f) << 24;
5653 else z = (d - 0xe0) << 24;
5654 z += stb_fgetc(f) << 16;
5655 }
5656 else
5657 z = (d - 0xc0) << 16;
5658 z += stb_fgetc(f) << 8;
5659 } else
5660 z = (d - 0x80) << 8;
5661 z += stb_fgetc(f);
5662 } else
5663 z = d;
5664 return z;
5665 }
5666
5667 stb_uint64 stb_fget_varlen64(FILE *f)
5668 {
5669 stb_uint64 z;
5670 unsigned char d;
5671 d = stb_fgetc(f);
5672
5673 if (d >= 0x80) {
5674 if (d >= 0xc0) {
5675 if (d >= 0xe0) {
5676 if (d >= 0xf0) {
5677 if (d >= 0xf8) {
5678 if (d >= 0xfc) {
5679 if (d >= 0xfe) {
5680 if (d >= 0xff)
5681 z = (stb_uint64) stb_fgetc(f) << 56;
5682 else
5683 z = (stb_uint64) (d - 0xfe) << 56;
5684 z |= (stb_uint64) stb_fgetc(f) << 48;
5685 } else z = (stb_uint64) (d - 0xfc) << 48;
5686 z |= (stb_uint64) stb_fgetc(f) << 40;
5687 } else z = (stb_uint64) (d - 0xf8) << 40;
5688 z |= (stb_uint64) stb_fgetc(f) << 32;
5689 } else z = (stb_uint64) (d - 0xf0) << 32;
5690 z |= (stb_uint) stb_fgetc(f) << 24;
5691 } else z = (stb_uint) (d - 0xe0) << 24;
5692 z |= (stb_uint) stb_fgetc(f) << 16;
5693 } else z = (stb_uint) (d - 0xc0) << 16;
5694 z |= (stb_uint) stb_fgetc(f) << 8;
5695 } else z = (stb_uint) (d - 0x80) << 8;
5696 z |= stb_fgetc(f);
5697 } else
5698 z = d;
5699
5700 return (z & 1) ? ~(z >> 1) : (z >> 1);
5701 }
5702
5703 int stb_size_varlen64(stb_uint64 v)
5704 {
5705 if (v < 0x00000080) return 1;
5706 if (v < 0x00004000) return 2;
5707 if (v < 0x00200000) return 3;
5708 if (v < 0x10000000) return 4;
5709 if (v < STB_IMM_UINT64(0x0000000800000000)) return 5;
5710 if (v < STB_IMM_UINT64(0x0000040000000000)) return 6;
5711 if (v < STB_IMM_UINT64(0x0002000000000000)) return 7;
5712 if (v < STB_IMM_UINT64(0x0100000000000000)) return 8;
5713 return 9;
5714 }
5715
5716 void stb_fput_varlen64(FILE *f, stb_uint64 v)
5717 {
5718 stb_uint64 z = stb__varlen_xform(v);
5719 int first=1;
5720 if (z >= STB_IMM_UINT64(0x100000000000000)) {
5721 fputc(0xff,f);
5722 first=0;
5723 }
5724 if (z >= STB_IMM_UINT64(0x02000000000000)) fputc((first ? 0xFE : 0)+(char)(z>>56),f), first=0;
5725 if (z >= STB_IMM_UINT64(0x00040000000000)) fputc((first ? 0xFC : 0)+(char)(z>>48),f), first=0;
5726 if (z >= STB_IMM_UINT64(0x00000800000000)) fputc((first ? 0xF8 : 0)+(char)(z>>40),f), first=0;
5727 if (z >= STB_IMM_UINT64(0x00000010000000)) fputc((first ? 0xF0 : 0)+(char)(z>>32),f), first=0;
5728 if (z >= STB_IMM_UINT64(0x00000000200000)) fputc((first ? 0xE0 : 0)+(char)(z>>24),f), first=0;
5729 if (z >= STB_IMM_UINT64(0x00000000004000)) fputc((first ? 0xC0 : 0)+(char)(z>>16),f), first=0;
5730 if (z >= STB_IMM_UINT64(0x00000000000080)) fputc((first ? 0x80 : 0)+(char)(z>> 8),f), first=0;
5731 fputc((char)z,f);
5732 }
5733
5734 void stb_fput_ranged(FILE *f, int v, int b, stb_uint n)
5735 {
5736 v -= b;
5737 if (n <= (1 << 31))
5738 assert((stb_uint) v < n);
5739 if (n > (1 << 24)) fputc(v >> 24, f);
5740 if (n > (1 << 16)) fputc(v >> 16, f);
5741 if (n > (1 << 8)) fputc(v >> 8, f);
5742 fputc(v,f);
5743 }
5744
5745 int stb_fget_ranged(FILE *f, int b, stb_uint n)
5746 {
5747 unsigned int v=0;
5748 if (n > (1 << 24)) v += stb_fgetc(f) << 24;
5749 if (n > (1 << 16)) v += stb_fgetc(f) << 16;
5750 if (n > (1 << 8)) v += stb_fgetc(f) << 8;
5751 v += stb_fgetc(f);
5752 return b+v;
5753 }
5754
5755 int stb_size_ranged(int b, stb_uint n)
5756 {
5757 if (n > (1 << 24)) return 4;
5758 if (n > (1 << 16)) return 3;
5759 if (n > (1 << 8)) return 2;
5760 return 1;
5761 }
5762
5763 void stb_fput_string(FILE *f, char *s)
5764 {
5765 int len = strlen(s);
5766 stb_fput_varlenu(f, len);
5767 fwrite(s, 1, len, f);
5768 }
5769
5770 // inverse of the above algorithm
5771 char *stb_fget_string(FILE *f, void *p)
5772 {
5773 char *s;
5774 int len = stb_fget_varlenu(f);
5775 if (len > 4096) return NULL;
5776 s = p ? stb_malloc_string(p, len+1) : (char *) malloc(len+1);
5777 fread(s, 1, len, f);
5778 s[len] = 0;
5779 return s;
5780 }
5781
5782 char *stb_strdup(char *str, void *pool)
5783 {
5784 int len = strlen(str);
5785 char *p = stb_malloc_string(pool, len+1);
5786 strcpy(p, str);
5787 return p;
5788 }
5789
5790 // strip the trailing '/' or '\\' from a directory so we can refer to it
5791 // as a file for _stat()
5792 char *stb_strip_final_slash(char *t)
5793 {
5794 if (t[0]) {
5795 char *z = t + strlen(t) - 1;
5796 // *z is the last character
5797 if (*z == '\\' || *z == '/')
5798 if (z != t+2 || t[1] != ':') // but don't strip it if it's e.g. "c:/"
5799 *z = 0;
5800 if (*z == '\\')
5801 *z = '/'; // canonicalize to make sure it matches db
5802 }
5803 return t;
5804 }
5805
5806 char *stb_strip_final_slash_regardless(char *t)
5807 {
5808 if (t[0]) {
5809 char *z = t + strlen(t) - 1;
5810 // *z is the last character
5811 if (*z == '\\' || *z == '/')
5812 *z = 0;
5813 if (*z == '\\')
5814 *z = '/'; // canonicalize to make sure it matches db
5815 }
5816 return t;
5817 }
5818 #endif
5819
5820 //////////////////////////////////////////////////////////////////////////////
5821 //
5822 // Options parsing
5823 //
5824
5825 STB_EXTERN char **stb_getopt_param(int *argc, char **argv, char *param);
5826 STB_EXTERN char **stb_getopt(int *argc, char **argv);
5827 STB_EXTERN void stb_getopt_free(char **opts);
5828
5829 #ifdef STB_DEFINE
5830
5831 void stb_getopt_free(char **opts)
5832 {
5833 int i;
5834 char ** o2 = opts;
5835 for (i=0; i < stb_arr_len(o2); ++i)
5836 free(o2[i]);
5837 stb_arr_free(o2);
5838 }
5839
5840 char **stb_getopt(int *argc, char **argv)
5841 {
5842 return stb_getopt_param(argc, argv, "");
5843 }
5844
5845 char **stb_getopt_param(int *argc, char **argv, char *param)
5846 {
5847 char ** opts=NULL;
5848 int i,j=1;
5849 for (i=1; i < *argc; ++i) {
5850 if (argv[i][0] != '-') {
5851 argv[j++] = argv[i];
5852 } else {
5853 if (argv[i][1] == 0) { // plain - == don't parse further options
5854 ++i;
5855 while (i < *argc)
5856 argv[j++] = argv[i++];
5857 break;
5858 } else {
5859 int k;
5860 char *q = argv[i]; // traverse options list
5861 for (k=1; q[k]; ++k) {
5862 char *s;
5863 if (strchr(param, q[k])) { // does it take a parameter?
5864 char *t = &q[k+1], z = q[k];
5865 int len=0;
5866 if (*t == 0) {
5867 if (i == *argc-1) { // takes a parameter, but none found
5868 *argc = 0;
5869 stb_getopt_free(opts);
5870 return NULL;
5871 }
5872 t = argv[++i];
5873 } else
5874 k += strlen(t);
5875 len = strlen(t);
5876 s = (char *) malloc(len+2);
5877 if (!s) return NULL;
5878 s[0] = z;
5879 strcpy(s+1, t);
5880 } else {
5881 // no parameter
5882 s = (char *) malloc(2);
5883 if (!s) return NULL;
5884 s[0] = q[k];
5885 s[1] = 0;
5886 }
5887 stb_arr_push(opts, s);
5888 }
5889 }
5890 }
5891 }
5892 stb_arr_push(opts, NULL);
5893 *argc = j;
5894 return opts;
5895 }
5896 #endif
5897
5898
5899 //////////////////////////////////////////////////////////////////////////////
5900 //
5901 // Portable directory reading
5902 //
5903
5904 STB_EXTERN char **stb_readdir_files (char *dir);
5905 STB_EXTERN char **stb_readdir_files_mask(char *dir, char *wild);
5906 STB_EXTERN char **stb_readdir_subdirs(char *dir);
5907 STB_EXTERN char **stb_readdir_subdirs_mask(char *dir, char *wild);
5908 STB_EXTERN void stb_readdir_free (char **files);
5909 STB_EXTERN char **stb_readdir_recursive(char *dir, char *filespec);
5910 STB_EXTERN void stb_delete_directory_recursive(char *dir);
5911
5912 #ifdef STB_DEFINE
5913
5914 #ifdef _MSC_VER
5915 #include <io.h>
5916 #else
5917 #include <unistd.h>
5918 #include <dirent.h>
5919 #endif
5920
5921 void stb_readdir_free(char **files)
5922 {
5923 char **f2 = files;
5924 int i;
5925 for (i=0; i < stb_arr_len(f2); ++i)
5926 free(f2[i]);
5927 stb_arr_free(f2);
5928 }
5929
5930 static int isdotdirname(char *name)
5931 {
5932 if (name[0] == '.')
5933 return (name[1] == '.') ? !name[2] : !name[1];
5934 return 0;
5935 }
5936
5937 STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
5938 static char **readdir_raw(char *dir, int return_subdirs, char *mask)
5939 {
5940 char **results = NULL;
5941 char buffer[4096], with_slash[4096];
5942 size_t n;
5943
5944 #ifdef _MSC_VER
5945 stb__wchar *ws;
5946 struct _wfinddata_t data;
5947 #ifdef _WIN64
5948 const intptr_t none = -1;
5949 intptr_t z;
5950 #else
5951 const long none = -1;
5952 long z;
5953 #endif
5954 #else // !_MSC_VER
5955 const DIR *none = NULL;
5956 DIR *z;
5957 #endif
5958
5959 n = stb_strscpy(buffer,dir,sizeof(buffer));
5960 if (!n || n >= sizeof(buffer))
5961 return NULL;
5962 stb_fixpath(buffer);
5963 n--;
5964
5965 if (n > 0 && (buffer[n-1] != '/')) {
5966 buffer[n++] = '/';
5967 }
5968 buffer[n] = 0;
5969 if (!stb_strscpy(with_slash,buffer,sizeof(with_slash)))
5970 return NULL;
5971
5972 #ifdef _MSC_VER
5973 if (!stb_strscpy(buffer+n,"*.*",sizeof(buffer)-n))
5974 return NULL;
5975 ws = stb__from_utf8(buffer);
5976 z = _wfindfirst((const wchar_t *)ws, &data);
5977 #else
5978 z = opendir(dir);
5979 #endif
5980
5981 if (z != none) {
5982 int nonempty = STB_TRUE;
5983 #ifndef _MSC_VER
5984 struct dirent *data = readdir(z);
5985 nonempty = (data != NULL);
5986 #endif
5987
5988 if (nonempty) {
5989
5990 do {
5991 int is_subdir;
5992 #ifdef _MSC_VER
5993 char *name = stb__to_utf8((stb__wchar *)data.name);
5994 if (name == NULL) {
5995 fprintf(stderr, "%s to convert '%S' to %s!\n", "Unable", data.name, "utf8");
5996 continue;
5997 }
5998 is_subdir = !!(data.attrib & _A_SUBDIR);
5999 #else
6000 char *name = data->d_name;
6001 if (!stb_strscpy(buffer+n,name,sizeof(buffer)-n))
6002 break;
6003 // Could follow DT_LNK, but would need to check for recursive links.
6004 is_subdir = !!(data->d_type & DT_DIR);
6005 #endif
6006
6007 if (is_subdir == return_subdirs) {
6008 if (!is_subdir || !isdotdirname(name)) {
6009 if (!mask || stb_wildmatchi(mask, name)) {
6010 char buffer[4096],*p=buffer;
6011 if ( stb_snprintf(buffer, sizeof(buffer), "%s%s", with_slash, name) < 0 )
6012 break;
6013 if (buffer[0] == '.' && buffer[1] == '/')
6014 p = buffer+2;
6015 stb_arr_push(results, strdup(p));
6016 }
6017 }
6018 }
6019 }
6020 #ifdef _MSC_VER
6021 while (0 == _wfindnext(z, &data));
6022 #else
6023 while ((data = readdir(z)) != NULL);
6024 #endif
6025 }
6026 #ifdef _MSC_VER
6027 _findclose(z);
6028 #else
6029 closedir(z);
6030 #endif
6031 }
6032 return results;
6033 }
6034
6035 char **stb_readdir_files (char *dir) { return readdir_raw(dir, 0, NULL); }
6036 char **stb_readdir_subdirs(char *dir) { return readdir_raw(dir, 1, NULL); }
6037 char **stb_readdir_files_mask(char *dir, char *wild) { return readdir_raw(dir, 0, wild); }
6038 char **stb_readdir_subdirs_mask(char *dir, char *wild) { return readdir_raw(dir, 1, wild); }
6039
6040 int stb__rec_max=0x7fffffff;
6041 static char **stb_readdir_rec(char **sofar, char *dir, char *filespec)
6042 {
6043 char **files;
6044 char ** dirs;
6045 char **p;
6046
6047 if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
6048
6049 files = stb_readdir_files_mask(dir, filespec);
6050 stb_arr_for(p, files) {
6051 stb_arr_push(sofar, strdup(*p));
6052 if (stb_arr_len(sofar) >= stb__rec_max) break;
6053 }
6054 stb_readdir_free(files);
6055 if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
6056
6057 dirs = stb_readdir_subdirs(dir);
6058 stb_arr_for(p, dirs)
6059 sofar = stb_readdir_rec(sofar, *p, filespec);
6060 stb_readdir_free(dirs);
6061 return sofar;
6062 }
6063
6064 char **stb_readdir_recursive(char *dir, char *filespec)
6065 {
6066 return stb_readdir_rec(NULL, dir, filespec);
6067 }
6068
6069 void stb_delete_directory_recursive(char *dir)
6070 {
6071 char **list = stb_readdir_subdirs(dir);
6072 int i;
6073 for (i=0; i < stb_arr_len(list); ++i)
6074 stb_delete_directory_recursive(list[i]);
6075 stb_arr_free(list);
6076 list = stb_readdir_files(dir);
6077 for (i=0; i < stb_arr_len(list); ++i)
6078 if (!remove(list[i])) {
6079 // on windows, try again after making it writeable; don't ALWAYS
6080 // do this first since that would be slow in the normal case
6081 #ifdef _MSC_VER
6082 _chmod(list[i], _S_IWRITE);
6083 remove(list[i]);
6084 #endif
6085 }
6086 stb_arr_free(list);
6087 stb__windows(_rmdir,rmdir)(dir);
6088 }
6089
6090 #endif
6091
6092 //////////////////////////////////////////////////////////////////////////////
6093 //
6094 // construct trees from filenames; useful for cmirror summaries
6095
6096 typedef struct stb_dirtree2 stb_dirtree2;
6097
6098 struct stb_dirtree2
6099 {
6100 stb_dirtree2 **subdirs;
6101
6102 // make convenient for stb_summarize_tree
6103 int num_subdir;
6104 float weight;
6105
6106 // actual data
6107 char *fullpath;
6108 char *relpath;
6109 char **files;
6110 };
6111
6112 STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count);
6113 STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count);
6114 STB_EXTERN int stb_dir_is_prefix(char *dir, int dirlen, char *file);
6115
6116 #ifdef STB_DEFINE
6117
6118 int stb_dir_is_prefix(char *dir, int dirlen, char *file)
6119 {
6120 if (dirlen == 0) return STB_TRUE;
6121 if (stb_strnicmp(dir, file, dirlen)) return STB_FALSE;
6122 if (file[dirlen] == '/' || file[dirlen] == '\\') return STB_TRUE;
6123 return STB_FALSE;
6124 }
6125
6126 stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count)
6127 {
6128 char buffer1[1024];
6129 int i;
6130 int dlen = strlen(src), elen;
6131 stb_dirtree2 *d;
6132 char ** descendents = NULL;
6133 char ** files = NULL;
6134 char *s;
6135 if (!count) return NULL;
6136 // first find all the ones that belong here... note this is will take O(NM) with N files and M subdirs
6137 for (i=0; i < count; ++i) {
6138 if (stb_dir_is_prefix(src, dlen, filelist[i])) {
6139 stb_arr_push(descendents, filelist[i]);
6140 }
6141 }
6142 if (descendents == NULL)
6143 return NULL;
6144 elen = dlen;
6145 // skip a leading slash
6146 if (elen == 0 && (descendents[0][0] == '/' || descendents[0][0] == '\\'))
6147 ++elen;
6148 else if (elen)
6149 ++elen;
6150 // now extract all the ones that have their root here
6151 for (i=0; i < stb_arr_len(descendents);) {
6152 if (!stb_strchr2(descendents[i]+elen, '/', '\\')) {
6153 stb_arr_push(files, descendents[i]);
6154 descendents[i] = descendents[stb_arr_len(descendents)-1];
6155 stb_arr_pop(descendents);
6156 } else
6157 ++i;
6158 }
6159 // now create a record
6160 d = (stb_dirtree2 *) malloc(sizeof(*d));
6161 d->files = files;
6162 d->subdirs = NULL;
6163 d->fullpath = strdup(src);
6164 s = stb_strrchr2(d->fullpath, '/', '\\');
6165 if (s)
6166 ++s;
6167 else
6168 s = d->fullpath;
6169 d->relpath = s;
6170 // now create the children
6171 qsort(descendents, stb_arr_len(descendents), sizeof(char *), stb_qsort_stricmp(0));
6172 buffer1[0] = 0;
6173 for (i=0; i < stb_arr_len(descendents); ++i) {
6174 char buffer2[1024];
6175 char *s = descendents[i] + elen, *t;
6176 t = stb_strchr2(s, '/', '\\');
6177 assert(t);
6178 stb_strncpy(buffer2, descendents[i], t-descendents[i]+1);
6179 if (stb_stricmp(buffer1, buffer2)) {
6180 stb_dirtree2 *t = stb_dirtree2_from_files_relative(buffer2, descendents, stb_arr_len(descendents));
6181 assert(t != NULL);
6182 strcpy(buffer1, buffer2);
6183 stb_arr_push(d->subdirs, t);
6184 }
6185 }
6186 d->num_subdir = stb_arr_len(d->subdirs);
6187 d->weight = 0;
6188 return d;
6189 }
6190
6191 stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count)
6192 {
6193 return stb_dirtree2_from_files_relative("", filelist, count);
6194 }
6195 #endif
6196
6197 //////////////////////////////////////////////////////////////////////////////
6198 //
6199 // Checksums: CRC-32, ADLER32, SHA-1
6200 //
6201 // CRC-32 and ADLER32 allow streaming blocks
6202 // SHA-1 requires either a complete buffer, max size 2^32 - 73
6203 // or it can checksum directly from a file, max 2^61
6204
6205 #define STB_ADLER32_SEED 1
6206 #define STB_CRC32_SEED 0 // note that we logical NOT this in the code
6207
6208 STB_EXTERN stb_uint
6209 stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen);
6210 STB_EXTERN stb_uint
6211 stb_crc32_block(stb_uint crc32, stb_uchar *buffer, stb_uint len);
6212 STB_EXTERN stb_uint stb_crc32(unsigned char *buffer, stb_uint len);
6213
6214 STB_EXTERN void stb_sha1(
6215 unsigned char output[20], unsigned char *buffer, unsigned int len);
6216 STB_EXTERN int stb_sha1_file(unsigned char output[20], char *file);
6217
6218 STB_EXTERN void stb_sha1_readable(char display[27], unsigned char sha[20]);
6219
6220 #ifdef STB_DEFINE
6221 stb_uint stb_crc32_block(stb_uint crc, unsigned char *buffer, stb_uint len)
6222 {
6223 static stb_uint crc_table[256];
6224 stb_uint i,j,s;
6225 crc = ~crc;
6226
6227 if (crc_table[1] == 0)
6228 for(i=0; i < 256; i++) {
6229 for (s=i, j=0; j < 8; ++j)
6230 s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0);
6231 crc_table[i] = s;
6232 }
6233 for (i=0; i < len; ++i)
6234 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
6235 return ~crc;
6236 }
6237
6238 stb_uint stb_crc32(unsigned char *buffer, stb_uint len)
6239 {
6240 return stb_crc32_block(0, buffer, len);
6241 }
6242
6243 stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
6244 {
6245 const unsigned long ADLER_MOD = 65521;
6246 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
6247 unsigned long blocklen, i;
6248
6249 blocklen = buflen % 5552;
6250 while (buflen) {
6251 for (i=0; i + 7 < blocklen; i += 8) {
6252 s1 += buffer[0], s2 += s1;
6253 s1 += buffer[1], s2 += s1;
6254 s1 += buffer[2], s2 += s1;
6255 s1 += buffer[3], s2 += s1;
6256 s1 += buffer[4], s2 += s1;
6257 s1 += buffer[5], s2 += s1;
6258 s1 += buffer[6], s2 += s1;
6259 s1 += buffer[7], s2 += s1;
6260
6261 buffer += 8;
6262 }
6263
6264 for (; i < blocklen; ++i)
6265 s1 += *buffer++, s2 += s1;
6266
6267 s1 %= ADLER_MOD, s2 %= ADLER_MOD;
6268 buflen -= blocklen;
6269 blocklen = 5552;
6270 }
6271 return (s2 << 16) + s1;
6272 }
6273
6274 static void stb__sha1(stb_uchar *chunk, stb_uint h[5])
6275 {
6276 int i;
6277 stb_uint a,b,c,d,e;
6278 stb_uint w[80];
6279
6280 for (i=0; i < 16; ++i)
6281 w[i] = stb_big32(&chunk[i*4]);
6282 for (i=16; i < 80; ++i) {
6283 stb_uint t;
6284 t = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
6285 w[i] = (t + t) | (t >> 31);
6286 }
6287
6288 a = h[0];
6289 b = h[1];
6290 c = h[2];
6291 d = h[3];
6292 e = h[4];
6293
6294 #define STB__SHA1(k,f) \
6295 { \
6296 stb_uint temp = (a << 5) + (a >> 27) + (f) + e + (k) + w[i]; \
6297 e = d; \
6298 d = c; \
6299 c = (b << 30) + (b >> 2); \
6300 b = a; \
6301 a = temp; \
6302 }
6303
6304 i=0;
6305 for (; i < 20; ++i) STB__SHA1(0x5a827999, d ^ (b & (c ^ d)) );
6306 for (; i < 40; ++i) STB__SHA1(0x6ed9eba1, b ^ c ^ d );
6307 for (; i < 60; ++i) STB__SHA1(0x8f1bbcdc, (b & c) + (d & (b ^ c)) );
6308 for (; i < 80; ++i) STB__SHA1(0xca62c1d6, b ^ c ^ d );
6309
6310 #undef STB__SHA1
6311
6312 h[0] += a;
6313 h[1] += b;
6314 h[2] += c;
6315 h[3] += d;
6316 h[4] += e;
6317 }
6318
6319 void stb_sha1(stb_uchar output[20], stb_uchar *buffer, stb_uint len)
6320 {
6321 unsigned char final_block[128];
6322 stb_uint end_start, final_len, j;
6323 int i;
6324
6325 stb_uint h[5];
6326
6327 h[0] = 0x67452301;
6328 h[1] = 0xefcdab89;
6329 h[2] = 0x98badcfe;
6330 h[3] = 0x10325476;
6331 h[4] = 0xc3d2e1f0;
6332
6333 // we need to write padding to the last one or two
6334 // blocks, so build those first into 'final_block'
6335
6336 // we have to write one special byte, plus the 8-byte length
6337
6338 // compute the block where the data runs out
6339 end_start = len & ~63;
6340
6341 // compute the earliest we can encode the length
6342 if (((len+9) & ~63) == end_start) {
6343 // it all fits in one block, so fill a second-to-last block
6344 end_start -= 64;
6345 }
6346
6347 final_len = end_start + 128;
6348
6349 // now we need to copy the data in
6350 assert(end_start + 128 >= len+9);
6351 assert(end_start < len || len < 64-9);
6352
6353 j = 0;
6354 if (end_start > len)
6355 j = (stb_uint) - (int) end_start;
6356
6357 for (; end_start + j < len; ++j)
6358 final_block[j] = buffer[end_start + j];
6359 final_block[j++] = 0x80;
6360 while (j < 128-5) // 5 byte length, so write 4 extra padding bytes
6361 final_block[j++] = 0;
6362 // big-endian size
6363 final_block[j++] = len >> 29;
6364 final_block[j++] = len >> 21;
6365 final_block[j++] = len >> 13;
6366 final_block[j++] = len >> 5;
6367 final_block[j++] = len << 3;
6368 assert(j == 128 && end_start + j == final_len);
6369
6370 for (j=0; j < final_len; j += 64) { // 512-bit chunks
6371 if (j+64 >= end_start+64)
6372 stb__sha1(&final_block[j - end_start], h);
6373 else
6374 stb__sha1(&buffer[j], h);
6375 }
6376
6377 for (i=0; i < 5; ++i) {
6378 output[i*4 + 0] = h[i] >> 24;
6379 output[i*4 + 1] = h[i] >> 16;
6380 output[i*4 + 2] = h[i] >> 8;
6381 output[i*4 + 3] = h[i] >> 0;
6382 }
6383 }
6384
6385 #ifdef _MSC_VER
6386 int stb_sha1_file(stb_uchar output[20], char *file)
6387 {
6388 int i;
6389 stb_uint64 length=0;
6390 unsigned char buffer[128];
6391
6392 FILE *f = stb__fopen(file, "rb");
6393 stb_uint h[5];
6394
6395 if (f == NULL) return 0; // file not found
6396
6397 h[0] = 0x67452301;
6398 h[1] = 0xefcdab89;
6399 h[2] = 0x98badcfe;
6400 h[3] = 0x10325476;
6401 h[4] = 0xc3d2e1f0;
6402
6403 for(;;) {
6404 int n = fread(buffer, 1, 64, f);
6405 if (n == 64) {
6406 stb__sha1(buffer, h);
6407 length += n;
6408 } else {
6409 int block = 64;
6410
6411 length += n;
6412
6413 buffer[n++] = 0x80;
6414
6415 // if there isn't enough room for the length, double the block
6416 if (n + 8 > 64)
6417 block = 128;
6418
6419 // pad to end
6420 memset(buffer+n, 0, block-8-n);
6421
6422 i = block - 8;
6423 buffer[i++] = (stb_uchar) (length >> 53);
6424 buffer[i++] = (stb_uchar) (length >> 45);
6425 buffer[i++] = (stb_uchar) (length >> 37);
6426 buffer[i++] = (stb_uchar) (length >> 29);
6427 buffer[i++] = (stb_uchar) (length >> 21);
6428 buffer[i++] = (stb_uchar) (length >> 13);
6429 buffer[i++] = (stb_uchar) (length >> 5);
6430 buffer[i++] = (stb_uchar) (length << 3);
6431 assert(i == block);
6432 stb__sha1(buffer, h);
6433 if (block == 128)
6434 stb__sha1(buffer+64, h);
6435 else
6436 assert(block == 64);
6437 break;
6438 }
6439 }
6440 fclose(f);
6441
6442 for (i=0; i < 5; ++i) {
6443 output[i*4 + 0] = h[i] >> 24;
6444 output[i*4 + 1] = h[i] >> 16;
6445 output[i*4 + 2] = h[i] >> 8;
6446 output[i*4 + 3] = h[i] >> 0;
6447 }
6448
6449 return 1;
6450 }
6451 #endif // _MSC_VER
6452
6453 // client can truncate this wherever they like
6454 void stb_sha1_readable(char display[27], unsigned char sha[20])
6455 {
6456 char encoding[65] = "0123456789abcdefghijklmnopqrstuv"
6457 "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%$";
6458 int num_bits = 0, acc=0;
6459 int i=0,o=0;
6460 while (o < 26) {
6461 int v;
6462 // expand the accumulator
6463 if (num_bits < 6) {
6464 assert(i != 20);
6465 acc += sha[i++] << num_bits;
6466 num_bits += 8;
6467 }
6468 v = acc & ((1 << 6) - 1);
6469 display[o++] = encoding[v];
6470 acc >>= 6;
6471 num_bits -= 6;
6472 }
6473 assert(num_bits == 20*8 - 26*6);
6474 display[o++] = encoding[acc];
6475 }
6476
6477 #endif // STB_DEFINE
6478
6479 ///////////////////////////////////////////////////////////
6480 //
6481 // simplified WINDOWS registry interface... hopefully
6482 // we'll never actually use this?
6483
6484 #if defined(_WIN32)
6485
6486 STB_EXTERN void * stb_reg_open(char *mode, char *where); // mode: "rHKLM" or "rHKCU" or "w.."
6487 STB_EXTERN void stb_reg_close(void *reg);
6488 STB_EXTERN int stb_reg_read(void *zreg, char *str, void *data, unsigned long len);
6489 STB_EXTERN int stb_reg_read_string(void *zreg, char *str, char *data, int len);
6490 STB_EXTERN void stb_reg_write(void *zreg, char *str, void *data, unsigned long len);
6491 STB_EXTERN void stb_reg_write_string(void *zreg, char *str, char *data);
6492
6493 #if defined(STB_DEFINE) && !defined(STB_NO_REGISTRY)
6494
6495 #define STB_HAS_REGISTRY
6496
6497 #ifndef _WINDOWS_
6498
6499 #define HKEY void *
6500
6501 STB_EXTERN __declspec(dllimport) long __stdcall RegCloseKey ( HKEY hKey );
6502 STB_EXTERN __declspec(dllimport) long __stdcall RegCreateKeyExA ( HKEY hKey, const char * lpSubKey,
6503 int Reserved, char * lpClass, int dwOptions,
6504 int samDesired, void *lpSecurityAttributes, HKEY * phkResult, int * lpdwDisposition );
6505 STB_EXTERN __declspec(dllimport) long __stdcall RegDeleteKeyA ( HKEY hKey, const char * lpSubKey );
6506 STB_EXTERN __declspec(dllimport) long __stdcall RegQueryValueExA ( HKEY hKey, const char * lpValueName,
6507 int * lpReserved, unsigned long * lpType, unsigned char * lpData, unsigned long * lpcbData );
6508 STB_EXTERN __declspec(dllimport) long __stdcall RegSetValueExA ( HKEY hKey, const char * lpValueName,
6509 int Reserved, int dwType, const unsigned char* lpData, int cbData );
6510 STB_EXTERN __declspec(dllimport) long __stdcall RegOpenKeyExA ( HKEY hKey, const char * lpSubKey,
6511 int ulOptions, int samDesired, HKEY * phkResult );
6512
6513 #endif // _WINDOWS_
6514
6515 #define STB__REG_OPTION_NON_VOLATILE 0
6516 #define STB__REG_KEY_ALL_ACCESS 0x000f003f
6517 #define STB__REG_KEY_READ 0x00020019
6518
6519 void *stb_reg_open(char *mode, char *where)
6520 {
6521 long res;
6522 HKEY base;
6523 HKEY zreg;
6524 if (!stb_stricmp(mode+1, "cu") || !stb_stricmp(mode+1, "hkcu"))
6525 base = (HKEY) 0x80000001; // HKCU
6526 else if (!stb_stricmp(mode+1, "lm") || !stb_stricmp(mode+1, "hklm"))
6527 base = (HKEY) 0x80000002; // HKLM
6528 else
6529 return NULL;
6530
6531 if (mode[0] == 'r')
6532 res = RegOpenKeyExA(base, where, 0, STB__REG_KEY_READ, &zreg);
6533 else if (mode[0] == 'w')
6534 res = RegCreateKeyExA(base, where, 0, NULL, STB__REG_OPTION_NON_VOLATILE, STB__REG_KEY_ALL_ACCESS, NULL, &zreg, NULL);
6535 else
6536 return NULL;
6537
6538 return res ? NULL : zreg;
6539 }
6540
6541 void stb_reg_close(void *reg)
6542 {
6543 RegCloseKey((HKEY) reg);
6544 }
6545
6546 #define STB__REG_SZ 1
6547 #define STB__REG_BINARY 3
6548 #define STB__REG_DWORD 4
6549
6550 int stb_reg_read(void *zreg, char *str, void *data, unsigned long len)
6551 {
6552 unsigned long type;
6553 unsigned long alen = len;
6554 if (0 == RegQueryValueExA((HKEY) zreg, str, 0, &type, (unsigned char *) data, &len))
6555 if (type == STB__REG_BINARY || type == STB__REG_SZ || type == STB__REG_DWORD) {
6556 if (len < alen)
6557 *((char *) data + len) = 0;
6558 return 1;
6559 }
6560 return 0;
6561 }
6562
6563 void stb_reg_write(void *zreg, char *str, void *data, unsigned long len)
6564 {
6565 if (zreg)
6566 RegSetValueExA((HKEY) zreg, str, 0, STB__REG_BINARY, (const unsigned char *) data, len);
6567 }
6568
6569 int stb_reg_read_string(void *zreg, char *str, char *data, int len)
6570 {
6571 if (!stb_reg_read(zreg, str, data, len)) return 0;
6572 data[len-1] = 0; // force a 0 at the end of the string no matter what
6573 return 1;
6574 }
6575
6576 void stb_reg_write_string(void *zreg, char *str, char *data)
6577 {
6578 if (zreg)
6579 RegSetValueExA((HKEY) zreg, str, 0, STB__REG_SZ, (const unsigned char *) data, strlen(data)+1);
6580 }
6581 #endif // STB_DEFINE
6582 #endif // _WIN32
6583
6584
6585 //////////////////////////////////////////////////////////////////////////////
6586 //
6587 // stb_cfg - This is like the registry, but the config info
6588 // is all stored in plain old files where we can
6589 // backup and restore them easily. The LOCATION of
6590 // the config files is gotten from... the registry!
6591
6592 #ifndef STB_NO_STB_STRINGS
6593 typedef struct stb_cfg_st stb_cfg;
6594
6595 STB_EXTERN stb_cfg * stb_cfg_open(char *config, char *mode); // mode = "r", "w"
6596 STB_EXTERN void stb_cfg_close(stb_cfg *cfg);
6597 STB_EXTERN int stb_cfg_read(stb_cfg *cfg, char *key, void *value, int len);
6598 STB_EXTERN void stb_cfg_write(stb_cfg *cfg, char *key, void *value, int len);
6599 STB_EXTERN int stb_cfg_read_string(stb_cfg *cfg, char *key, char *value, int len);
6600 STB_EXTERN void stb_cfg_write_string(stb_cfg *cfg, char *key, char *value);
6601 STB_EXTERN int stb_cfg_delete(stb_cfg *cfg, char *key);
6602 STB_EXTERN void stb_cfg_set_directory(char *dir);
6603
6604 #ifdef STB_DEFINE
6605
6606 typedef struct
6607 {
6608 char *key;
6609 void *value;
6610 int value_len;
6611 } stb__cfg_item;
6612
6613 struct stb_cfg_st
6614 {
6615 stb__cfg_item *data;
6616 char *loaded_file; // this needs to be freed
6617 FILE *f; // write the data to this file on close
6618 };
6619
6620 static char *stb__cfg_sig = "sTbCoNfIg!\0\0";
6621 static char stb__cfg_dir[512];
6622 STB_EXTERN void stb_cfg_set_directory(char *dir)
6623 {
6624 strcpy(stb__cfg_dir, dir);
6625 }
6626
6627 STB_EXTERN stb_cfg * stb_cfg_open(char *config, char *mode)
6628 {
6629 size_t len;
6630 stb_cfg *z;
6631 char file[512];
6632 if (mode[0] != 'r' && mode[0] != 'w') return NULL;
6633
6634 if (!stb__cfg_dir[0]) {
6635 #ifdef _WIN32
6636 strcpy(stb__cfg_dir, "c:/stb");
6637 #else
6638 strcpy(stb__cfg_dir, "~/.stbconfig");
6639 #endif
6640
6641 #ifdef STB_HAS_REGISTRY
6642 {
6643 void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
6644 if (reg) {
6645 stb_reg_read_string(reg, "config_dir", stb__cfg_dir, sizeof(stb__cfg_dir));
6646 stb_reg_close(reg);
6647 }
6648 }
6649 #endif
6650 }
6651
6652 sprintf(file, "%s/%s.cfg", stb__cfg_dir, config);
6653
6654 z = (stb_cfg *) stb_malloc(0, sizeof(*z));
6655 z->data = NULL;
6656
6657 z->loaded_file = stb_filec(file, &len);
6658 if (z->loaded_file) {
6659 char *s = z->loaded_file;
6660 if (!memcmp(s, stb__cfg_sig, 12)) {
6661 char *s = z->loaded_file + 12;
6662 while (s < z->loaded_file + len) {
6663 stb__cfg_item a;
6664 int n = *(stb_int16 *) s;
6665 a.key = s+2;
6666 s = s+2 + n;
6667 a.value_len = *(int *) s;
6668 s += 4;
6669 a.value = s;
6670 s += a.value_len;
6671 stb_arr_push(z->data, a);
6672 }
6673 assert(s == z->loaded_file + len);
6674 }
6675 }
6676
6677 if (mode[0] == 'w')
6678 z->f = fopen(file, "wb");
6679 else
6680 z->f = NULL;
6681
6682 return z;
6683 }
6684
6685 void stb_cfg_close(stb_cfg *z)
6686 {
6687 if (z->f) {
6688 int i;
6689 // write the file out
6690 fwrite(stb__cfg_sig, 12, 1, z->f);
6691 for (i=0; i < stb_arr_len(z->data); ++i) {
6692 stb_int16 n = strlen(z->data[i].key)+1;
6693 fwrite(&n, 2, 1, z->f);
6694 fwrite(z->data[i].key, n, 1, z->f);
6695 fwrite(&z->data[i].value_len, 4, 1, z->f);
6696 fwrite(z->data[i].value, z->data[i].value_len, 1, z->f);
6697 }
6698 fclose(z->f);
6699 }
6700 stb_arr_free(z->data);
6701 stb_free(z);
6702 }
6703
6704 int stb_cfg_read(stb_cfg *z, char *key, void *value, int len)
6705 {
6706 int i;
6707 for (i=0; i < stb_arr_len(z->data); ++i) {
6708 if (!stb_stricmp(z->data[i].key, key)) {
6709 int n = stb_min(len, z->data[i].value_len);
6710 memcpy(value, z->data[i].value, n);
6711 if (n < len)
6712 *((char *) value + n) = 0;
6713 return 1;
6714 }
6715 }
6716 return 0;
6717 }
6718
6719 void stb_cfg_write(stb_cfg *z, char *key, void *value, int len)
6720 {
6721 int i;
6722 for (i=0; i < stb_arr_len(z->data); ++i)
6723 if (!stb_stricmp(z->data[i].key, key))
6724 break;
6725 if (i == stb_arr_len(z->data)) {
6726 stb__cfg_item p;
6727 p.key = stb_strdup(key, z);
6728 p.value = NULL;
6729 p.value_len = 0;
6730 stb_arr_push(z->data, p);
6731 }
6732 z->data[i].value = stb_malloc(z, len);
6733 z->data[i].value_len = len;
6734 memcpy(z->data[i].value, value, len);
6735 }
6736
6737 int stb_cfg_delete(stb_cfg *z, char *key)
6738 {
6739 int i;
6740 for (i=0; i < stb_arr_len(z->data); ++i)
6741 if (!stb_stricmp(z->data[i].key, key)) {
6742 stb_arr_fastdelete(z->data, i);
6743 return 1;
6744 }
6745 return 0;
6746 }
6747
6748 int stb_cfg_read_string(stb_cfg *z, char *key, char *value, int len)
6749 {
6750 if (!stb_cfg_read(z, key, value, len)) return 0;
6751 value[len-1] = 0;
6752 return 1;
6753 }
6754
6755 void stb_cfg_write_string(stb_cfg *z, char *key, char *value)
6756 {
6757 stb_cfg_write(z, key, value, strlen(value)+1);
6758 }
6759 #endif
6760
6761 //////////////////////////////////////////////////////////////////////////////
6762 //
6763 // stb_dirtree - load a description of a directory tree
6764 // uses a cache and stat()s the directories for changes
6765 // MUCH faster on NTFS, _wrong_ on FAT32, so should
6766 // ignore the db on FAT32
6767
6768 #ifdef _WIN32
6769
6770 typedef struct
6771 {
6772 char * path; // full path from passed-in root
6773 time_t last_modified;
6774 int num_files;
6775 int flag;
6776 } stb_dirtree_dir;
6777
6778 typedef struct
6779 {
6780 char *name; // name relative to path
6781 int dir; // index into dirs[] array
6782 stb_int64 size; // size, max 4GB
6783 time_t last_modified;
6784 int flag;
6785 } stb_dirtree_file;
6786
6787 typedef struct
6788 {
6789 stb_dirtree_dir *dirs;
6790 stb_dirtree_file *files;
6791
6792 // internal use
6793 void * string_pool; // used to free data en masse
6794 } stb_dirtree;
6795
6796 extern void stb_dirtree_free ( stb_dirtree *d );
6797 extern stb_dirtree *stb_dirtree_get ( char *dir);
6798 extern stb_dirtree *stb_dirtree_get_dir ( char *dir, char *cache_dir);
6799 extern stb_dirtree *stb_dirtree_get_with_file ( char *dir, char *cache_file);
6800
6801 // get a list of all the files recursively underneath 'dir'
6802 //
6803 // cache_file is used to store a copy of the directory tree to speed up
6804 // later calls. It must be unique to 'dir' and the current working
6805 // directory! Otherwise who knows what will happen (a good solution
6806 // is to put it _in_ dir, but this API doesn't force that).
6807 //
6808 // Also, it might be possible to break this if you have two different processes
6809 // do a call to stb_dirtree_get() with the same cache file at about the same
6810 // time, but I _think_ it might just work.
6811
6812 // i needed to build an identical data structure representing the state of
6813 // a mirrored copy WITHOUT bothering to rescan it (i.e. we're mirroring to
6814 // it WITHOUT scanning it, e.g. it's over the net), so this requires access
6815 // to all of the innards.
6816 extern void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last);
6817 extern void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last);
6818 extern void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir);
6819 extern void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir);
6820
6821 #ifdef STB_DEFINE
6822 static void stb__dirtree_add_dir(char *path, time_t last, stb_dirtree *active)
6823 {
6824 stb_dirtree_dir d;
6825 d.last_modified = last;
6826 d.num_files = 0;
6827 d.path = stb_strdup(path, active->string_pool);
6828 stb_arr_push(active->dirs, d);
6829 }
6830
6831 static void stb__dirtree_add_file(char *name, int dir, stb_int64 size, time_t last, stb_dirtree *active)
6832 {
6833 stb_dirtree_file f;
6834 f.dir = dir;
6835 f.size = size;
6836 f.last_modified = last;
6837 f.name = stb_strdup(name, active->string_pool);
6838 ++active->dirs[dir].num_files;
6839 stb_arr_push(active->files, f);
6840 }
6841
6842 // version 02 supports > 4GB files
6843 static char stb__signature[12] = { 's', 'T', 'b', 'D', 'i', 'R', 't', 'R', 'e', 'E', '0', '2' };
6844
6845 static void stb__dirtree_save_db(char *filename, stb_dirtree *data, char *root)
6846 {
6847 int i, num_dirs_final=0, num_files_final;
6848 char *info = root ? root : "";
6849 int *remap;
6850 FILE *f = fopen(filename, "wb");
6851 if (!f) return;
6852
6853 fwrite(stb__signature, sizeof(stb__signature), 1, f);
6854 fwrite(info, strlen(info)+1, 1, f);
6855 // need to be slightly tricky and not write out NULLed directories, nor the root
6856
6857 // build remapping table of all dirs we'll be writing out
6858 remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(data->dirs));
6859 for (i=0; i < stb_arr_len(data->dirs); ++i) {
6860 if (data->dirs[i].path == NULL || (root && 0==stb_stricmp(data->dirs[i].path, root))) {
6861 remap[i] = -1;
6862 } else {
6863 remap[i] = num_dirs_final++;
6864 }
6865 }
6866
6867 fwrite(&num_dirs_final, 4, 1, f);
6868 for (i=0; i < stb_arr_len(data->dirs); ++i) {
6869 if (remap[i] >= 0) {
6870 fwrite(&data->dirs[i].last_modified, 4, 1, f);
6871 stb_fput_string(f, data->dirs[i].path);
6872 }
6873 }
6874
6875 num_files_final = 0;
6876 for (i=0; i < stb_arr_len(data->files); ++i)
6877 if (remap[data->files[i].dir] >= 0 && data->files[i].name)
6878 ++num_files_final;
6879
6880 fwrite(&num_files_final, 4, 1, f);
6881 for (i=0; i < stb_arr_len(data->files); ++i) {
6882 if (remap[data->files[i].dir] >= 0 && data->files[i].name) {
6883 stb_fput_ranged(f, remap[data->files[i].dir], 0, num_dirs_final);
6884 stb_fput_varlen64(f, data->files[i].size);
6885 fwrite(&data->files[i].last_modified, 4, 1, f);
6886 stb_fput_string(f, data->files[i].name);
6887 }
6888 }
6889
6890 fclose(f);
6891 }
6892
6893 // note: stomps any existing data, rather than appending
6894 static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir)
6895 {
6896 char sig[2048];
6897 int i,n;
6898 FILE *f = fopen(filename, "rb");
6899
6900 if (!f) return;
6901
6902 data->string_pool = stb_malloc(0,1);
6903
6904 fread(sig, sizeof(stb__signature), 1, f);
6905 if (memcmp(stb__signature, sig, sizeof(stb__signature))) { fclose(f); return; }
6906 if (!fread(sig, strlen(dir)+1, 1, f)) { fclose(f); return; }
6907 if (stb_stricmp(sig,dir)) { fclose(f); return; }
6908
6909 // we can just read them straight in, because they're guaranteed to be valid
6910 fread(&n, 4, 1, f);
6911 stb_arr_setlen(data->dirs, n);
6912 for(i=0; i < stb_arr_len(data->dirs); ++i) {
6913 fread(&data->dirs[i].last_modified, 4, 1, f);
6914 data->dirs[i].path = stb_fget_string(f, data->string_pool);
6915 if (data->dirs[i].path == NULL) goto bail;
6916 }
6917 fread(&n, 4, 1, f);
6918 stb_arr_setlen(data->files, n);
6919 for (i=0; i < stb_arr_len(data->files); ++i) {
6920 data->files[i].dir = stb_fget_ranged(f, 0, stb_arr_len(data->dirs));
6921 data->files[i].size = stb_fget_varlen64(f);
6922 fread(&data->files[i].last_modified, 4, 1, f);
6923 data->files[i].name = stb_fget_string(f, data->string_pool);
6924 if (data->files[i].name == NULL) goto bail;
6925 }
6926
6927 if (0) {
6928 bail:
6929 stb_arr_free(data->dirs);
6930 stb_arr_free(data->files);
6931 }
6932 fclose(f);
6933 }
6934
6935 static int stb__dircount, stb__dircount_mask, stb__showfile;
6936 static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active)
6937 {
6938 // this is dumb depth first; theoretically it might be faster
6939 // to fully traverse each directory before visiting its children,
6940 // but it's complicated and didn't seem like a gain in the test app
6941
6942 int n;
6943
6944 struct _wfinddatai64_t c_file;
6945 long hFile;
6946 stb__wchar full_path[1024];
6947 int has_slash;
6948 if (stb__showfile) printf("<");
6949
6950 has_slash = (path[0] && path[strlen(path)-1] == '/');
6951 if (has_slash)
6952 swprintf(full_path, L"%s*", stb__from_utf8(path));
6953 else
6954 swprintf(full_path, L"%s/*", stb__from_utf8(path));
6955
6956 // it's possible this directory is already present: that means it was in the
6957 // cache, but its parent wasn't... in that case, we're done with it
6958 if (stb__showfile) printf("C[%d]", stb_arr_len(active->dirs));
6959 for (n=0; n < stb_arr_len(active->dirs); ++n)
6960 if (0 == stb_stricmp(active->dirs[n].path, path)) {
6961 if (stb__showfile) printf("D");
6962 return;
6963 }
6964 if (stb__showfile) printf("E");
6965
6966 // otherwise, we need to add it
6967 stb__dirtree_add_dir(path, last_time, active);
6968 n = stb_arr_lastn(active->dirs);
6969
6970 if (stb__showfile) printf("[");
6971 if( (hFile = _wfindfirsti64( full_path, &c_file )) != -1L ) {
6972 do {
6973 if (stb__showfile) printf(")");
6974 if (c_file.attrib & _A_SUBDIR) {
6975 // ignore subdirectories starting with '.', e.g. "." and ".."
6976 if (c_file.name[0] != '.') {
6977 char *new_path = (char *) full_path;
6978 char *temp = stb__to_utf8(c_file.name);
6979
6980 if (has_slash)
6981 sprintf(new_path, "%s%s", path, temp);
6982 else
6983 sprintf(new_path, "%s/%s", path, temp);
6984
6985 if (stb__dircount_mask) {
6986 ++stb__dircount;
6987 if (!(stb__dircount & stb__dircount_mask)) {
6988 printf("%s\r", new_path);
6989 }
6990 }
6991
6992 stb__dirtree_scandir(new_path, c_file.time_write, active);
6993 }
6994 } else {
6995 char *temp = stb__to_utf8(c_file.name);
6996 stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active);
6997 }
6998 if (stb__showfile) printf("(");
6999 } while( _wfindnexti64( hFile, &c_file ) == 0 );
7000 if (stb__showfile) printf("]");
7001 _findclose( hFile );
7002 }
7003 if (stb__showfile) printf(">\n");
7004 }
7005
7006 // scan the database and see if it's all valid
7007 static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active)
7008 {
7009 int changes_detected = STB_FALSE;
7010 int i;
7011 int *remap;
7012 int *rescan=NULL;
7013 remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(db->dirs));
7014 memset(remap, 0, sizeof(remap[0]) * stb_arr_len(db->dirs));
7015 rescan = NULL;
7016
7017 for (i=0; i < stb_arr_len(db->dirs); ++i) {
7018 struct _stat info;
7019 if (stb__dircount_mask) {
7020 ++stb__dircount;
7021 if (!(stb__dircount & stb__dircount_mask)) {
7022 printf(".");
7023 }
7024 }
7025 if (0 == _stat(db->dirs[i].path, &info)) {
7026 if (info.st_mode & _S_IFDIR) {
7027 // it's still a directory, as expected
7028 int n = abs(info.st_mtime - db->dirs[i].last_modified);
7029 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
7030 // it's changed! force a rescan
7031 // we don't want to scan it until we've stat()d its
7032 // subdirs, though, so we queue it
7033 if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, db->dirs[i].last_modified, info.st_mtime);
7034 stb_arr_push(rescan, i);
7035 // update the last_mod time
7036 db->dirs[i].last_modified = info.st_mtime;
7037 // ignore existing files in this dir
7038 remap[i] = -1;
7039 changes_detected = STB_TRUE;
7040 } else {
7041 // it hasn't changed, just copy it through unchanged
7042 stb__dirtree_add_dir(db->dirs[i].path, db->dirs[i].last_modified, active);
7043 remap[i] = stb_arr_lastn(active->dirs);
7044 }
7045 } else {
7046 // this path used to refer to a directory, but now it's a file!
7047 // assume that the parent directory is going to be forced to rescan anyway
7048 goto delete_entry;
7049 }
7050 } else {
7051 delete_entry:
7052 // directory no longer exists, so don't copy it
7053 // we don't free it because it's in the string pool now
7054 db->dirs[i].path = NULL;
7055 remap[i] = -1;
7056 changes_detected = STB_TRUE;
7057 }
7058 }
7059
7060 // at this point, we have:
7061 //
7062 // <rescan> holds a list of directory indices that need to be scanned due to being out of date
7063 // <remap> holds the directory index in <active> for each dir in <db>, if it exists; -1 if not
7064 // directories in <rescan> are not in <active> yet
7065
7066 // so we can go ahead and remap all the known files right now
7067 for (i=0; i < stb_arr_len(db->files); ++i) {
7068 int dir = db->files[i].dir;
7069 if (remap[dir] >= 0) {
7070 stb__dirtree_add_file(db->files[i].name, remap[dir], db->files[i].size, db->files[i].last_modified, active);
7071 }
7072 }
7073
7074 // at this point we're done with db->files, and done with remap
7075 free(remap);
7076
7077 // now scan those directories using the standard scan
7078 for (i=0; i < stb_arr_len(rescan); ++i) {
7079 int z = rescan[i];
7080 stb__dirtree_scandir(db->dirs[z].path, db->dirs[z].last_modified, active);
7081 }
7082 stb_arr_free(rescan);
7083
7084 return changes_detected;
7085 }
7086
7087 static void stb__dirtree_free_raw(stb_dirtree *d)
7088 {
7089 stb_free(d->string_pool);
7090 stb_arr_free(d->dirs);
7091 stb_arr_free(d->files);
7092 }
7093
7094 stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file)
7095 {
7096 stb_dirtree *output = (stb_dirtree *) malloc(sizeof(*output));
7097 stb_dirtree db,active;
7098 int prev_dir_count, cache_mismatch;
7099
7100 char *stripped_dir; // store the directory name without a trailing '/' or '\\'
7101
7102 // load the database of last-known state on disk
7103 db.string_pool = NULL;
7104 db.files = NULL;
7105 db.dirs = NULL;
7106
7107 stripped_dir = stb_strip_final_slash(strdup(dir));
7108
7109 if (cache_file != NULL)
7110 stb__dirtree_load_db(cache_file, &db, stripped_dir);
7111 else if (stb__showfile)
7112 printf("No cache file\n");
7113
7114 active.files = NULL;
7115 active.dirs = NULL;
7116 active.string_pool = stb_malloc(0,1); // @TODO: share string pools between both?
7117
7118 // check all the directories in the database; make note if
7119 // anything we scanned had changed, and rescan those things
7120 cache_mismatch = stb__dirtree_update_db(&db, &active);
7121
7122 // check the root tree
7123 prev_dir_count = stb_arr_len(active.dirs); // record how many directories we've seen
7124
7125 stb__dirtree_scandir(stripped_dir, 0, &active); // no last_modified time available for root
7126
7127 if (stb__dircount_mask)
7128 printf(" \r");
7129
7130 // done with the DB; write it back out if any changes, i.e. either
7131 // 1. any inconsistency found between cached information and actual disk
7132 // or 2. if scanning the root found any new directories--which we detect because
7133 // more than one directory got added to the active db during that scan
7134 if (cache_mismatch || stb_arr_len(active.dirs) > prev_dir_count+1)
7135 stb__dirtree_save_db(cache_file, &active, stripped_dir);
7136
7137 free(stripped_dir);
7138
7139 stb__dirtree_free_raw(&db);
7140
7141 *output = active;
7142 return output;
7143 }
7144
7145 stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir)
7146 {
7147 int i;
7148 stb_uint8 sha[20];
7149 char dir_lower[1024];
7150 char cache_file[1024],*s;
7151 if (cache_dir == NULL)
7152 return stb_dirtree_get_with_file(dir, NULL);
7153 strcpy(dir_lower, dir);
7154 stb_tolower(dir_lower);
7155 stb_sha1(sha, (unsigned char *) dir_lower, strlen(dir_lower));
7156 strcpy(cache_file, cache_dir);
7157 s = cache_file + strlen(cache_file);
7158 if (s[-1] != '//' && s[-1] != '\\') *s++ = '/';
7159 strcpy(s, "dirtree_");
7160 s += strlen(s);
7161 for (i=0; i < 8; ++i) {
7162 char *hex = "0123456789abcdef";
7163 stb_uint z = sha[i];
7164 *s++ = hex[z >> 4];
7165 *s++ = hex[z & 15];
7166 }
7167 strcpy(s, ".bin");
7168 return stb_dirtree_get_with_file(dir, cache_file);
7169 }
7170
7171 stb_dirtree *stb_dirtree_get(char *dir)
7172 {
7173 char cache_dir[256];
7174 strcpy(cache_dir, "c:/stb");
7175 #ifdef STB_HAS_REGISTRY
7176 {
7177 void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
7178 if (reg) {
7179 stb_reg_read(reg, "dirtree", cache_dir, sizeof(cache_dir));
7180 stb_reg_close(reg);
7181 }
7182 }
7183 #endif
7184 return stb_dirtree_get_dir(dir, cache_dir);
7185 }
7186
7187 void stb_dirtree_free(stb_dirtree *d)
7188 {
7189 stb__dirtree_free_raw(d);
7190 free(d);
7191 }
7192
7193 void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last)
7194 {
7195 stb__dirtree_add_dir(path, last, active);
7196 }
7197
7198 void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last)
7199 {
7200 stb__dirtree_add_file(name, dir, size, last, active);
7201 }
7202
7203 void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir)
7204 {
7205 char *s = stb_strip_final_slash(strdup(dir));
7206 target->dirs = 0;
7207 target->files = 0;
7208 target->string_pool = 0;
7209 stb__dirtree_load_db(filename, target, s);
7210 free(s);
7211 }
7212
7213 void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir)
7214 {
7215 stb__dirtree_save_db(filename, target, 0); // don't strip out any directories
7216 }
7217
7218 #endif // STB_DEFINE
7219
7220 #endif // _WIN32
7221 #endif // STB_NO_STB_STRINGS
7222
7223 //////////////////////////////////////////////////////////////////////////////
7224 //
7225 // STB_MALLOC_WRAPPER
7226 //
7227 // you can use the wrapper functions with your own malloc wrapper,
7228 // or define STB_MALLOC_WRAPPER project-wide to have
7229 // malloc/free/realloc/strdup all get vectored to it
7230
7231 // this has too many very specific error messages you could google for and find in stb.h,
7232 // so don't use it if they don't want any stb.h-identifiable strings
7233 #if defined(STB_DEFINE) && !defined(STB_NO_STB_STRINGS)
7234
7235 typedef struct
7236 {
7237 void *p;
7238 char *file;
7239 int line;
7240 int size;
7241 } stb_malloc_record;
7242
7243 #ifndef STB_MALLOC_HISTORY_COUNT
7244 #define STB_MALLOC_HISTORY_COUNT 50 // 800 bytes
7245 #endif
7246
7247 stb_malloc_record *stb__allocations;
7248 static int stb__alloc_size, stb__alloc_limit, stb__alloc_mask;
7249 int stb__alloc_count;
7250
7251 stb_malloc_record stb__alloc_history[STB_MALLOC_HISTORY_COUNT];
7252 int stb__history_pos;
7253
7254 static int stb__hashfind(void *p)
7255 {
7256 stb_uint32 h = stb_hashptr(p);
7257 int s,n = h & stb__alloc_mask;
7258 if (stb__allocations[n].p == p)
7259 return n;
7260 s = stb_rehash(h)|1;
7261 for(;;) {
7262 if (stb__allocations[n].p == NULL)
7263 return -1;
7264 n = (n+s) & stb__alloc_mask;
7265 if (stb__allocations[n].p == p)
7266 return n;
7267 }
7268 }
7269
7270 int stb_wrapper_allocsize(void *p)
7271 {
7272 int n = stb__hashfind(p);
7273 if (n < 0) return 0;
7274 return stb__allocations[n].size;
7275 }
7276
7277 static int stb__historyfind(void *p)
7278 {
7279 int n = stb__history_pos;
7280 int i;
7281 for (i=0; i < STB_MALLOC_HISTORY_COUNT; ++i) {
7282 if (--n < 0) n = STB_MALLOC_HISTORY_COUNT-1;
7283 if (stb__alloc_history[n].p == p)
7284 return n;
7285 }
7286 return -1;
7287 }
7288
7289 static void stb__add_alloc(void *p, int sz, char *file, int line);
7290 static void stb__grow_alloc(void)
7291 {
7292 int i,old_num = stb__alloc_size;
7293 stb_malloc_record *old = stb__allocations;
7294 if (stb__alloc_size == 0)
7295 stb__alloc_size = 64;
7296 else
7297 stb__alloc_size *= 2;
7298
7299 stb__allocations = (stb_malloc_record *) stb__realloc_raw(NULL, stb__alloc_size * sizeof(stb__allocations[0]));
7300 if (stb__allocations == NULL)
7301 stb_fatal("Internal error: couldn't grow malloc wrapper table");
7302 memset(stb__allocations, 0, stb__alloc_size * sizeof(stb__allocations[0]));
7303 stb__alloc_limit = (stb__alloc_size*3)>>2;
7304 stb__alloc_mask = stb__alloc_size-1;
7305
7306 stb__alloc_count = 0;
7307
7308 for (i=0; i < old_num; ++i)
7309 if (old[i].p > STB_DEL) {
7310 stb__add_alloc(old[i].p, old[i].size, old[i].file, old[i].line);
7311 assert(stb__hashfind(old[i].p) >= 0);
7312 }
7313 for (i=0; i < old_num; ++i)
7314 if (old[i].p > STB_DEL)
7315 assert(stb__hashfind(old[i].p) >= 0);
7316 stb__realloc_raw(old, 0);
7317 }
7318
7319 static void stb__add_alloc(void *p, int sz, char *file, int line)
7320 {
7321 stb_uint32 h;
7322 int n;
7323 if (stb__alloc_count >= stb__alloc_limit)
7324 stb__grow_alloc();
7325 h = stb_hashptr(p);
7326 n = h & stb__alloc_mask;
7327 if (stb__allocations[n].p > STB_DEL) {
7328 int s = stb_rehash(h)|1;
7329 do {
7330 n = (n+s) & stb__alloc_mask;
7331 } while (stb__allocations[n].p > STB_DEL);
7332 }
7333 assert(stb__allocations[n].p == NULL || stb__allocations[n].p == STB_DEL);
7334 stb__allocations[n].p = p;
7335 stb__allocations[n].size = sz;
7336 stb__allocations[n].line = line;
7337 stb__allocations[n].file = file;
7338 ++stb__alloc_count;
7339 }
7340
7341 static void stb__remove_alloc(int n, char *file, int line)
7342 {
7343 stb__alloc_history[stb__history_pos] = stb__allocations[n];
7344 stb__alloc_history[stb__history_pos].file = file;
7345 stb__alloc_history[stb__history_pos].line = line;
7346 if (++stb__history_pos == STB_MALLOC_HISTORY_COUNT)
7347 stb__history_pos = 0;
7348 stb__allocations[n].p = STB_DEL;
7349 --stb__alloc_count;
7350 }
7351
7352 void stb_wrapper_malloc(void *p, int sz, char *file, int line)
7353 {
7354 if (!p) return;
7355 stb__add_alloc(p,sz,file,line);
7356 }
7357
7358 void stb_wrapper_free(void *p, char *file, int line)
7359 {
7360 int n;
7361
7362 if (p == NULL) return;
7363
7364 n = stb__hashfind(p);
7365
7366 if (n >= 0)
7367 stb__remove_alloc(n, file, line);
7368 else {
7369 // tried to free something we hadn't allocated!
7370 n = stb__historyfind(p);
7371 assert(0); /* NOTREACHED */
7372 if (n >= 0)
7373 stb_fatal("Attempted to free %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7374 stb__alloc_history[n].size, p,
7375 file, line,
7376 stb__alloc_history[n].file, stb__alloc_history[n].line);
7377 else
7378 stb_fatal("Attempted to free unknown block %p at %s:%d", p, file,line);
7379 }
7380 }
7381
7382 void stb_wrapper_check(void *p)
7383 {
7384 int n;
7385
7386 if (p == NULL) return;
7387
7388 n = stb__hashfind(p);
7389
7390 if (n >= 0) return;
7391
7392 for (n=0; n < stb__alloc_size; ++n)
7393 if (stb__allocations[n].p == p)
7394 stb_fatal("Internal error: pointer %p was allocated, but hash search failed", p);
7395
7396 // tried to free something that wasn't allocated!
7397 n = stb__historyfind(p);
7398 if (n >= 0)
7399 stb_fatal("Checked %d-byte block %p previously freed/realloced at %s:%d",
7400 stb__alloc_history[n].size, p,
7401 stb__alloc_history[n].file, stb__alloc_history[n].line);
7402 stb_fatal("Checked unknown block %p");
7403 }
7404
7405 void stb_wrapper_realloc(void *p, void *q, int sz, char *file, int line)
7406 {
7407 int n;
7408 if (p == NULL) { stb_wrapper_malloc(q, sz, file, line); return; }
7409 if (q == NULL) return; // nothing happened
7410
7411 n = stb__hashfind(p);
7412 if (n == -1) {
7413 // tried to free something we hadn't allocated!
7414 // this is weird, though, because we got past the realloc!
7415 n = stb__historyfind(p);
7416 assert(0); /* NOTREACHED */
7417 if (n >= 0)
7418 stb_fatal("Attempted to realloc %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
7419 stb__alloc_history[n].size, p,
7420 file, line,
7421 stb__alloc_history[n].file, stb__alloc_history[n].line);
7422 else
7423 stb_fatal("Attempted to realloc unknown block %p at %s:%d", p, file,line);
7424 } else {
7425 if (q == p) {
7426 stb__allocations[n].size = sz;
7427 stb__allocations[n].file = file;
7428 stb__allocations[n].line = line;
7429 } else {
7430 stb__remove_alloc(n, file, line);
7431 stb__add_alloc(q,sz,file,line);
7432 }
7433 }
7434 }
7435
7436 void stb_wrapper_listall(void (*func)(void *ptr, int sz, char *file, int line))
7437 {
7438 int i;
7439 for (i=0; i < stb__alloc_size; ++i)
7440 if (stb__allocations[i].p > STB_DEL)
7441 func(stb__allocations[i].p , stb__allocations[i].size,
7442 stb__allocations[i].file, stb__allocations[i].line);
7443 }
7444
7445 void stb_wrapper_dump(char *filename)
7446 {
7447 int i;
7448 FILE *f = fopen(filename, "w");
7449 if (!f) return;
7450 for (i=0; i < stb__alloc_size; ++i)
7451 if (stb__allocations[i].p > STB_DEL)
7452 fprintf(f, "%p %7d - %4d %s\n",
7453 stb__allocations[i].p , stb__allocations[i].size,
7454 stb__allocations[i].line, stb__allocations[i].file);
7455 }
7456 #endif // STB_DEFINE
7457
7458
7459 //////////////////////////////////////////////////////////////////////////////
7460 //
7461 // stb_pointer_set
7462 //
7463 //
7464 // For data structures that support querying by key, data structure
7465 // classes always hand-wave away the issue of what to do if two entries
7466 // have the same key: basically, store a linked list of all the nodes
7467 // which have the same key (a LISP-style list).
7468 //
7469 // The thing is, it's not that trivial. If you have an O(log n)
7470 // lookup data structure, but then n/4 items have the same value,
7471 // you don't want to spend O(n) time scanning that list when
7472 // deleting an item if you already have a pointer to the item.
7473 // (You have to spend O(n) time enumerating all the items with
7474 // a given key, sure, and you can't accelerate deleting a particular
7475 // item if you only have the key, not a pointer to the item.)
7476 //
7477 // I'm going to call this data structure, whatever it turns out to
7478 // be, a "pointer set", because we don't store any associated data for
7479 // items in this data structure, we just answer the question of
7480 // whether an item is in it or not (it's effectively one bit per pointer).
7481 // Technically they don't have to be pointers; you could cast ints
7482 // to (void *) if you want, but you can't store 0 or 1 because of the
7483 // hash table.
7484 //
7485 // Since the fastest data structure we might want to add support for
7486 // identical-keys to is a hash table with O(1)-ish lookup time,
7487 // that means that the conceptual "linked list of all items with
7488 // the same indexed value" that we build needs to have the same
7489 // performance; that way when we index a table we think is arbitrary
7490 // ints, but in fact half of them are 0, we don't get screwed.
7491 //
7492 // Therefore, it needs to be a hash table, at least when it gets
7493 // large. On the other hand, when the data has totally arbitrary ints
7494 // or floats, there won't be many collisions, and we'll have tons of
7495 // 1-item bitmaps. That will be grossly inefficient as hash tables;
7496 // trade-off; the hash table is reasonably efficient per-item when
7497 // it's large, but not when it's small. So we need to do something
7498 // Judy-like and use different strategies depending on the size.
7499 //
7500 // Like Judy, we'll use the bottom bit to encode the strategy:
7501 //
7502 // bottom bits:
7503 // 00 - direct pointer
7504 // 01 - 4-item bucket (16 bytes, no length, NULLs)
7505 // 10 - N-item array
7506 // 11 - hash table
7507
7508 typedef struct stb_ps stb_ps;
7509
7510 STB_EXTERN int stb_ps_find (stb_ps *ps, void *value);
7511 STB_EXTERN stb_ps * stb_ps_add (stb_ps *ps, void *value);
7512 STB_EXTERN stb_ps * stb_ps_remove(stb_ps *ps, void *value);
7513 STB_EXTERN stb_ps * stb_ps_remove_any(stb_ps *ps, void **value);
7514 STB_EXTERN void stb_ps_delete(stb_ps *ps);
7515 STB_EXTERN int stb_ps_count (stb_ps *ps);
7516
7517 STB_EXTERN stb_ps * stb_ps_copy (stb_ps *ps);
7518 STB_EXTERN int stb_ps_subset(stb_ps *bigger, stb_ps *smaller);
7519 STB_EXTERN int stb_ps_eq (stb_ps *p0, stb_ps *p1);
7520
7521 STB_EXTERN void ** stb_ps_getlist (stb_ps *ps, int *count);
7522 STB_EXTERN int stb_ps_writelist(stb_ps *ps, void **list, int size );
7523
7524 // enum and fastlist don't allocate storage, but you must consume the
7525 // list before there's any chance the data structure gets screwed up;
7526 STB_EXTERN int stb_ps_enum (stb_ps *ps, void *data,
7527 int (*func)(void *value, void*data) );
7528 STB_EXTERN void ** stb_ps_fastlist(stb_ps *ps, int *count);
7529 // result:
7530 // returns a list, *count is the length of that list,
7531 // but some entries of the list may be invalid;
7532 // test with 'stb_ps_fastlist_valid(x)'
7533
7534 #define stb_ps_fastlist_valid(x) ((stb_uinta) (x) > 1)
7535
7536 #ifdef STB_DEFINE
7537
7538 enum
7539 {
7540 STB_ps_direct = 0,
7541 STB_ps_bucket = 1,
7542 STB_ps_array = 2,
7543 STB_ps_hash = 3,
7544 };
7545
7546 #define STB_BUCKET_SIZE 4
7547
7548 typedef struct
7549 {
7550 void *p[STB_BUCKET_SIZE];
7551 } stb_ps_bucket;
7552 #define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket))
7553 #define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket))
7554
7555 static void stb_bucket_free(stb_ps_bucket *b)
7556 {
7557 free(b);
7558 }
7559
7560 static stb_ps_bucket *stb_bucket_create2(void *v0, void *v1)
7561 {
7562 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7563 b->p[0] = v0;
7564 b->p[1] = v1;
7565 b->p[2] = NULL;
7566 b->p[3] = NULL;
7567 return b;
7568 }
7569
7570 static stb_ps_bucket * stb_bucket_create3(void **v)
7571 {
7572 stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
7573 b->p[0] = v[0];
7574 b->p[1] = v[1];
7575 b->p[2] = v[2];
7576 b->p[3] = NULL;
7577 return b;
7578 }
7579
7580
7581 // could use stb_arr, but this will save us memory
7582 typedef struct
7583 {
7584 int count;
7585 void *p[1];
7586 } stb_ps_array;
7587 #define GetArray(p) ((stb_ps_array *) ((char *) (p) - STB_ps_array))
7588 #define EncodeArray(p) ((stb_ps *) ((char *) (p) + STB_ps_array))
7589
7590 static int stb_ps_array_max = 13;
7591
7592 typedef struct
7593 {
7594 int size, mask;
7595 int count, count_deletes;
7596 int grow_threshhold;
7597 int shrink_threshhold;
7598 int rehash_threshhold;
7599 int any_offset;
7600 void *table[1];
7601 } stb_ps_hash;
7602 #define GetHash(p) ((stb_ps_hash *) ((char *) (p) - STB_ps_hash))
7603 #define EncodeHash(p) ((stb_ps *) ((char *) (p) + STB_ps_hash))
7604
7605 #define stb_ps_empty(v) (((stb_uint32) v) <= 1)
7606
7607 static stb_ps_hash *stb_ps_makehash(int size, int old_size, void **old_data)
7608 {
7609 int i;
7610 stb_ps_hash *h = (stb_ps_hash *) malloc(sizeof(*h) + (size-1) * sizeof(h->table[0]));
7611 assert(stb_is_pow2(size));
7612 h->size = size;
7613 h->mask = size-1;
7614 h->shrink_threshhold = (int) (0.3f * size);
7615 h-> grow_threshhold = (int) (0.8f * size);
7616 h->rehash_threshhold = (int) (0.9f * size);
7617 h->count = 0;
7618 h->count_deletes = 0;
7619 h->any_offset = 0;
7620 memset(h->table, 0, size * sizeof(h->table[0]));
7621 for (i=0; i < old_size; ++i)
7622 if (!stb_ps_empty(old_data[i]))
7623 stb_ps_add(EncodeHash(h), old_data[i]);
7624 return h;
7625 }
7626
7627 void stb_ps_delete(stb_ps *ps)
7628 {
7629 switch (3 & (int) ps) {
7630 case STB_ps_direct: break;
7631 case STB_ps_bucket: stb_bucket_free(GetBucket(ps)); break;
7632 case STB_ps_array : free(GetArray(ps)); break;
7633 case STB_ps_hash : free(GetHash(ps)); break;
7634 }
7635 }
7636
7637 stb_ps *stb_ps_copy(stb_ps *ps)
7638 {
7639 int i;
7640 // not a switch: order based on expected performance/power-law distribution
7641 switch (3 & (int) ps) {
7642 case STB_ps_direct: return ps;
7643 case STB_ps_bucket: {
7644 stb_ps_bucket *n = (stb_ps_bucket *) malloc(sizeof(*n));
7645 *n = *GetBucket(ps);
7646 return EncodeBucket(n);
7647 }
7648 case STB_ps_array: {
7649 stb_ps_array *a = GetArray(ps);
7650 stb_ps_array *n = (stb_ps_array *) malloc(sizeof(*n) + stb_ps_array_max * sizeof(n->p[0]));
7651 n->count = a->count;
7652 for (i=0; i < a->count; ++i)
7653 n->p[i] = a->p[i];
7654 return EncodeArray(n);
7655 }
7656 case STB_ps_hash: {
7657 stb_ps_hash *h = GetHash(ps);
7658 stb_ps_hash *n = stb_ps_makehash(h->size, h->size, h->table);
7659 return EncodeHash(n);
7660 }
7661 }
7662 assert(0); /* NOTREACHED */
7663 return NULL;
7664 }
7665
7666 int stb_ps_find(stb_ps *ps, void *value)
7667 {
7668 int i, code = 3 & (int) ps;
7669 assert((3 & (int) value) == STB_ps_direct);
7670 assert(stb_ps_fastlist_valid(value));
7671 // not a switch: order based on expected performance/power-law distribution
7672 if (code == STB_ps_direct)
7673 return value == ps;
7674 if (code == STB_ps_bucket) {
7675 stb_ps_bucket *b = GetBucket(ps);
7676 assert(STB_BUCKET_SIZE == 4);
7677 if (b->p[0] == value || b->p[1] == value ||
7678 b->p[2] == value || b->p[3] == value)
7679 return STB_TRUE;
7680 return STB_FALSE;
7681 }
7682 if (code == STB_ps_array) {
7683 stb_ps_array *a = GetArray(ps);
7684 for (i=0; i < a->count; ++i)
7685 if (a->p[i] == value)
7686 return STB_TRUE;
7687 return STB_FALSE;
7688 } else {
7689 stb_ps_hash *h = GetHash(ps);
7690 stb_uint32 hash = stb_hashptr(value);
7691 stb_uint32 s, n = hash & h->mask;
7692 void **t = h->table;
7693 if (t[n] == value) return STB_TRUE;
7694 if (t[n] == NULL) return STB_FALSE;
7695 s = stb_rehash(hash) | 1;
7696 do {
7697 n = (n + s) & h->mask;
7698 if (t[n] == value) return STB_TRUE;
7699 } while (t[n] != NULL);
7700 return STB_FALSE;
7701 }
7702 }
7703
7704 stb_ps * stb_ps_add (stb_ps *ps, void *value)
7705 {
7706 #ifdef STB_DEBUG
7707 assert(!stb_ps_find(ps,value));
7708 #endif
7709 if (value == NULL) return ps; // ignore NULL adds to avoid bad breakage
7710 assert((3 & (int) value) == STB_ps_direct);
7711 assert(stb_ps_fastlist_valid(value));
7712 assert(value != STB_DEL); // STB_DEL is less likely
7713
7714 switch (3 & (int) ps) {
7715 case STB_ps_direct:
7716 if (ps == NULL) return (stb_ps *) value;
7717 return EncodeBucket(stb_bucket_create2(ps,value));
7718
7719 case STB_ps_bucket: {
7720 stb_ps_bucket *b = GetBucket(ps);
7721 stb_ps_array *a;
7722 assert(STB_BUCKET_SIZE == 4);
7723 if (b->p[0] == NULL) { b->p[0] = value; return ps; }
7724 if (b->p[1] == NULL) { b->p[1] = value; return ps; }
7725 if (b->p[2] == NULL) { b->p[2] = value; return ps; }
7726 if (b->p[3] == NULL) { b->p[3] = value; return ps; }
7727 a = (stb_ps_array *) malloc(sizeof(*a) + 7 * sizeof(a->p[0])); // 8 slots, must be 2^k
7728 memcpy(a->p, b, sizeof(*b));
7729 a->p[4] = value;
7730 a->count = 5;
7731 stb_bucket_free(b);
7732 return EncodeArray(a);
7733 }
7734
7735 case STB_ps_array: {
7736 stb_ps_array *a = GetArray(ps);
7737 if (a->count == stb_ps_array_max) {
7738 // promote from array to hash
7739 stb_ps_hash *h = stb_ps_makehash(2 << stb_log2_ceil(a->count), a->count, a->p);
7740 free(a);
7741 return stb_ps_add(EncodeHash(h), value);
7742 }
7743 // do we need to resize the array? the array doubles in size when it
7744 // crosses a power-of-two
7745 if ((a->count & (a->count-1))==0) {
7746 int newsize = a->count*2;
7747 // clamp newsize to max if:
7748 // 1. it's larger than max
7749 // 2. newsize*1.5 is larger than max (to avoid extra resizing)
7750 if (newsize + a->count > stb_ps_array_max)
7751 newsize = stb_ps_array_max;
7752 a = (stb_ps_array *) realloc(a, sizeof(*a) + (newsize-1) * sizeof(a->p[0]));
7753 }
7754 a->p[a->count++] = value;
7755 return EncodeArray(a);
7756 }
7757 case STB_ps_hash: {
7758 stb_ps_hash *h = GetHash(ps);
7759 stb_uint32 hash = stb_hashptr(value);
7760 stb_uint32 n = hash & h->mask;
7761 void **t = h->table;
7762 // find first NULL or STB_DEL entry
7763 if (!stb_ps_empty(t[n])) {
7764 stb_uint32 s = stb_rehash(hash) | 1;
7765 do {
7766 n = (n + s) & h->mask;
7767 } while (!stb_ps_empty(t[n]));
7768 }
7769 if (t[n] == STB_DEL)
7770 -- h->count_deletes;
7771 t[n] = value;
7772 ++ h->count;
7773 if (h->count == h->grow_threshhold) {
7774 stb_ps_hash *h2 = stb_ps_makehash(h->size*2, h->size, t);
7775 free(h);
7776 return EncodeHash(h2);
7777 }
7778 if (h->count + h->count_deletes == h->rehash_threshhold) {
7779 stb_ps_hash *h2 = stb_ps_makehash(h->size, h->size, t);
7780 free(h);
7781 return EncodeHash(h2);
7782 }
7783 return ps;
7784 }
7785 }
7786 return NULL; /* NOTREACHED */
7787 }
7788
7789 stb_ps *stb_ps_remove(stb_ps *ps, void *value)
7790 {
7791 #ifdef STB_DEBUG
7792 assert(stb_ps_find(ps, value));
7793 #endif
7794 assert((3 & (int) value) == STB_ps_direct);
7795 if (value == NULL) return ps; // ignore NULL removes to avoid bad breakage
7796 switch (3 & (int) ps) {
7797 case STB_ps_direct:
7798 return ps == value ? NULL : ps;
7799 case STB_ps_bucket: {
7800 stb_ps_bucket *b = GetBucket(ps);
7801 int count=0;
7802 assert(STB_BUCKET_SIZE == 4);
7803 if (b->p[0] == value) b->p[0] = NULL; else count += (b->p[0] != NULL);
7804 if (b->p[1] == value) b->p[1] = NULL; else count += (b->p[1] != NULL);
7805 if (b->p[2] == value) b->p[2] = NULL; else count += (b->p[2] != NULL);
7806 if (b->p[3] == value) b->p[3] = NULL; else count += (b->p[3] != NULL);
7807 if (count == 1) { // shrink bucket at size 1
7808 value = b->p[0];
7809 if (value == NULL) value = b->p[1];
7810 if (value == NULL) value = b->p[2];
7811 if (value == NULL) value = b->p[3];
7812 assert(value != NULL);
7813 stb_bucket_free(b);
7814 return (stb_ps *) value; // return STB_ps_direct of value
7815 }
7816 return ps;
7817 }
7818 case STB_ps_array: {
7819 stb_ps_array *a = GetArray(ps);
7820 int i;
7821 for (i=0; i < a->count; ++i) {
7822 if (a->p[i] == value) {
7823 a->p[i] = a->p[--a->count];
7824 if (a->count == 3) { // shrink to bucket!
7825 stb_ps_bucket *b = stb_bucket_create3(a->p);
7826 free(a);
7827 return EncodeBucket(b);
7828 }
7829 return ps;
7830 }
7831 }
7832 return ps;
7833 }
7834 case STB_ps_hash: {
7835 stb_ps_hash *h = GetHash(ps);
7836 stb_uint32 hash = stb_hashptr(value);
7837 stb_uint32 s, n = hash & h->mask;
7838 void **t = h->table;
7839 if (t[n] != value) {
7840 s = stb_rehash(hash) | 1;
7841 do {
7842 n = (n + s) & h->mask;
7843 } while (t[n] != value);
7844 }
7845 t[n] = STB_DEL;
7846 -- h->count;
7847 ++ h->count_deletes;
7848 // should we shrink down to an array?
7849 if (h->count < stb_ps_array_max) {
7850 int n = 1 << stb_log2_floor(stb_ps_array_max);
7851 if (h->count < n) {
7852 stb_ps_array *a = (stb_ps_array *) malloc(sizeof(*a) + (n-1) * sizeof(a->p[0]));
7853 int i,j=0;
7854 for (i=0; i < h->size; ++i)
7855 if (!stb_ps_empty(t[i]))
7856 a->p[j++] = t[i];
7857 assert(j == h->count);
7858 a->count = j;
7859 free(h);
7860 return EncodeArray(a);
7861 }
7862 }
7863 if (h->count == h->shrink_threshhold) {
7864 stb_ps_hash *h2 = stb_ps_makehash(h->size >> 1, h->size, t);
7865 free(h);
7866 return EncodeHash(h2);
7867 }
7868 return ps;
7869 }
7870 }
7871 return ps; /* NOTREACHED */
7872 }
7873
7874 stb_ps *stb_ps_remove_any(stb_ps *ps, void **value)
7875 {
7876 assert(ps != NULL);
7877 switch (3 & (int) ps) {
7878 case STB_ps_direct:
7879 *value = ps;
7880 return NULL;
7881 case STB_ps_bucket: {
7882 stb_ps_bucket *b = GetBucket(ps);
7883 int count=0, slast=0, last=0;
7884 assert(STB_BUCKET_SIZE == 4);
7885 if (b->p[0]) { ++count; last = 0; }
7886 if (b->p[1]) { ++count; slast = last; last = 1; }
7887 if (b->p[2]) { ++count; slast = last; last = 2; }
7888 if (b->p[3]) { ++count; slast = last; last = 3; }
7889 *value = b->p[last];
7890 b->p[last] = 0;
7891 if (count == 2) {
7892 void *leftover = b->p[slast]; // second to last
7893 stb_bucket_free(b);
7894 return (stb_ps *) leftover;
7895 }
7896 return ps;
7897 }
7898 case STB_ps_array: {
7899 stb_ps_array *a = GetArray(ps);
7900 *value = a->p[a->count-1];
7901 if (a->count == 4)
7902 return stb_ps_remove(ps, *value);
7903 --a->count;
7904 return ps;
7905 }
7906 case STB_ps_hash: {
7907 stb_ps_hash *h = GetHash(ps);
7908 void **t = h->table;
7909 stb_uint32 n = h->any_offset;
7910 while (stb_ps_empty(t[n]))
7911 n = (n + 1) & h->mask;
7912 *value = t[n];
7913 h->any_offset = (n+1) & h->mask;
7914 // check if we need to skip down to the previous type
7915 if (h->count-1 < stb_ps_array_max || h->count-1 == h->shrink_threshhold)
7916 return stb_ps_remove(ps, *value);
7917 t[n] = STB_DEL;
7918 -- h->count;
7919 ++ h->count_deletes;
7920 return ps;
7921 }
7922 }
7923 return ps; /* NOTREACHED */
7924 }
7925
7926
7927 void ** stb_ps_getlist(stb_ps *ps, int *count)
7928 {
7929 int i,n=0;
7930 void **p = NULL;
7931 switch (3 & (int) ps) {
7932 case STB_ps_direct:
7933 if (ps == NULL) { *count = 0; return NULL; }
7934 p = (void **) malloc(sizeof(*p) * 1);
7935 p[0] = ps;
7936 *count = 1;
7937 return p;
7938 case STB_ps_bucket: {
7939 stb_ps_bucket *b = GetBucket(ps);
7940 p = (void **) malloc(sizeof(*p) * STB_BUCKET_SIZE);
7941 for (i=0; i < STB_BUCKET_SIZE; ++i)
7942 if (b->p[i] != NULL)
7943 p[n++] = b->p[i];
7944 break;
7945 }
7946 case STB_ps_array: {
7947 stb_ps_array *a = GetArray(ps);
7948 p = (void **) malloc(sizeof(*p) * a->count);
7949 memcpy(p, a->p, sizeof(*p) * a->count);
7950 *count = a->count;
7951 return p;
7952 }
7953 case STB_ps_hash: {
7954 stb_ps_hash *h = GetHash(ps);
7955 p = (void **) malloc(sizeof(*p) * h->count);
7956 for (i=0; i < h->size; ++i)
7957 if (!stb_ps_empty(h->table[i]))
7958 p[n++] = h->table[i];
7959 break;
7960 }
7961 }
7962 *count = n;
7963 return p;
7964 }
7965
7966 int stb_ps_writelist(stb_ps *ps, void **list, int size )
7967 {
7968 int i,n=0;
7969 switch (3 & (int) ps) {
7970 case STB_ps_direct:
7971 if (ps == NULL || size <= 0) return 0;
7972 list[0] = ps;
7973 return 1;
7974 case STB_ps_bucket: {
7975 stb_ps_bucket *b = GetBucket(ps);
7976 for (i=0; i < STB_BUCKET_SIZE; ++i)
7977 if (b->p[i] != NULL && n < size)
7978 list[n++] = b->p[i];
7979 return n;
7980 }
7981 case STB_ps_array: {
7982 stb_ps_array *a = GetArray(ps);
7983 n = stb_min(size, a->count);
7984 memcpy(list, a->p, sizeof(*list) * n);
7985 return n;
7986 }
7987 case STB_ps_hash: {
7988 stb_ps_hash *h = GetHash(ps);
7989 if (size <= 0) return 0;
7990 for (i=0; i < h->count; ++i) {
7991 if (!stb_ps_empty(h->table[i])) {
7992 list[n++] = h->table[i];
7993 if (n == size) break;
7994 }
7995 }
7996 return n;
7997 }
7998 }
7999 return 0; /* NOTREACHED */
8000 }
8001
8002 int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data))
8003 {
8004 int i;
8005 switch (3 & (int) ps) {
8006 case STB_ps_direct:
8007 if (ps == NULL) return STB_TRUE;
8008 return func(ps, data);
8009 case STB_ps_bucket: {
8010 stb_ps_bucket *b = GetBucket(ps);
8011 for (i=0; i < STB_BUCKET_SIZE; ++i)
8012 if (b->p[i] != NULL)
8013 if (!func(b->p[i], data))
8014 return STB_FALSE;
8015 return STB_TRUE;
8016 }
8017 case STB_ps_array: {
8018 stb_ps_array *a = GetArray(ps);
8019 for (i=0; i < a->count; ++i)
8020 if (!func(a->p[i], data))
8021 return STB_FALSE;
8022 return STB_TRUE;
8023 }
8024 case STB_ps_hash: {
8025 stb_ps_hash *h = GetHash(ps);
8026 for (i=0; i < h->count; ++i)
8027 if (!stb_ps_empty(h->table[i]))
8028 if (!func(h->table[i], data))
8029 return STB_FALSE;
8030 return STB_TRUE;
8031 }
8032 }
8033 return STB_TRUE; /* NOTREACHED */
8034 }
8035
8036 int stb_ps_count (stb_ps *ps)
8037 {
8038 switch (3 & (int) ps) {
8039 case STB_ps_direct:
8040 return ps != NULL;
8041 case STB_ps_bucket: {
8042 stb_ps_bucket *b = GetBucket(ps);
8043 return (b->p[0] != NULL) + (b->p[1] != NULL) +
8044 (b->p[2] != NULL) + (b->p[3] != NULL);
8045 }
8046 case STB_ps_array: {
8047 stb_ps_array *a = GetArray(ps);
8048 return a->count;
8049 }
8050 case STB_ps_hash: {
8051 stb_ps_hash *h = GetHash(ps);
8052 return h->count;
8053 }
8054 }
8055 return 0;
8056 }
8057
8058 void ** stb_ps_fastlist(stb_ps *ps, int *count)
8059 {
8060 static void *storage;
8061
8062 switch (3 & (int) ps) {
8063 case STB_ps_direct:
8064 if (ps == NULL) { *count = 0; return NULL; }
8065 storage = ps;
8066 *count = 1;
8067 return &storage;
8068 case STB_ps_bucket: {
8069 stb_ps_bucket *b = GetBucket(ps);
8070 *count = STB_BUCKET_SIZE;
8071 return b->p;
8072 }
8073 case STB_ps_array: {
8074 stb_ps_array *a = GetArray(ps);
8075 *count = a->count;
8076 return a->p;
8077 }
8078 case STB_ps_hash: {
8079 stb_ps_hash *h = GetHash(ps);
8080 *count = h->size;
8081 return h->table;
8082 }
8083 }
8084 return NULL; /* NOTREACHED */
8085 }
8086
8087 int stb_ps_subset(stb_ps *bigger, stb_ps *smaller)
8088 {
8089 int i, listlen;
8090 void **list = stb_ps_fastlist(smaller, &listlen);
8091 for(i=0; i < listlen; ++i)
8092 if (stb_ps_fastlist_valid(list[i]))
8093 if (!stb_ps_find(bigger, list[i]))
8094 return 0;
8095 return 1;
8096 }
8097
8098 int stb_ps_eq(stb_ps *p0, stb_ps *p1)
8099 {
8100 if (stb_ps_count(p0) != stb_ps_count(p1))
8101 return 0;
8102 return stb_ps_subset(p0, p1);
8103 }
8104
8105 #undef GetBucket
8106 #undef GetArray
8107 #undef GetHash
8108
8109 #undef EncodeBucket
8110 #undef EncodeArray
8111 #undef EncodeHash
8112
8113 #endif
8114
8115
8116 //////////////////////////////////////////////////////////////////////////////
8117 //
8118 // Random Numbers via Meresenne Twister or LCG
8119 //
8120
8121 STB_EXTERN unsigned long stb_srandLCG(unsigned long seed);
8122 STB_EXTERN unsigned long stb_randLCG(void);
8123 STB_EXTERN double stb_frandLCG(void);
8124
8125 STB_EXTERN void stb_srand(unsigned long seed);
8126 STB_EXTERN unsigned long stb_rand(void);
8127 STB_EXTERN double stb_frand(void);
8128 STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz,
8129 unsigned long seed);
8130 STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz);
8131
8132 STB_EXTERN unsigned long stb_randLCG_explicit(unsigned long seed);
8133
8134 #define stb_rand_define(x,y) \
8135 \
8136 unsigned long x(void) \
8137 { \
8138 static unsigned long stb__rand = y; \
8139 stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \
8140 return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \
8141 }
8142
8143 #ifdef STB_DEFINE
8144 unsigned long stb_randLCG_explicit(unsigned long seed)
8145 {
8146 return seed * 2147001325 + 715136305;
8147 }
8148
8149 static unsigned long stb__rand_seed=0;
8150
8151 unsigned long stb_srandLCG(unsigned long seed)
8152 {
8153 unsigned long previous = stb__rand_seed;
8154 stb__rand_seed = seed;
8155 return previous;
8156 }
8157
8158 unsigned long stb_randLCG(void)
8159 {
8160 stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator
8161 // shuffle non-random bits to the middle, and xor to decorrelate with seed
8162 return 0x31415926 ^ ((stb__rand_seed >> 16) + (stb__rand_seed << 16));
8163 }
8164
8165 double stb_frandLCG(void)
8166 {
8167 return stb_randLCG() / ((double) (1 << 16) * (1 << 16));
8168 }
8169
8170 void stb_shuffle(void *p, size_t n, size_t sz, unsigned long seed)
8171 {
8172 char *a;
8173 unsigned long old_seed;
8174 int i;
8175 if (seed)
8176 old_seed = stb_srandLCG(seed);
8177 a = (char *) p + (n-1) * sz;
8178
8179 for (i=n; i > 1; --i) {
8180 int j = stb_randLCG() % i;
8181 stb_swap(a, (char *) p + j * sz, sz);
8182 a -= sz;
8183 }
8184 if (seed)
8185 stb_srandLCG(old_seed);
8186 }
8187
8188 void stb_reverse(void *p, size_t n, size_t sz)
8189 {
8190 int i,j = n-1;
8191 for (i=0; i < j; ++i,--j) {
8192 stb_swap((char *) p + i * sz, (char *) p + j * sz, sz);
8193 }
8194 }
8195
8196 // public domain Mersenne Twister by Michael Brundage
8197 #define STB__MT_LEN 624
8198
8199 int stb__mt_index = STB__MT_LEN*sizeof(unsigned long)+1;
8200 unsigned long stb__mt_buffer[STB__MT_LEN];
8201
8202 void stb_srand(unsigned long seed)
8203 {
8204 int i;
8205 unsigned long old = stb_srandLCG(seed);
8206 for (i = 0; i < STB__MT_LEN; i++)
8207 stb__mt_buffer[i] = stb_randLCG();
8208 stb_srandLCG(old);
8209 stb__mt_index = STB__MT_LEN*sizeof(unsigned long);
8210 }
8211
8212 #define STB__MT_IA 397
8213 #define STB__MT_IB (STB__MT_LEN - STB__MT_IA)
8214 #define STB__UPPER_MASK 0x80000000
8215 #define STB__LOWER_MASK 0x7FFFFFFF
8216 #define STB__MATRIX_A 0x9908B0DF
8217 #define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK)
8218 #define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A)
8219
8220 unsigned long stb_rand()
8221 {
8222 unsigned long * b = stb__mt_buffer;
8223 int idx = stb__mt_index;
8224 unsigned long s,r;
8225 int i;
8226
8227 if (idx >= STB__MT_LEN*sizeof(unsigned long)) {
8228 if (idx > STB__MT_LEN*sizeof(unsigned long))
8229 stb_srand(0);
8230 idx = 0;
8231 i = 0;
8232 for (; i < STB__MT_IB; i++) {
8233 s = STB__TWIST(b, i, i+1);
8234 b[i] = b[i + STB__MT_IA] ^ (s >> 1) ^ STB__MAGIC(s);
8235 }
8236 for (; i < STB__MT_LEN-1; i++) {
8237 s = STB__TWIST(b, i, i+1);
8238 b[i] = b[i - STB__MT_IB] ^ (s >> 1) ^ STB__MAGIC(s);
8239 }
8240
8241 s = STB__TWIST(b, STB__MT_LEN-1, 0);
8242 b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s);
8243 }
8244 stb__mt_index = idx + sizeof(unsigned long);
8245
8246 r = *(unsigned long *)((unsigned char *)b + idx);
8247
8248 r ^= (r >> 11);
8249 r ^= (r << 7) & 0x9D2C5680;
8250 r ^= (r << 15) & 0xEFC60000;
8251 r ^= (r >> 18);
8252
8253 return r;
8254 }
8255
8256 double stb_frand(void)
8257 {
8258 return stb_rand() / ((double) (1 << 16) * (1 << 16));
8259 }
8260
8261 #endif
8262
8263
8264 //////////////////////////////////////////////////////////////////////////////
8265 //
8266 // stb_dupe
8267 //
8268 // stb_dupe is a duplicate-finding system for very, very large data
8269 // structures--large enough that sorting is too slow, but not so large
8270 // that we can't keep all the data in memory. using it works as follows:
8271 //
8272 // 1. create an stb_dupe:
8273 // provide a hash function
8274 // provide an equality function
8275 // provide an estimate for the size
8276 // optionally provide a comparison function
8277 //
8278 // 2. traverse your data, 'adding' pointers to the stb_dupe
8279 //
8280 // 3. finish and ask for duplicates
8281 //
8282 // the stb_dupe will discard its intermediate data and build
8283 // a collection of sorted lists of duplicates, with non-duplicate
8284 // entries omitted entirely
8285 //
8286 //
8287 // Implementation strategy:
8288 //
8289 // while collecting the N items, we keep a hash table of approximate
8290 // size sqrt(N). (if you tell use the N up front, the hash table is
8291 // just that size exactly)
8292 //
8293 // each entry in the hash table is just an stb__arr of pointers (no need
8294 // to use stb_ps, because we don't need to delete from these)
8295 //
8296 // for step 3, for each entry in the hash table, we apply stb_dupe to it
8297 // recursively. once the size gets small enough (or doesn't decrease
8298 // significantly), we switch to either using qsort() on the comparison
8299 // function, or else we just do the icky N^2 gather
8300
8301
8302 typedef struct stb_dupe stb_dupe;
8303
8304 typedef int (*stb_compare_func)(void *a, void *b);
8305 typedef int (*stb_hash_func)(void *a, unsigned int seed);
8306
8307 STB_EXTERN void stb_dupe_free(stb_dupe *sd);
8308 STB_EXTERN stb_dupe *stb_dupe_create(stb_hash_func hash,
8309 stb_compare_func eq, int size, stb_compare_func ineq);
8310 STB_EXTERN void stb_dupe_add(stb_dupe *sd, void *item);
8311 STB_EXTERN void stb_dupe_finish(stb_dupe *sd);
8312 STB_EXTERN int stb_dupe_numsets(stb_dupe *sd);
8313 STB_EXTERN void **stb_dupe_set(stb_dupe *sd, int num);
8314 STB_EXTERN int stb_dupe_set_count(stb_dupe *sd, int num);
8315
8316 struct stb_dupe
8317 {
8318 void ***hash_table;
8319 int hash_size;
8320 int size_log2;
8321 int population;
8322
8323 int hash_shift;
8324 stb_hash_func hash;
8325
8326 stb_compare_func eq;
8327 stb_compare_func ineq;
8328
8329 void ***dupes;
8330 };
8331
8332 #ifdef STB_DEFINE
8333
8334 int stb_dupe_numsets(stb_dupe *sd)
8335 {
8336 assert(sd->hash_table == NULL);
8337 return stb_arr_len(sd->dupes);
8338 }
8339
8340 void **stb_dupe_set(stb_dupe *sd, int num)
8341 {
8342 assert(sd->hash_table == NULL);
8343 return sd->dupes[num];
8344 }
8345
8346 int stb_dupe_set_count(stb_dupe *sd, int num)
8347 {
8348 assert(sd->hash_table == NULL);
8349 return stb_arr_len(sd->dupes[num]);
8350 }
8351
8352 stb_dupe *stb_dupe_create(stb_hash_func hash, stb_compare_func eq, int size,
8353 stb_compare_func ineq)
8354 {
8355 int i, hsize;
8356 stb_dupe *sd = (stb_dupe *) malloc(sizeof(*sd));
8357
8358 sd->size_log2 = 4;
8359 hsize = 1 << sd->size_log2;
8360 while (hsize * hsize < size) {
8361 ++sd->size_log2;
8362 hsize *= 2;
8363 }
8364
8365 sd->hash = hash;
8366 sd->eq = eq;
8367 sd->ineq = ineq;
8368 sd->hash_shift = 0;
8369
8370 sd->population = 0;
8371 sd->hash_size = hsize;
8372 sd->hash_table = (void ***) malloc(sizeof(*sd->hash_table) * hsize);
8373 for (i=0; i < hsize; ++i)
8374 sd->hash_table[i] = NULL;
8375
8376 sd->dupes = NULL;
8377
8378 return sd;
8379 }
8380
8381 void stb_dupe_add(stb_dupe *sd, void *item)
8382 {
8383 stb_uint32 hash = sd->hash(item, sd->hash_shift);
8384 int z = hash & (sd->hash_size-1);
8385 stb_arr_push(sd->hash_table[z], item);
8386 ++sd->population;
8387 }
8388
8389 void stb_dupe_free(stb_dupe *sd)
8390 {
8391 int i;
8392 for (i=0; i < stb_arr_len(sd->dupes); ++i)
8393 if (sd->dupes[i])
8394 stb_arr_free(sd->dupes[i]);
8395 stb_arr_free(sd->dupes);
8396 free(sd);
8397 }
8398
8399 static stb_compare_func stb__compare;
8400
8401 static int stb__dupe_compare(const void *a, const void *b)
8402 {
8403 void *p = *(void **) a;
8404 void *q = *(void **) b;
8405
8406 return stb__compare(p,q);
8407 }
8408
8409 void stb_dupe_finish(stb_dupe *sd)
8410 {
8411 int i,j,k;
8412 assert(sd->dupes == NULL);
8413 for (i=0; i < sd->hash_size; ++i) {
8414 void ** list = sd->hash_table[i];
8415 if (list != NULL) {
8416 int n = stb_arr_len(list);
8417 // @TODO: measure to find good numbers instead of just making them up!
8418 int thresh = (sd->ineq ? 200 : 20);
8419 // if n is large enough to be worth it, and n is smaller than
8420 // before (so we can guarantee we'll use a smaller hash table);
8421 // and there are enough hash bits left, assuming full 32-bit hash
8422 if (n > thresh && n < (sd->population >> 3) && sd->hash_shift + sd->size_log2*2 < 32) {
8423
8424 // recursively process this row using stb_dupe, O(N log log N)
8425
8426 stb_dupe *d = stb_dupe_create(sd->hash, sd->eq, n, sd->ineq);
8427 d->hash_shift = stb_randLCG_explicit(sd->hash_shift);
8428 for (j=0; j < n; ++j)
8429 stb_dupe_add(d, list[j]);
8430 stb_arr_free(sd->hash_table[i]);
8431 stb_dupe_finish(d);
8432 for (j=0; j < stb_arr_len(d->dupes); ++j) {
8433 stb_arr_push(sd->dupes, d->dupes[j]);
8434 d->dupes[j] = NULL; // take over ownership
8435 }
8436 stb_dupe_free(d);
8437
8438 } else if (sd->ineq) {
8439
8440 // process this row using qsort(), O(N log N)
8441 stb__compare = sd->ineq;
8442 qsort(list, n, sizeof(list[0]), stb__dupe_compare);
8443
8444 // find equal subsequences of the list
8445 for (j=0; j < n-1; ) {
8446 // find a subsequence from j..k
8447 for (k=j; k < n; ++k)
8448 // only use ineq so eq can be left undefined
8449 if (sd->ineq(list[j], list[k]))
8450 break;
8451 // k is the first one not in the subsequence
8452 if (k-j > 1) {
8453 void **mylist = NULL;
8454 stb_arr_setlen(mylist, k-j);
8455 memcpy(mylist, list+j, sizeof(list[j]) * (k-j));
8456 stb_arr_push(sd->dupes, mylist);
8457 }
8458 j = k;
8459 }
8460 stb_arr_free(sd->hash_table[i]);
8461 } else {
8462
8463 // process this row using eq(), O(N^2)
8464 for (j=0; j < n; ++j) {
8465 if (list[j] != NULL) {
8466 void **output = NULL;
8467 for (k=j+1; k < n; ++k) {
8468 if (sd->eq(list[j], list[k])) {
8469 if (output == NULL)
8470 stb_arr_push(output, list[j]);
8471 stb_arr_push(output, list[k]);
8472 list[k] = NULL;
8473 }
8474 }
8475 list[j] = NULL;
8476 if (output)
8477 stb_arr_push(sd->dupes, output);
8478 }
8479 }
8480 stb_arr_free(sd->hash_table[i]);
8481 }
8482 }
8483 }
8484 free(sd->hash_table);
8485 sd->hash_table = NULL;
8486 }
8487 #endif
8488
8489 //////////////////////////////////////////////////////////////////////////////
8490 //
8491 // templatized Sort routine
8492 //
8493 // This is an attempt to implement a templated sorting algorithm.
8494 // To use it, you have to explicitly instantiate it as a _function_,
8495 // then you call that function. This allows the comparison to be inlined,
8496 // giving the sort similar performance to C++ sorts.
8497 //
8498 // It implements quicksort with three-way-median partitioning (generally
8499 // well-behaved), with a final insertion sort pass.
8500 //
8501 // When you define the compare expression, you should assume you have
8502 // elements of your array pointed to by 'a' and 'b', and perform the comparison
8503 // on those. OR you can use one or more statements; first say '0;', then
8504 // write whatever code you want, and compute the result into a variable 'c'.
8505
8506 #define stb_declare_sort(FUNCNAME, TYPE) \
8507 void FUNCNAME(TYPE *p, int n)
8508 #define stb_define_sort(FUNCNAME,TYPE,COMPARE) \
8509 stb__define_sort( void, FUNCNAME,TYPE,COMPARE)
8510 #define stb_define_sort_static(FUNCNAME,TYPE,COMPARE) \
8511 stb__define_sort(static void, FUNCNAME,TYPE,COMPARE)
8512
8513 #define stb__define_sort(MODE, FUNCNAME, TYPE, COMPARE) \
8514 \
8515 static void STB_(FUNCNAME,_ins_sort)(TYPE *p, int n) \
8516 { \
8517 int i,j; \
8518 for (i=1; i < n; ++i) { \
8519 TYPE t = p[i], *a = &t; \
8520 j = i; \
8521 while (j > 0) { \
8522 TYPE *b = &p[j-1]; \
8523 int c = COMPARE; \
8524 if (!c) break; \
8525 p[j] = p[j-1]; \
8526 --j; \
8527 } \
8528 if (i != j) \
8529 p[j] = t; \
8530 } \
8531 } \
8532 \
8533 static void STB_(FUNCNAME,_quicksort)(TYPE *p, int n) \
8534 { \
8535 /* threshhold for transitioning to insertion sort */ \
8536 while (n > 12) { \
8537 TYPE *a,*b,t; \
8538 int c01,c12,c,m,i,j; \
8539 \
8540 /* compute median of three */ \
8541 m = n >> 1; \
8542 a = &p[0]; \
8543 b = &p[m]; \
8544 c = COMPARE; \
8545 c01 = c; \
8546 a = &p[m]; \
8547 b = &p[n-1]; \
8548 c = COMPARE; \
8549 c12 = c; \
8550 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ \
8551 if (c01 != c12) { \
8552 /* otherwise, we'll need to swap something else to middle */ \
8553 int z; \
8554 a = &p[0]; \
8555 b = &p[n-1]; \
8556 c = COMPARE; \
8557 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ \
8558 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ \
8559 z = (c == c12) ? 0 : n-1; \
8560 t = p[z]; \
8561 p[z] = p[m]; \
8562 p[m] = t; \
8563 } \
8564 /* now p[m] is the median-of-three */ \
8565 /* swap it to the beginning so it won't move around */ \
8566 t = p[0]; \
8567 p[0] = p[m]; \
8568 p[m] = t; \
8569 \
8570 /* partition loop */ \
8571 i=1; \
8572 j=n-1; \
8573 for(;;) { \
8574 /* handling of equality is crucial here */ \
8575 /* for sentinels & efficiency with duplicates */ \
8576 b = &p[0]; \
8577 for (;;++i) { \
8578 a=&p[i]; \
8579 c = COMPARE; \
8580 if (!c) break; \
8581 } \
8582 a = &p[0]; \
8583 for (;;--j) { \
8584 b=&p[j]; \
8585 c = COMPARE; \
8586 if (!c) break; \
8587 } \
8588 /* make sure we haven't crossed */ \
8589 if (i >= j) break; \
8590 t = p[i]; \
8591 p[i] = p[j]; \
8592 p[j] = t; \
8593 \
8594 ++i; \
8595 --j; \
8596 } \
8597 /* recurse on smaller side, iterate on larger */ \
8598 if (j < (n-i)) { \
8599 STB_(FUNCNAME,_quicksort)(p,j); \
8600 p = p+i; \
8601 n = n-i; \
8602 } else { \
8603 STB_(FUNCNAME,_quicksort)(p+i, n-i); \
8604 n = j; \
8605 } \
8606 } \
8607 } \
8608 \
8609 MODE FUNCNAME(TYPE *p, int n) \
8610 { \
8611 STB_(FUNCNAME, _quicksort)(p, n); \
8612 STB_(FUNCNAME, _ins_sort)(p, n); \
8613 } \
8614
8615
8616 //////////////////////////////////////////////////////////////////////////////
8617 //
8618 // stb_bitset an array of booleans indexed by integers
8619 //
8620
8621 typedef stb_uint32 stb_bitset;
8622
8623 STB_EXTERN stb_bitset *stb_bitset_new(int value, int len);
8624
8625 #define stb_bitset_clearall(arr,len) (memset(arr, 0, 4 * (len)))
8626 #define stb_bitset_setall(arr,len) (memset(arr, 255, 4 * (len)))
8627
8628 #define stb_bitset_setbit(arr,n) ((arr)[(n) >> 5] |= (1 << (n & 31)))
8629 #define stb_bitset_clearbit(arr,n) ((arr)[(n) >> 5] &= ~(1 << (n & 31)))
8630 #define stb_bitset_testbit(arr,n) ((arr)[(n) >> 5] & (1 << (n & 31)))
8631
8632 STB_EXTERN stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len);
8633
8634 STB_EXTERN int *stb_bitset_getlist(stb_bitset *out, int start, int end);
8635
8636 STB_EXTERN int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len);
8637 STB_EXTERN int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len);
8638 STB_EXTERN int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len);
8639 STB_EXTERN int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len);
8640 STB_EXTERN int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len);
8641
8642 #ifdef STB_DEFINE
8643 int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len)
8644 {
8645 int i;
8646 for (i=0; i < len; ++i)
8647 if (p0[i] != p1[i]) return 0;
8648 return 1;
8649 }
8650
8651 int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len)
8652 {
8653 int i;
8654 for (i=0; i < len; ++i)
8655 if (p0[i] & p1[i]) return 0;
8656 return 1;
8657 }
8658
8659 int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len)
8660 {
8661 int i;
8662 for (i=0; i < len; ++i)
8663 if ((p0[i] | p1[i]) != 0xffffffff) return 0;
8664 return 1;
8665 }
8666
8667 int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len)
8668 {
8669 int i;
8670 for (i=0; i < len; ++i)
8671 if ((bigger[i] & smaller[i]) != smaller[i]) return 0;
8672 return 1;
8673 }
8674
8675 stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len)
8676 {
8677 int i;
8678 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8679 for (i=0; i < len; ++i) d[i] = p0[i] | p1[i];
8680 return d;
8681 }
8682
8683 int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len)
8684 {
8685 int i, changed=0;
8686 for (i=0; i < len; ++i) {
8687 stb_bitset d = p0[i] | p1[i];
8688 if (d != p0[i]) {
8689 p0[i] = d;
8690 changed = 1;
8691 }
8692 }
8693 return changed;
8694 }
8695
8696 stb_bitset *stb_bitset_new(int value, int len)
8697 {
8698 int i;
8699 stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
8700 if (value) value = 0xffffffff;
8701 for (i=0; i < len; ++i) d[i] = value;
8702 return d;
8703 }
8704
8705 int *stb_bitset_getlist(stb_bitset *out, int start, int end)
8706 {
8707 int *list = NULL;
8708 int i;
8709 for (i=start; i < end; ++i)
8710 if (stb_bitset_testbit(out, i))
8711 stb_arr_push(list, i);
8712 return list;
8713 }
8714 #endif
8715
8716 //////////////////////////////////////////////////////////////////////////////
8717 //
8718 // stb_wordwrap quality word-wrapping for fixed-width fonts
8719 //
8720
8721 STB_EXTERN int stb_wordwrap(int *pairs, int pair_max, int count, char *str);
8722 STB_EXTERN int *stb_wordwrapalloc(int count, char *str);
8723
8724 #ifdef STB_DEFINE
8725
8726 int stb_wordwrap(int *pairs, int pair_max, int count, char *str)
8727 {
8728 int n=0,i=0, start=0,nonwhite=0;
8729 if (pairs == NULL) pair_max = 0x7ffffff0;
8730 else pair_max *= 2;
8731 // parse
8732 for(;;) {
8733 int s=i; // first whitespace char; last nonwhite+1
8734 int w; // word start
8735 // accept whitespace
8736 while (isspace(str[i])) {
8737 if (str[i] == '\n' || str[i] == '\r') {
8738 if (str[i] + str[i+1] == '\n' + '\r') ++i;
8739 if (n >= pair_max) return -1;
8740 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8741 n += 2;
8742 nonwhite=0;
8743 start = i+1;
8744 s = start;
8745 }
8746 ++i;
8747 }
8748 if (i >= start+count) {
8749 // we've gone off the end using whitespace
8750 if (nonwhite) {
8751 if (n >= pair_max) return -1;
8752 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8753 n += 2;
8754 start = s = i;
8755 nonwhite=0;
8756 } else {
8757 // output all the whitespace
8758 while (i >= start+count) {
8759 if (n >= pair_max) return -1;
8760 if (pairs) pairs[n] = start, pairs[n+1] = count;
8761 n += 2;
8762 start += count;
8763 }
8764 s = start;
8765 }
8766 }
8767
8768 if (str[i] == 0) break;
8769 // now scan out a word and see if it fits
8770 w = i;
8771 while (str[i] && !isspace(str[i])) {
8772 ++i;
8773 }
8774 // wrapped?
8775 if (i > start + count) {
8776 // huge?
8777 if (i-s <= count) {
8778 if (n >= pair_max) return -1;
8779 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8780 n += 2;
8781 start = w;
8782 } else {
8783 // This word is longer than one line. If we wrap it onto N lines
8784 // there are leftover chars. do those chars fit on the cur line?
8785 // But if we have leading whitespace, we force it to start here.
8786 if ((w-start) + ((i-w) % count) <= count || !nonwhite) {
8787 // output a full line
8788 if (n >= pair_max) return -1;
8789 if (pairs) pairs[n] = start, pairs[n+1] = count;
8790 n += 2;
8791 start += count;
8792 w = start;
8793 } else {
8794 // output a partial line, trimming trailing whitespace
8795 if (s != start) {
8796 if (n >= pair_max) return -1;
8797 if (pairs) pairs[n] = start, pairs[n+1] = s-start;
8798 n += 2;
8799 start = w;
8800 }
8801 }
8802 // now output full lines as needed
8803 while (start + count <= i) {
8804 if (n >= pair_max) return -1;
8805 if (pairs) pairs[n] = start, pairs[n+1] = count;
8806 n += 2;
8807 start += count;
8808 }
8809 }
8810 }
8811 nonwhite=1;
8812 }
8813 if (start < i) {
8814 if (n >= pair_max) return -1;
8815 if (pairs) pairs[n] = start, pairs[n+1] = i-start;
8816 n += 2;
8817 }
8818 return n>>1;
8819 }
8820
8821 int *stb_wordwrapalloc(int count, char *str)
8822 {
8823 int n = stb_wordwrap(NULL,0,count,str);
8824 int *z = NULL;
8825 stb_arr_setlen(z, n*2);
8826 stb_wordwrap(z, n, count, str);
8827 return z;
8828 }
8829 #endif
8830
8831
8832 //////////////////////////////////////////////////////////////////////////////
8833 //
8834 // stb_match: wildcards and regexping
8835 //
8836
8837 STB_EXTERN int stb_wildmatch (char *expr, char *candidate);
8838 STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
8839 STB_EXTERN int stb_wildfind (char *expr, char *candidate);
8840 STB_EXTERN int stb_wildfindi (char *expr, char *candidate);
8841
8842 STB_EXTERN int stb_regex(char *regex, char *candidate);
8843
8844 typedef struct stb_matcher stb_matcher;
8845
8846 STB_EXTERN stb_matcher *stb_regex_matcher(char *regex);
8847 STB_EXTERN int stb_matcher_match(stb_matcher *m, char *str);
8848 STB_EXTERN int stb_matcher_find(stb_matcher *m, char *str);
8849 STB_EXTERN void stb_matcher_free(stb_matcher *f);
8850
8851 STB_EXTERN stb_matcher *stb_lex_matcher(void);
8852 STB_EXTERN int stb_lex_item(stb_matcher *m, char *str, int result);
8853 STB_EXTERN int stb_lex_item_wild(stb_matcher *matcher, char *regex, int result);
8854 STB_EXTERN int stb_lex(stb_matcher *m, char *str, int *len);
8855
8856
8857
8858 #ifdef STB_DEFINE
8859
8860 static int stb__match_qstring(char *candidate, char *qstring, int qlen, int insensitive)
8861 {
8862 int i;
8863 if (insensitive) {
8864 for (i=0; i < qlen; ++i)
8865 if (qstring[i] == '?') {
8866 if (!candidate[i]) return 0;
8867 } else
8868 if (tolower(qstring[i]) != tolower(candidate[i]))
8869 return 0;
8870 } else {
8871 for (i=0; i < qlen; ++i)
8872 if (qstring[i] == '?') {
8873 if (!candidate[i]) return 0;
8874 } else
8875 if (qstring[i] != candidate[i])
8876 return 0;
8877 }
8878 return 1;
8879 }
8880
8881 static int stb__find_qstring(char *candidate, char *qstring, int qlen, int insensitive)
8882 {
8883 char c;
8884
8885 int offset=0;
8886 while (*qstring == '?') {
8887 ++qstring;
8888 --qlen;
8889 ++candidate;
8890 if (qlen == 0) return 0;
8891 if (*candidate == 0) return -1;
8892 }
8893
8894 c = *qstring++;
8895 --qlen;
8896 if (insensitive) c = tolower(c);
8897
8898 while (candidate[offset]) {
8899 if (c == (insensitive ? tolower(candidate[offset]) : candidate[offset]))
8900 if (stb__match_qstring(candidate+offset+1, qstring, qlen, insensitive))
8901 return offset;
8902 ++offset;
8903 }
8904
8905 return -1;
8906 }
8907
8908 int stb__wildmatch_raw2(char *expr, char *candidate, int search, int insensitive)
8909 {
8910 int where=0;
8911 int start = -1;
8912
8913 if (!search) {
8914 // parse to first '*'
8915 if (*expr != '*')
8916 start = 0;
8917 while (*expr != '*') {
8918 if (!*expr)
8919 return *candidate == 0 ? 0 : -1;
8920 if (*expr == '?') {
8921 if (!*candidate) return -1;
8922 } else {
8923 if (insensitive) {
8924 if (tolower(*candidate) != tolower(*expr))
8925 return -1;
8926 } else
8927 if (*candidate != *expr)
8928 return -1;
8929 }
8930 ++candidate, ++expr, ++where;
8931 }
8932 } else {
8933 // 0-length search string
8934 if (!*expr)
8935 return 0;
8936 }
8937
8938 assert(search || *expr == '*');
8939 if (!search)
8940 ++expr;
8941
8942 // implicit '*' at this point
8943
8944 while (*expr) {
8945 int o=0;
8946 // combine redundant * characters
8947 while (expr[0] == '*') ++expr;
8948
8949 // ok, at this point, expr[-1] == '*',
8950 // and expr[0] != '*'
8951
8952 if (!expr[0]) return start >= 0 ? start : 0;
8953
8954 // now find next '*'
8955 o = 0;
8956 while (expr[o] != '*') {
8957 if (expr[o] == 0)
8958 break;
8959 ++o;
8960 }
8961 // if no '*', scan to end, then match at end
8962 if (expr[o] == 0 && !search) {
8963 int z;
8964 for (z=0; z < o; ++z)
8965 if (candidate[z] == 0)
8966 return -1;
8967 while (candidate[z])
8968 ++z;
8969 // ok, now check if they match
8970 if (stb__match_qstring(candidate+z-o, expr, o, insensitive))
8971 return start >= 0 ? start : 0;
8972 return -1;
8973 } else {
8974 // if yes '*', then do stb__find_qmatch on the intervening chars
8975 int n = stb__find_qstring(candidate, expr, o, insensitive);
8976 if (n < 0)
8977 return -1;
8978 if (start < 0)
8979 start = where + n;
8980 expr += o;
8981 candidate += n+o;
8982 }
8983
8984 if (*expr == 0) {
8985 assert(search);
8986 return start;
8987 }
8988
8989 assert(*expr == '*');
8990 ++expr;
8991 }
8992
8993 return start >= 0 ? start : 0;
8994 }
8995
8996 int stb__wildmatch_raw(char *expr, char *candidate, int search, int insensitive)
8997 {
8998 char buffer[256];
8999 // handle multiple search strings
9000 char *s = strchr(expr, ';');
9001 char *last = expr;
9002 while (s) {
9003 int z;
9004 // need to allow for non-writeable strings... assume they're small
9005 if (s - last < 256) {
9006 stb_strncpy(buffer, last, s-last+1);
9007 z = stb__wildmatch_raw2(buffer, candidate, search, insensitive);
9008 } else {
9009 *s = 0;
9010 z = stb__wildmatch_raw2(last, candidate, search, insensitive);
9011 *s = ';';
9012 }
9013 if (z >= 0) return z;
9014 last = s+1;
9015 s = strchr(last, ';');
9016 }
9017 return stb__wildmatch_raw2(last, candidate, search, insensitive);
9018 }
9019
9020 int stb_wildmatch(char *expr, char *candidate)
9021 {
9022 return stb__wildmatch_raw(expr, candidate, 0,0) >= 0;
9023 }
9024
9025 int stb_wildmatchi(char *expr, char *candidate)
9026 {
9027 return stb__wildmatch_raw(expr, candidate, 0,1) >= 0;
9028 }
9029
9030 int stb_wildfind(char *expr, char *candidate)
9031 {
9032 return stb__wildmatch_raw(expr, candidate, 1,0);
9033 }
9034
9035 int stb_wildfindi(char *expr, char *candidate)
9036 {
9037 return stb__wildmatch_raw(expr, candidate, 1,1);
9038 }
9039
9040 typedef struct
9041 {
9042 stb_int16 transition[256];
9043 } stb_dfa;
9044
9045 // an NFA node represents a state you're in; it then has
9046 // an arbitrary number of edges dangling off of it
9047 // note this isn't utf8-y
9048 typedef struct
9049 {
9050 stb_int16 match; // character/set to match
9051 stb_uint16 node; // output node to go to
9052 } stb_nfa_edge;
9053
9054 typedef struct
9055 {
9056 stb_int16 goal; // does reaching this win the prize?
9057 stb_uint8 active; // is this in the active list
9058 stb_nfa_edge *out;
9059 stb_uint16 *eps; // list of epsilon closures
9060 } stb_nfa_node;
9061
9062 #define STB__DFA_UNDEF -1
9063 #define STB__DFA_GOAL -2
9064 #define STB__DFA_END -3
9065 #define STB__DFA_MGOAL -4
9066 #define STB__DFA_VALID 0
9067
9068 #define STB__NFA_STOP_GOAL -1
9069
9070 // compiled regexp
9071 struct stb_matcher
9072 {
9073 stb_uint16 start_node;
9074 stb_int16 dfa_start;
9075 stb_uint32 *charset;
9076 int num_charset;
9077 int match_start;
9078 stb_nfa_node *nodes;
9079 int does_lex;
9080
9081 // dfa matcher
9082 stb_dfa * dfa;
9083 stb_uint32 * dfa_mapping;
9084 stb_int16 * dfa_result;
9085 int num_words_per_dfa;
9086 };
9087
9088 static int stb__add_node(stb_matcher *matcher)
9089 {
9090 stb_nfa_node z;
9091 z.active = 0;
9092 z.eps = 0;
9093 z.goal = 0;
9094 z.out = 0;
9095 stb_arr_push(matcher->nodes, z);
9096 return stb_arr_len(matcher->nodes)-1;
9097 }
9098
9099 static void stb__add_epsilon(stb_matcher *matcher, int from, int to)
9100 {
9101 assert(from != to);
9102 if (matcher->nodes[from].eps == NULL)
9103 stb_arr_malloc((void **) &matcher->nodes[from].eps, matcher);
9104 stb_arr_push(matcher->nodes[from].eps, to);
9105 }
9106
9107 static void stb__add_edge(stb_matcher *matcher, int from, int to, int type)
9108 {
9109 stb_nfa_edge z = { type, to };
9110 if (matcher->nodes[from].out == NULL)
9111 stb_arr_malloc((void **) &matcher->nodes[from].out, matcher);
9112 stb_arr_push(matcher->nodes[from].out, z);
9113 }
9114
9115 static char *stb__reg_parse_alt(stb_matcher *m, int s, char *r, stb_uint16 *e);
9116 static char *stb__reg_parse(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9117 {
9118 int n;
9119 int last_start = -1;
9120 stb_uint16 last_end = start;
9121
9122 while (*regex) {
9123 switch (*regex) {
9124 case '(':
9125 last_start = last_end;
9126 regex = stb__reg_parse_alt(matcher, last_end, regex+1, &last_end);
9127 if (regex == NULL || *regex != ')')
9128 return NULL;
9129 ++regex;
9130 break;
9131
9132 case '|':
9133 case ')':
9134 *end = last_end;
9135 return regex;
9136
9137 case '?':
9138 if (last_start < 0) return NULL;
9139 stb__add_epsilon(matcher, last_start, last_end);
9140 ++regex;
9141 break;
9142
9143 case '*':
9144 if (last_start < 0) return NULL;
9145 stb__add_epsilon(matcher, last_start, last_end);
9146
9147 // fall through
9148
9149 case '+':
9150 if (last_start < 0) return NULL;
9151 stb__add_epsilon(matcher, last_end, last_start);
9152 // prevent links back to last_end from chaining to last_start
9153 n = stb__add_node(matcher);
9154 stb__add_epsilon(matcher, last_end, n);
9155 last_end = n;
9156 ++regex;
9157 break;
9158
9159 case '{': // not supported!
9160 // @TODO: given {n,m}, clone last_start to last_end m times,
9161 // and include epsilons from start to first m-n blocks
9162 return NULL;
9163
9164 case '\\':
9165 ++regex;
9166 if (!*regex) return NULL;
9167
9168 // fallthrough
9169 default: // match exactly this character
9170 n = stb__add_node(matcher);
9171 stb__add_edge(matcher, last_end, n, *regex);
9172 last_start = last_end;
9173 last_end = n;
9174 ++regex;
9175 break;
9176
9177 case '$':
9178 n = stb__add_node(matcher);
9179 stb__add_edge(matcher, last_end, n, '\n');
9180 last_start = last_end;
9181 last_end = n;
9182 ++regex;
9183 break;
9184
9185 case '.':
9186 n = stb__add_node(matcher);
9187 stb__add_edge(matcher, last_end, n, -1);
9188 last_start = last_end;
9189 last_end = n;
9190 ++regex;
9191 break;
9192
9193 case '[': {
9194 stb_uint8 flags[256];
9195 int invert = 0,z;
9196 ++regex;
9197 if (matcher->num_charset == 0) {
9198 matcher->charset = (stb_uint *) stb_malloc(matcher, sizeof(*matcher->charset) * 256);
9199 memset(matcher->charset, 0, sizeof(*matcher->charset) * 256);
9200 }
9201
9202 memset(flags,0,sizeof(flags));
9203
9204 // leading ^ is special
9205 if (*regex == '^')
9206 ++regex, invert = 1;
9207
9208 // leading ] is special
9209 if (*regex == ']') {
9210 flags[']'] = 1;
9211 ++regex;
9212 }
9213 while (*regex != ']') {
9214 stb_uint a;
9215 if (!*regex) return NULL;
9216 a = *regex++;
9217 if (regex[0] == '-' && regex[1] != ']') {
9218 stb_uint i,b = regex[1];
9219 regex += 2;
9220 if (b == 0) return NULL;
9221 if (a > b) return NULL;
9222 for (i=a; i <= b; ++i)
9223 flags[i] = 1;
9224 } else
9225 flags[a] = 1;
9226 }
9227 ++regex;
9228 if (invert) {
9229 int i;
9230 for (i=0; i < 256; ++i)
9231 flags[i] = 1-flags[i];
9232 }
9233
9234 // now check if any existing charset matches
9235 for (z=0; z < matcher->num_charset; ++z) {
9236 int i, k[2] = { 0, 1 << z};
9237 for (i=0; i < 256; ++i) {
9238 unsigned int f = k[flags[i]];
9239 if ((matcher->charset[i] & k[1]) != f)
9240 break;
9241 }
9242 if (i == 256) break;
9243 }
9244
9245 if (z == matcher->num_charset) {
9246 int i;
9247 ++matcher->num_charset;
9248 if (matcher->num_charset > 32) {
9249 assert(0); /* NOTREACHED */
9250 return NULL; // too many charsets, oops
9251 }
9252 for (i=0; i < 256; ++i)
9253 if (flags[i])
9254 matcher->charset[i] |= (1 << z);
9255 }
9256
9257 n = stb__add_node(matcher);
9258 stb__add_edge(matcher, last_end, n, -2 - z);
9259 last_start = last_end;
9260 last_end = n;
9261 break;
9262 }
9263 }
9264 }
9265 *end = last_end;
9266 return regex;
9267 }
9268
9269 static char *stb__reg_parse_alt(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
9270 {
9271 stb_uint16 last_end = start;
9272 stb_uint16 main_end;
9273
9274 int head, tail;
9275
9276 head = stb__add_node(matcher);
9277 stb__add_epsilon(matcher, start, head);
9278
9279 regex = stb__reg_parse(matcher, head, regex, &last_end);
9280 if (regex == NULL) return NULL;
9281 if (*regex == 0 || *regex == ')') {
9282 *end = last_end;
9283 return regex;
9284 }
9285
9286 main_end = last_end;
9287 tail = stb__add_node(matcher);
9288
9289 stb__add_epsilon(matcher, last_end, tail);
9290
9291 // start alternatives from the same starting node; use epsilon
9292 // transitions to combine their endings
9293 while(*regex && *regex != ')') {
9294 assert(*regex == '|');
9295 head = stb__add_node(matcher);
9296 stb__add_epsilon(matcher, start, head);
9297 regex = stb__reg_parse(matcher, head, regex+1, &last_end);
9298 if (regex == NULL)
9299 return NULL;
9300 stb__add_epsilon(matcher, last_end, tail);
9301 }
9302
9303 *end = tail;
9304 return regex;
9305 }
9306
9307 static char *stb__wild_parse(stb_matcher *matcher, int start, char *str, stb_uint16 *end)
9308 {
9309 int n;
9310 stb_uint16 last_end;
9311
9312 last_end = stb__add_node(matcher);
9313 stb__add_epsilon(matcher, start, last_end);
9314
9315 while (*str) {
9316 switch (*str) {
9317 // fallthrough
9318 default: // match exactly this character
9319 n = stb__add_node(matcher);
9320 if (toupper(*str) == tolower(*str)) {
9321 stb__add_edge(matcher, last_end, n, *str);
9322 } else {
9323 stb__add_edge(matcher, last_end, n, tolower(*str));
9324 stb__add_edge(matcher, last_end, n, toupper(*str));
9325 }
9326 last_end = n;
9327 ++str;
9328 break;
9329
9330 case '?':
9331 n = stb__add_node(matcher);
9332 stb__add_edge(matcher, last_end, n, -1);
9333 last_end = n;
9334 ++str;
9335 break;
9336
9337 case '*':
9338 n = stb__add_node(matcher);
9339 stb__add_edge(matcher, last_end, n, -1);
9340 stb__add_epsilon(matcher, last_end, n);
9341 stb__add_epsilon(matcher, n, last_end);
9342 last_end = n;
9343 ++str;
9344 break;
9345 }
9346 }
9347
9348 // now require end of string to match
9349 n = stb__add_node(matcher);
9350 stb__add_edge(matcher, last_end, n, 0);
9351 last_end = n;
9352
9353 *end = last_end;
9354 return str;
9355 }
9356
9357 static int stb__opt(stb_matcher *m, int n)
9358 {
9359 for(;;) {
9360 stb_nfa_node *p = &m->nodes[n];
9361 if (p->goal) return n;
9362 if (stb_arr_len(p->out)) return n;
9363 if (stb_arr_len(p->eps) != 1) return n;
9364 n = p->eps[0];
9365 }
9366 }
9367
9368 static void stb__optimize(stb_matcher *m)
9369 {
9370 // if the target of any edge is a node with exactly
9371 // one out-epsilon, shorten it
9372 int i,j;
9373 for (i=0; i < stb_arr_len(m->nodes); ++i) {
9374 stb_nfa_node *p = &m->nodes[i];
9375 for (j=0; j < stb_arr_len(p->out); ++j)
9376 p->out[j].node = stb__opt(m,p->out[j].node);
9377 for (j=0; j < stb_arr_len(p->eps); ++j)
9378 p->eps[j] = stb__opt(m,p->eps[j] );
9379 }
9380 m->start_node = stb__opt(m,m->start_node);
9381 }
9382
9383 void stb_matcher_free(stb_matcher *f)
9384 {
9385 stb_free(f);
9386 }
9387
9388 static stb_matcher *stb__alloc_matcher(void)
9389 {
9390 stb_matcher *matcher = (stb_matcher *) stb_malloc(0,sizeof(*matcher));
9391
9392 matcher->start_node = 0;
9393 stb_arr_malloc((void **) &matcher->nodes, matcher);
9394 matcher->num_charset = 0;
9395 matcher->match_start = 0;
9396 matcher->does_lex = 0;
9397
9398 matcher->dfa_start = STB__DFA_UNDEF;
9399 stb_arr_malloc((void **) &matcher->dfa, matcher);
9400 stb_arr_malloc((void **) &matcher->dfa_mapping, matcher);
9401 stb_arr_malloc((void **) &matcher->dfa_result, matcher);
9402
9403 stb__add_node(matcher);
9404
9405 return matcher;
9406 }
9407
9408 static void stb__lex_reset(stb_matcher *matcher)
9409 {
9410 // flush cached dfa data
9411 stb_arr_setlen(matcher->dfa, 0);
9412 stb_arr_setlen(matcher->dfa_mapping, 0);
9413 stb_arr_setlen(matcher->dfa_result, 0);
9414 matcher->dfa_start = STB__DFA_UNDEF;
9415 }
9416
9417 stb_matcher *stb_regex_matcher(char *regex)
9418 {
9419 char *z;
9420 stb_uint16 end;
9421 stb_matcher *matcher = stb__alloc_matcher();
9422 if (*regex == '^') {
9423 matcher->match_start = 1;
9424 ++regex;
9425 }
9426
9427 z = stb__reg_parse_alt(matcher, matcher->start_node, regex, &end);
9428
9429 if (!z || *z) {
9430 stb_free(matcher);
9431 return NULL;
9432 }
9433
9434 ((matcher->nodes)[(int) end]).goal = STB__NFA_STOP_GOAL;
9435
9436 return matcher;
9437 }
9438
9439 stb_matcher *stb_lex_matcher(void)
9440 {
9441 stb_matcher *matcher = stb__alloc_matcher();
9442
9443 matcher->match_start = 1;
9444 matcher->does_lex = 1;
9445
9446 return matcher;
9447 }
9448
9449 int stb_lex_item(stb_matcher *matcher, char *regex, int result)
9450 {
9451 char *z;
9452 stb_uint16 end;
9453
9454 z = stb__reg_parse_alt(matcher, matcher->start_node, regex, &end);
9455
9456 if (z == NULL)
9457 return 0;
9458
9459 stb__lex_reset(matcher);
9460
9461 matcher->nodes[(int) end].goal = result;
9462 return 1;
9463 }
9464
9465 int stb_lex_item_wild(stb_matcher *matcher, char *regex, int result)
9466 {
9467 char *z;
9468 stb_uint16 end;
9469
9470 z = stb__wild_parse(matcher, matcher->start_node, regex, &end);
9471
9472 if (z == NULL)
9473 return 0;
9474
9475 stb__lex_reset(matcher);
9476
9477 matcher->nodes[(int) end].goal = result;
9478 return 1;
9479 }
9480
9481 static void stb__clear(stb_matcher *m, stb_uint16 *list)
9482 {
9483 int i;
9484 for (i=0; i < stb_arr_len(list); ++i)
9485 m->nodes[(int) list[i]].active = 0;
9486 }
9487
9488 static int stb__clear_goalcheck(stb_matcher *m, stb_uint16 *list)
9489 {
9490 int i, t=0;
9491 for (i=0; i < stb_arr_len(list); ++i) {
9492 t += m->nodes[(int) list[i]].goal;
9493 m->nodes[(int) list[i]].active = 0;
9494 }
9495 return t;
9496 }
9497
9498 static stb_uint16 * stb__add_if_inactive(stb_matcher *m, stb_uint16 *list, int n)
9499 {
9500 if (!m->nodes[n].active) {
9501 stb_arr_push(list, n);
9502 m->nodes[n].active = 1;
9503 }
9504 return list;
9505 }
9506
9507 static stb_uint16 * stb__eps_closure(stb_matcher *m, stb_uint16 *list)
9508 {
9509 int i,n = stb_arr_len(list);
9510
9511 for(i=0; i < n; ++i) {
9512 stb_uint16 *e = m->nodes[(int) list[i]].eps;
9513 if (e) {
9514 int j,k = stb_arr_len(e);
9515 for (j=0; j < k; ++j)
9516 list = stb__add_if_inactive(m, list, e[j]);
9517 n = stb_arr_len(list);
9518 }
9519 }
9520
9521 return list;
9522 }
9523
9524 int stb_matcher_match(stb_matcher *m, char *str)
9525 {
9526 int result = 0;
9527 int i,j,y,z;
9528 stb_uint16 *previous = NULL;
9529 stb_uint16 *current = NULL;
9530 stb_uint16 *temp;
9531
9532 stb_arr_setsize(previous, 4);
9533 stb_arr_setsize(current, 4);
9534
9535 previous = stb__add_if_inactive(m, previous, m->start_node);
9536 previous = stb__eps_closure(m,previous);
9537 stb__clear(m, previous);
9538
9539 while (*str && stb_arr_len(previous)) {
9540 y = stb_arr_len(previous);
9541 for (i=0; i < y; ++i) {
9542 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9543 z = stb_arr_len(n->out);
9544 for (j=0; j < z; ++j) {
9545 if (n->out[j].match >= 0) {
9546 if (n->out[j].match == *str)
9547 current = stb__add_if_inactive(m, current, n->out[j].node);
9548 } else if (n->out[j].match == -1) {
9549 if (*str != '\n')
9550 current = stb__add_if_inactive(m, current, n->out[j].node);
9551 } else if (n->out[j].match < -1) {
9552 int z = -n->out[j].match - 2;
9553 if (m->charset[(stb_uint8) *str] & (1 << z))
9554 current = stb__add_if_inactive(m, current, n->out[j].node);
9555 }
9556 }
9557 }
9558 stb_arr_setlen(previous, 0);
9559
9560 temp = previous;
9561 previous = current;
9562 current = temp;
9563
9564 previous = stb__eps_closure(m,previous);
9565 stb__clear(m, previous);
9566
9567 ++str;
9568 }
9569
9570 // transition to pick up a '$' at the end
9571 y = stb_arr_len(previous);
9572 for (i=0; i < y; ++i)
9573 m->nodes[(int) previous[i]].active = 1;
9574
9575 for (i=0; i < y; ++i) {
9576 stb_nfa_node *n = &m->nodes[(int) previous[i]];
9577 z = stb_arr_len(n->out);
9578 for (j=0; j < z; ++j) {
9579 if (n->out[j].match == '\n')
9580 current = stb__add_if_inactive(m, current, n->out[j].node);
9581 }
9582 }
9583
9584 previous = stb__eps_closure(m,previous);
9585 stb__clear(m, previous);
9586
9587 y = stb_arr_len(previous);
9588 for (i=0; i < y; ++i)
9589 if (m->nodes[(int) previous[i]].goal)
9590 result = 1;
9591
9592 stb_arr_free(previous);
9593 stb_arr_free(current);
9594
9595 return result && *str == 0;
9596 }
9597
9598 stb_int16 stb__get_dfa_node(stb_matcher *m, stb_uint16 *list)
9599 {
9600 stb_uint16 node;
9601 stb_uint32 data[8], *state, *newstate;
9602 int i,j,n;
9603
9604 state = (stb_uint32 *) stb_temp(data, m->num_words_per_dfa * 4);
9605 memset(state, 0, m->num_words_per_dfa*4);
9606
9607 n = stb_arr_len(list);
9608 for (i=0; i < n; ++i) {
9609 int x = list[i];
9610 state[x >> 5] |= 1 << (x & 31);
9611 }
9612
9613 // @TODO use a hash table
9614 n = stb_arr_len(m->dfa_mapping);
9615 i=j=0;
9616 for(; j < n; ++i, j += m->num_words_per_dfa) {
9617 // @TODO special case for <= 32
9618 if (!memcmp(state, m->dfa_mapping + j, m->num_words_per_dfa*4)) {
9619 node = i;
9620 goto done;
9621 }
9622 }
9623
9624 assert(stb_arr_len(m->dfa) == i);
9625 node = i;
9626
9627 newstate = stb_arr_addn(m->dfa_mapping, m->num_words_per_dfa);
9628 memcpy(newstate, state, m->num_words_per_dfa*4);
9629
9630 // set all transitions to 'unknown'
9631 stb_arr_add(m->dfa);
9632 memset(m->dfa[i].transition, -1, sizeof(m->dfa[i].transition));
9633
9634 if (m->does_lex) {
9635 int result = -1;
9636 n = stb_arr_len(list);
9637 for (i=0; i < n; ++i) {
9638 if (m->nodes[(int) list[i]].goal > result)
9639 result = m->nodes[(int) list[i]].goal;
9640 }
9641
9642 stb_arr_push(m->dfa_result, result);
9643 }
9644
9645 done:
9646 stb_tempfree(data, state);
9647 return node;
9648 }
9649
9650 static int stb__matcher_dfa(stb_matcher *m, char *str_c, int *len)
9651 {
9652 stb_uint8 *str = (stb_uint8 *) str_c;
9653 stb_int16 node,prevnode;
9654 stb_dfa *trans;
9655 int match_length = 0;
9656 stb_int16 match_result=0;
9657
9658 if (m->dfa_start == STB__DFA_UNDEF) {
9659 stb_uint16 *list;
9660
9661 m->num_words_per_dfa = (stb_arr_len(m->nodes)+31) >> 5;
9662 stb__optimize(m);
9663
9664 list = stb__add_if_inactive(m, NULL, m->start_node);
9665 list = stb__eps_closure(m,list);
9666 if (m->does_lex) {
9667 m->dfa_start = stb__get_dfa_node(m,list);
9668 stb__clear(m, list);
9669 // DON'T allow start state to be a goal state!
9670 // this allows people to specify regexes that can match 0
9671 // characters without them actually matching (also we don't
9672 // check _before_ advancing anyway
9673 if (m->dfa_start <= STB__DFA_MGOAL)
9674 m->dfa_start = -(m->dfa_start - STB__DFA_MGOAL);
9675 } else {
9676 if (stb__clear_goalcheck(m, list))
9677 m->dfa_start = STB__DFA_GOAL;
9678 else
9679 m->dfa_start = stb__get_dfa_node(m,list);
9680 }
9681 stb_arr_free(list);
9682 }
9683
9684 prevnode = STB__DFA_UNDEF;
9685 node = m->dfa_start;
9686 trans = m->dfa;
9687
9688 if (m->dfa_start == STB__DFA_GOAL)
9689 return 1;
9690
9691 for(;;) {
9692 assert(node >= STB__DFA_VALID);
9693
9694 // fast inner DFA loop; especially if STB__DFA_VALID is 0
9695
9696 do {
9697 prevnode = node;
9698 node = trans[node].transition[*str++];
9699 } while (node >= STB__DFA_VALID);
9700
9701 assert(node >= STB__DFA_MGOAL - stb_arr_len(m->dfa));
9702 assert(node < stb_arr_len(m->dfa));
9703
9704 // special case for lex: need _longest_ match, so notice goal
9705 // state without stopping
9706 if (node <= STB__DFA_MGOAL) {
9707 match_length = str - (stb_uint8 *) str_c;
9708 node = -(node - STB__DFA_MGOAL);
9709 match_result = node;
9710 continue;
9711 }
9712
9713 // slow NFA->DFA conversion
9714
9715 // or we hit the goal or the end of the string, but those
9716 // can only happen once per search...
9717
9718 if (node == STB__DFA_UNDEF) {
9719 // build a list -- @TODO special case <= 32 states
9720 // heck, use a more compact data structure for <= 16 and <= 8 ?!
9721
9722 // @TODO keep states/newstates around instead of reallocating them
9723 stb_uint16 *states = NULL;
9724 stb_uint16 *newstates = NULL;
9725 int i,j,y,z;
9726 stb_uint32 *flags = &m->dfa_mapping[prevnode * m->num_words_per_dfa];
9727 assert(prevnode != STB__DFA_UNDEF);
9728 stb_arr_setsize(states, 4);
9729 stb_arr_setsize(newstates,4);
9730 for (j=0; j < m->num_words_per_dfa; ++j) {
9731 for (i=0; i < 32; ++i) {
9732 if (*flags & (1 << i))
9733 stb_arr_push(states, j*32+i);
9734 }
9735 ++flags;
9736 }
9737 // states is now the states we were in in the previous node;
9738 // so now we can compute what node it transitions to on str[-1]
9739
9740 y = stb_arr_len(states);
9741 for (i=0; i < y; ++i) {
9742 stb_nfa_node *n = &m->nodes[(int) states[i]];
9743 z = stb_arr_len(n->out);
9744 for (j=0; j < z; ++j) {
9745 if (n->out[j].match >= 0) {
9746 if (n->out[j].match == str[-1] || (str[-1] == 0 && n->out[j].match == '\n'))
9747 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9748 } else if (n->out[j].match == -1) {
9749 if (str[-1] != '\n' && str[-1])
9750 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9751 } else if (n->out[j].match < -1) {
9752 int z = -n->out[j].match - 2;
9753 if (m->charset[str[-1]] & (1 << z))
9754 newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
9755 }
9756 }
9757 }
9758 // AND add in the start state!
9759 if (!m->match_start || (str[-1] == '\n' && !m->does_lex))
9760 newstates = stb__add_if_inactive(m, newstates, m->start_node);
9761 // AND epsilon close it
9762 newstates = stb__eps_closure(m, newstates);
9763 // if it's a goal state, then that's all there is to it
9764 if (stb__clear_goalcheck(m, newstates)) {
9765 if (m->does_lex) {
9766 match_length = str - (stb_uint8 *) str_c;
9767 node = stb__get_dfa_node(m,newstates);
9768 match_result = node;
9769 node = -node + STB__DFA_MGOAL;
9770 trans = m->dfa; // could have gotten realloc()ed
9771 } else
9772 node = STB__DFA_GOAL;
9773 } else if (str[-1] == 0 || stb_arr_len(newstates) == 0) {
9774 node = STB__DFA_END;
9775 } else {
9776 node = stb__get_dfa_node(m,newstates);
9777 trans = m->dfa; // could have gotten realloc()ed
9778 }
9779 trans[prevnode].transition[str[-1]] = node;
9780 if (node <= STB__DFA_MGOAL)
9781 node = -(node - STB__DFA_MGOAL);
9782 stb_arr_free(newstates);
9783 stb_arr_free(states);
9784 }
9785
9786 if (node == STB__DFA_GOAL) {
9787 return 1;
9788 }
9789 if (node == STB__DFA_END) {
9790 if (m->does_lex) {
9791 if (match_result) {
9792 if (len) *len = match_length;
9793 return m->dfa_result[(int) match_result];
9794 }
9795 }
9796 return 0;
9797 }
9798
9799 assert(node != STB__DFA_UNDEF);
9800 }
9801 }
9802
9803 int stb_matcher_find(stb_matcher *m, char *str)
9804 {
9805 assert(m->does_lex == 0);
9806 return stb__matcher_dfa(m, str, NULL);
9807 }
9808
9809 int stb_lex(stb_matcher *m, char *str, int *len)
9810 {
9811 assert(m->does_lex);
9812 return stb__matcher_dfa(m, str, len);
9813 }
9814
9815 int stb_regex(char *regex, char *str)
9816 {
9817 static stb_perfect p;
9818 static stb_matcher ** matchers;
9819 static char ** regexps;
9820 static char ** regexp_cache;
9821 static unsigned short *mapping;
9822 int z = stb_perfect_hash(&p, (int) regex);
9823 if (z >= 0) {
9824 if (strcmp(regex, regexp_cache[(int) mapping[z]])) {
9825 int i = mapping[z];
9826 stb_matcher_free(matchers[i]);
9827 free(regexp_cache[i]);
9828 regexps[i] = regex;
9829 regexp_cache[i] = strdup(regex);
9830 matchers[i] = stb_regex_matcher(regex);
9831 }
9832 } else {
9833 int i,n;
9834 if (regex == NULL) {
9835 for (i=0; i < stb_arr_len(matchers); ++i) {
9836 stb_matcher_free(matchers[i]);
9837 free(regexp_cache[i]);
9838 }
9839 stb_arr_free(matchers);
9840 stb_arr_free(regexps);
9841 stb_arr_free(regexp_cache);
9842 stb_perfect_destroy(&p);
9843 free(mapping); mapping = NULL;
9844 return -1;
9845 }
9846 stb_arr_push(regexps, regex);
9847 stb_arr_push(regexp_cache, strdup(regex));
9848 stb_arr_push(matchers, stb_regex_matcher(regex));
9849 stb_perfect_destroy(&p);
9850 n = stb_perfect_create(&p, (unsigned int *) (char **) regexps, stb_arr_len(regexps));
9851 mapping = (unsigned short *) realloc(mapping, n * sizeof(*mapping));
9852 for (i=0; i < stb_arr_len(regexps); ++i)
9853 mapping[stb_perfect_hash(&p, (int) regexps[i])] = i;
9854 z = stb_perfect_hash(&p, (int) regex);
9855 }
9856 return stb_matcher_find(matchers[(int) mapping[z]], str);
9857 }
9858
9859 #endif // STB_DEFINE
9860
9861
9862 #if 0
9863 //////////////////////////////////////////////////////////////////////////////
9864 //
9865 // C source-code introspection
9866 //
9867
9868 // runtime structure
9869 typedef struct
9870 {
9871 char *name;
9872 char *type; // base type
9873 char *comment; // content of comment field
9874 int size; // size of base type
9875 int offset; // field offset
9876 int arrcount[8]; // array sizes; -1 = pointer indirection; 0 = end of list
9877 } stb_info_field;
9878
9879 typedef struct
9880 {
9881 char *structname;
9882 int size;
9883 int num_fields;
9884 stb_info_field *fields;
9885 } stb_info_struct;
9886
9887 extern stb_info_struct stb_introspect_output[];
9888
9889 //
9890
9891 STB_EXTERN void stb_introspect_precompiled(stb_info_struct *compiled);
9892 STB_EXTERN void stb__introspect(char *path, char *file);
9893
9894 #define stb_introspect_ship() stb__introspect(NULL, NULL, stb__introspect_output)
9895
9896 #ifdef STB_SHIP
9897 #define stb_introspect() stb_introspect_ship()
9898 #define stb_introspect_path(p) stb_introspect_ship()
9899 #else
9900 // bootstrapping: define stb_introspect() (or 'path') the first time
9901 #define stb_introspect() stb__introspect(NULL, __FILE__, NULL)
9902 #define stb_introspect_auto() stb__introspect(NULL, __FILE__, stb__introspect_output)
9903
9904 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
9905 #define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
9906 #endif
9907
9908 #ifdef STB_DEFINE
9909
9910 #ifndef STB_INTROSPECT_CPP
9911 #ifdef __cplusplus
9912 #define STB_INTROSPECT_CPP 1
9913 #else
9914 #define STB_INTROSPECT_CPP 0
9915 #endif
9916 #endif
9917
9918 void stb_introspect_precompiled(stb_info_struct *compiled)
9919 {
9920
9921 }
9922
9923
9924 static void stb__introspect_filename(char *buffer, char *path)
9925 {
9926 #if STB_INTROSPECT_CPP
9927 sprintf(buffer, "%s/stb_introspect.cpp", path);
9928 #else
9929 sprintf(buffer, "%s/stb_introspect.c", path);
9930 #endif
9931 }
9932
9933 static void stb__introspect_compute(char *path, char *file)
9934 {
9935 int i;
9936 char ** include_list = NULL;
9937 char ** introspect_list = NULL;
9938 FILE *f;
9939 f = fopen(file, "w");
9940 if (!f) return;
9941
9942 fputs("// if you get compiler errors, change the following 0 to a 1:\n", f);
9943 fputs("#define STB_INTROSPECT_INVALID 0\n\n", f);
9944 fputs("// this will force the code to compile, and force the introspector\n", f);
9945 fputs("// to run and then exit, allowing you to recompile\n\n\n", f);
9946 fputs("#include \"stb.h\"\n\n",f );
9947 fputs("#if STB_INTROSPECT_INVALID\n", f);
9948 fputs(" stb_info_struct stb__introspect_output[] = { (void *) 1 }\n", f);
9949 fputs("#else\n\n", f);
9950 for (i=0; i < stb_arr_len(include_list); ++i)
9951 fprintf(f, " #include \"%s\"\n", include_list[i]);
9952
9953 fputs(" stb_info_struct stb__introspect_output[] =\n{\n", f);
9954 for (i=0; i < stb_arr_len(introspect_list); ++i)
9955 fprintf(f, " stb_introspect_%s,\n", introspect_list[i]);
9956 fputs(" };\n", f);
9957 fputs("#endif\n", f);
9958 fclose(f);
9959 }
9960
9961 static stb_info_struct *stb__introspect_info;
9962
9963 #ifndef STB_SHIP
9964
9965 #endif
9966
9967 void stb__introspect(char *path, char *file, stb_info_struct *compiled)
9968 {
9969 static int first=1;
9970 if (!first) return;
9971 first=0;
9972
9973 stb__introspect_info = compiled;
9974
9975 #ifndef STB_SHIP
9976 if (path || file) {
9977 int bail_flag = compiled && compiled[0].structname == (void *) 1;
9978 int needs_building = bail_flag;
9979 struct stb__stat st;
9980 char buffer[1024], buffer2[1024];
9981 if (!path) {
9982 stb_splitpath(buffer, file, STB_PATH);
9983 path = buffer;
9984 }
9985 // bail if the source path doesn't exist
9986 if (!stb_fexists(path)) return;
9987
9988 stb__introspect_filename(buffer2, path);
9989
9990 // get source/include files timestamps, compare to output-file timestamp;
9991 // if mismatched, regenerate
9992
9993 if (stb__stat(buffer2, &st))
9994 needs_building = STB_TRUE;
9995
9996 {
9997 // find any file that contains an introspection command and is newer
9998 // if needs_building is already true, we don't need to do this test,
9999 // but we still need these arrays, so go ahead and get them
10000 char **all[3];
10001 all[0] = stb_readdir_files_mask(path, "*.h");
10002 all[1] = stb_readdir_files_mask(path, "*.c");
10003 all[2] = stb_readdir_files_mask(path, "*.cpp");
10004 int i,j;
10005 if (needs_building) {
10006 for (j=0; j < 3; ++j) {
10007 for (i=0; i < stb_arr_len(all[j]); ++i) {
10008 struct stb__stat st2;
10009 if (!stb__stat(all[j][i], &st2)) {
10010 if (st.st_mtime < st2.st_mtime) {
10011 char *z = stb_filec(all[j][i], NULL);
10012 int found=STB_FALSE;
10013 while (y) {
10014 y = strstr(y, "//si");
10015 if (y && isspace(y[4])) {
10016 found = STB_TRUE;
10017 break;
10018 }
10019 }
10020 needs_building = STB_TRUE;
10021 goto done;
10022 }
10023 }
10024 }
10025 }
10026 done:;
10027 }
10028 char *z = stb_filec(all[i], NULL), *y = z;
10029 int found=STB_FALSE;
10030 while (y) {
10031 y = strstr(y, "//si");
10032 if (y && isspace(y[4])) {
10033 found = STB_TRUE;
10034 break;
10035 }
10036 }
10037 if (found)
10038 stb_arr_push(introspect_h, strdup(all[i]));
10039 free(z);
10040 }
10041 }
10042 stb_readdir_free(all);
10043 if (!needs_building) {
10044 for (i=0; i < stb_arr_len(introspect_h); ++i) {
10045 struct stb__stat st2;
10046 if (!stb__stat(introspect_h[i], &st2))
10047 if (st.st_mtime < st2.st_mtime)
10048 needs_building = STB_TRUE;
10049 }
10050 }
10051
10052 if (needs_building) {
10053 stb__introspect_compute(path, buffer2);
10054 }
10055 }
10056 }
10057 #endif
10058 }
10059 #endif
10060 #endif
10061
10062 #ifdef STB_INTROSPECT
10063 // compile-time code-generator
10064 #define INTROSPECT(x) int main(int argc, char **argv) { stb__introspect(__FILE__); return 0; }
10065 #define FILE(x)
10066
10067 void stb__introspect(char *filename)
10068 {
10069 char *file = stb_file(filename, NULL);
10070 char *s = file, *t, **p;
10071 char *out_name = "stb_introspect.c";
10072 char *out_path;
10073 STB_ARR(char) filelist = NULL;
10074 int i,n;
10075 if (!file) stb_fatal("Couldn't open %s", filename);
10076
10077 out_path = stb_splitpathdup(filename, STB_PATH);
10078
10079 // search for the macros
10080 while (*s) {
10081 char buffer[256];
10082 while (*s && !isupper(*s)) ++s;
10083 s = stb_strtok_invert(buffer, s, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
10084 s = stb_skipwhite(s);
10085 if (*s == '(') {
10086 ++s;
10087 t = strchr(s, ')');
10088 if (t == NULL) stb_fatal("Error parsing %s", filename);
10089
10090 }
10091 }
10092 }
10093
10094
10095
10096 #endif
10097
10098
10099 //////////////////////////////////////////////////////////////////////////////
10100 //
10101 // STB-C sliding-window dictionary compression
10102 //
10103 // This uses a DEFLATE-style sliding window, but no bitwise entropy.
10104 // Everything is on byte boundaries, so you could then apply a byte-wise
10105 // entropy code, though that's nowhere near as effective.
10106 //
10107 // An STB-C stream begins with a 16-byte header:
10108 // 4 bytes: 0x57 0xBC 0x00 0x00
10109 // 8 bytes: big-endian size of decompressed data, 64-bits
10110 // 4 bytes: big-endian size of window (how far back decompressor may need)
10111 //
10112 // The following symbols appear in the stream (these were determined ad hoc,
10113 // not by analysis):
10114 //
10115 // [dict] 00000100 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10116 // [END] 00000101 11111010 cccccccc cccccccc cccccccc cccccccc
10117 // [dict] 00000110 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx
10118 // [literals] 00000111 zzzzzzzz zzzzzzzz
10119 // [literals] 00001zzz zzzzzzzz
10120 // [dict] 00010yyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
10121 // [dict] 00011yyy yyyyyyyy yyyyyyyy xxxxxxxx
10122 // [literals] 001zzzzz
10123 // [dict] 01yyyyyy yyyyyyyy xxxxxxxx
10124 // [dict] 1xxxxxxx yyyyyyyy
10125 //
10126 // xxxxxxxx: match length - 1
10127 // yyyyyyyy: backwards distance - 1
10128 // zzzzzzzz: num literals - 1
10129 // cccccccc: adler32 checksum of decompressed data
10130 // (all big-endian)
10131
10132
10133 STB_EXTERN stb_uint stb_decompress_length(stb_uchar *input);
10134 STB_EXTERN stb_uint stb_decompress(stb_uchar *out,stb_uchar *in,stb_uint len);
10135 STB_EXTERN stb_uint stb_compress (stb_uchar *out,stb_uchar *in,stb_uint len);
10136 STB_EXTERN void stb_compress_window(int z);
10137 STB_EXTERN void stb_compress_hashsize(unsigned int z);
10138
10139 STB_EXTERN int stb_compress_tofile(char *filename, char *in, stb_uint len);
10140 STB_EXTERN int stb_compress_intofile(FILE *f, char *input, stb_uint len);
10141 STB_EXTERN char *stb_decompress_fromfile(char *filename, stb_uint *len);
10142
10143 STB_EXTERN int stb_compress_stream_start(FILE *f);
10144 STB_EXTERN void stb_compress_stream_end(int close);
10145 STB_EXTERN void stb_write(char *data, int data_len);
10146
10147 #ifdef STB_DEFINE
10148
10149 stb_uint stb_decompress_length(stb_uchar *input)
10150 {
10151 return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
10152 }
10153
10154 //////////////////// decompressor ///////////////////////
10155
10156 // simple implementation that just writes whole thing into big block
10157
10158 static unsigned char *stb__barrier;
10159 static unsigned char *stb__barrier2;
10160 static unsigned char *stb__barrier3;
10161 static unsigned char *stb__barrier4;
10162
10163 static stb_uchar *stb__dout;
10164 static void stb__match(stb_uchar *data, stb_uint length)
10165 {
10166 // INVERSE of memmove... write each byte before copying the next...
10167 assert (stb__dout + length <= stb__barrier);
10168 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10169 if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }
10170 while (length--) *stb__dout++ = *data++;
10171 }
10172
10173 static void stb__lit(stb_uchar *data, stb_uint length)
10174 {
10175 assert (stb__dout + length <= stb__barrier);
10176 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10177 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10178 memcpy(stb__dout, data, length);
10179 stb__dout += length;
10180 }
10181
10182 #define stb__in2(x) ((i[x] << 8) + i[(x)+1])
10183 #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
10184 #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
10185
10186 static stb_uchar *stb_decompress_token(stb_uchar *i)
10187 {
10188 if (*i >= 0x20) { // use fewer if's for cases that expand small
10189 if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10190 else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10191 else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
10192 } else { // more ifs for cases that expand large, since overhead is amortized
10193 if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10194 else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10195 else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
10196 else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
10197 else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10198 else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10199 }
10200 return i;
10201 }
10202
10203 stb_uint stb_decompress(stb_uchar *output, stb_uchar *i, stb_uint length)
10204 {
10205 stb_uint olen;
10206 if (stb__in4(0) != 0x57bC0000) return 0;
10207 if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
10208 olen = stb_decompress_length(i);
10209 stb__barrier2 = i;
10210 stb__barrier3 = i+length;
10211 stb__barrier = output + olen;
10212 stb__barrier4 = output;
10213 i += 16;
10214
10215 stb__dout = output;
10216 while (1) {
10217 stb_uchar *old_i = i;
10218 i = stb_decompress_token(i);
10219 if (i == old_i) {
10220 if (*i == 0x05 && i[1] == 0xfa) {
10221 assert(stb__dout == output + olen);
10222 if (stb__dout != output + olen) return 0;
10223 if (stb_adler32(1, output, olen) != (stb_uint) stb__in4(2))
10224 return 0;
10225 return olen;
10226 } else {
10227 assert(0); /* NOTREACHED */
10228 return 0;
10229 }
10230 }
10231 assert(stb__dout <= output + olen);
10232 if (stb__dout > output + olen)
10233 return 0;
10234 }
10235 }
10236
10237 char *stb_decompress_fromfile(char *filename, unsigned int *len)
10238 {
10239 unsigned int n;
10240 char *q;
10241 unsigned char *p;
10242 FILE *f = fopen(filename, "rb"); if (f == NULL) return NULL;
10243 fseek(f, 0, SEEK_END);
10244 n = ftell(f);
10245 fseek(f, 0, SEEK_SET);
10246 p = (unsigned char * ) malloc(n); if (p == NULL) return NULL;
10247 fread(p, 1, n, f);
10248 fclose(f);
10249 if (p == NULL) return NULL;
10250 if (p[0] != 0x57 || p[1] != 0xBc || p[2] || p[3]) { free(p); return NULL; }
10251 q = (char *) malloc(stb_decompress_length(p)+1);
10252 if (!q) { free(p); return NULL; }
10253 *len = stb_decompress((unsigned char *) q, p, n);
10254 if (*len) q[*len] = 0;
10255 free(p);
10256 return q;
10257 }
10258
10259 #if 0
10260 // streaming decompressor
10261
10262 static struct
10263 {
10264 stb__uchar *in_buffer;
10265 stb__uchar *match;
10266
10267 stb__uint pending_literals;
10268 stb__uint pending_match;
10269 } xx;
10270
10271
10272
10273 static void stb__match(stb_uchar *data, stb_uint length)
10274 {
10275 // INVERSE of memmove... write each byte before copying the next...
10276 assert (stb__dout + length <= stb__barrier);
10277 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10278 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10279 while (length--) *stb__dout++ = *data++;
10280 }
10281
10282 static void stb__lit(stb_uchar *data, stb_uint length)
10283 {
10284 assert (stb__dout + length <= stb__barrier);
10285 if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
10286 if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
10287 memcpy(stb__dout, data, length);
10288 stb__dout += length;
10289 }
10290
10291 static void sx_match(stb_uchar *data, stb_uint length)
10292 {
10293 xx.match = data;
10294 xx.pending_match = length;
10295 }
10296
10297 static void sx_lit(stb_uchar *data, stb_uint length)
10298 {
10299 xx.pending_lit = length;
10300 }
10301
10302 static int stb_decompress_token_state(void)
10303 {
10304 stb__uchar *i = xx.in_buffer;
10305
10306 if (*i >= 0x20) { // use fewer if's for cases that expand small
10307 if (*i >= 0x80) sx_match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
10308 else if (*i >= 0x40) sx_match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
10309 else /* *i >= 0x20 */ sx_lit(i+1, i[0] - 0x20 + 1), i += 1;
10310 } else { // more ifs for cases that expand large, since overhead is amortized
10311 if (*i >= 0x18) sx_match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
10312 else if (*i >= 0x10) sx_match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
10313 else if (*i >= 0x08) sx_lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2;
10314 else if (*i == 0x07) sx_lit(i+3, stb__in2(1) + 1), i += 3;
10315 else if (*i == 0x06) sx_match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
10316 else if (*i == 0x04) sx_match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
10317 else return 0;
10318 }
10319 xx.in_buffer = i;
10320 return 1;
10321 }
10322 #endif
10323
10324
10325
10326 //////////////////// compressor ///////////////////////
10327
10328 static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
10329 {
10330 stb_uint i;
10331 for (i=0; i < maxlen; ++i)
10332 if (m1[i] != m2[i]) return i;
10333 return i;
10334 }
10335
10336 // simple implementation that just takes the source data in a big block
10337
10338 static stb_uchar *stb__out;
10339 static FILE *stb__outfile;
10340 static stb_uint stb__outbytes;
10341
10342 static void stb__write(unsigned char v)
10343 {
10344 fputc(v, stb__outfile);
10345 ++stb__outbytes;
10346 }
10347
10348 #define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
10349
10350 static void stb_out2(stb_uint v)
10351 {
10352 stb_out(v >> 8);
10353 stb_out(v);
10354 }
10355
10356 static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
10357 static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
10358 stb_out(v >> 8 ); stb_out(v); }
10359
10360 static void outliterals(stb_uchar *in, int numlit)
10361 {
10362 while (numlit > 65536) {
10363 outliterals(in,65536);
10364 in += 65536;
10365 numlit -= 65536;
10366 }
10367
10368 if (numlit == 0) ;
10369 else if (numlit <= 32) stb_out (0x000020 + numlit-1);
10370 else if (numlit <= 2048) stb_out2(0x000800 + numlit-1);
10371 else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1);
10372
10373 if (stb__out) {
10374 memcpy(stb__out,in,numlit);
10375 stb__out += numlit;
10376 } else
10377 fwrite(in, 1, numlit, stb__outfile);
10378 }
10379
10380 static int stb__window = 0x40000; // 256K
10381 void stb_compress_window(int z)
10382 {
10383 if (z >= 0x1000000) z = 0x1000000; // limit of implementation
10384 if (z < 0x100) z = 0x100; // insanely small
10385 stb__window = z;
10386 }
10387
10388 static int stb_not_crap(int best, int dist)
10389 {
10390 return ((best > 2 && dist <= 0x00100)
10391 || (best > 5 && dist <= 0x04000)
10392 || (best > 7 && dist <= 0x80000));
10393 }
10394
10395 static stb_uint stb__hashsize = 32768;
10396 void stb_compress_hashsize(unsigned int y)
10397 {
10398 unsigned int z = 1024;
10399 while (z < y) z <<= 1;
10400 stb__hashsize = z >> 2; // pass in bytes, store #pointers
10401 }
10402
10403 // note that you can play with the hashing functions all you
10404 // want without needing to change the decompressor
10405 #define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
10406 #define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
10407 #define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
10408
10409 static stb_uint32 stb__running_adler;
10410
10411 static int stb_compress_chunk(stb_uchar *history,
10412 stb_uchar *start,
10413 stb_uchar *end,
10414 int length,
10415 int *pending_literals,
10416 stb_uchar **chash,
10417 stb_uint mask)
10418 {
10419 int window = stb__window;
10420 stb_uint match_max;
10421 stb_uchar *lit_start = start - *pending_literals;
10422 stb_uchar *q = start;
10423
10424 #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
10425
10426 // stop short of the end so we don't scan off the end doing
10427 // the hashing; this means we won't compress the last few bytes
10428 // unless they were part of something longer
10429 while (q < start+length && q+12 < end) {
10430 int m;
10431 stb_uint h1,h2,h3,h4, h;
10432 stb_uchar *t;
10433 int best = 2, dist=0;
10434
10435 if (q+65536 > end)
10436 match_max = end-q;
10437 else
10438 match_max = 65536;
10439
10440 #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
10441
10442 #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
10443 if (p ? dist != q-t : 1) \
10444 if ((m = stb_matchlen(t, q, match_max)) > best) \
10445 if (stb__nc(m,q-(t))) \
10446 best = m, dist = q - (t)
10447
10448 // rather than search for all matches, only try 4 candidate locations,
10449 // chosen based on 4 different hash functions of different lengths.
10450 // this strategy is inspired by LZO; hashing is unrolled here using the
10451 // 'hc' macro
10452 h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
10453 t = chash[h1]; if (t) STB__TRY(t,0);
10454 h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
10455 h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
10456 h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
10457 h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
10458 h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
10459 t = chash[h4]; if (t) STB__TRY(t,1);
10460
10461 // because we use a shared hash table, can only update it
10462 // _after_ we've probed all of them
10463 chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
10464
10465 if (best > 2)
10466 assert(dist > 0);
10467
10468 // see if our best match qualifies
10469 if (best < 3) { // fast path literals
10470 ++q;
10471 } else if (best > 2 && best <= 0x80 && dist <= 0x100) {
10472 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10473 stb_out(0x80 + best-1);
10474 stb_out(dist-1);
10475 } else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
10476 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10477 stb_out2(0x4000 + dist-1);
10478 stb_out(best-1);
10479 } else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
10480 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10481 stb_out3(0x180000 + dist-1);
10482 stb_out(best-1);
10483 } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
10484 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10485 stb_out3(0x100000 + dist-1);
10486 stb_out2(best-1);
10487 } else if (best > 9 && dist <= 0x1000000) {
10488 if (best > 65536) best = 65536;
10489 outliterals(lit_start, q-lit_start); lit_start = (q += best);
10490 if (best <= 0x100) {
10491 stb_out(0x06);
10492 stb_out3(dist-1);
10493 stb_out(best-1);
10494 } else {
10495 stb_out(0x04);
10496 stb_out3(dist-1);
10497 stb_out2(best-1);
10498 }
10499 } else { // fallback literals if no match was a balanced tradeoff
10500 ++q;
10501 }
10502 }
10503
10504 // if we didn't get all the way, add the rest to literals
10505 if (q-start < length)
10506 q = start+length;
10507
10508 // the literals are everything from lit_start to q
10509 *pending_literals = (q - lit_start);
10510
10511 stb__running_adler = stb_adler32(stb__running_adler, start, q - start);
10512 return q - start;
10513 }
10514
10515 static int stb_compress_inner(stb_uchar *input, stb_uint length)
10516 {
10517 int literals = 0;
10518 stb_uint len,i;
10519
10520 stb_uchar **chash;
10521 chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
10522 if (chash == NULL) return 0; // failure
10523 for (i=0; i < stb__hashsize; ++i)
10524 chash[i] = NULL;
10525
10526 // stream signature
10527 stb_out(0x57); stb_out(0xbc);
10528 stb_out2(0);
10529
10530 stb_out4(0); // 64-bit length requires 32-bit leading 0
10531 stb_out4(length);
10532 stb_out4(stb__window);
10533
10534 stb__running_adler = 1;
10535
10536 len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
10537 assert(len == length);
10538
10539 outliterals(input+length - literals, literals);
10540
10541 free(chash);
10542
10543 stb_out2(0x05fa); // end opcode
10544
10545 stb_out4(stb__running_adler);
10546
10547 return 1; // success
10548 }
10549
10550 stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
10551 {
10552 stb__out = out;
10553 stb__outfile = NULL;
10554
10555 stb_compress_inner(input, length);
10556
10557 return stb__out - out;
10558 }
10559
10560 int stb_compress_tofile(char *filename, char *input, unsigned int length)
10561 {
10562 //int maxlen = length + 512 + (length >> 2); // total guess
10563 //char *buffer = (char *) malloc(maxlen);
10564 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10565
10566 stb__out = NULL;
10567 stb__outfile = fopen(filename, "wb");
10568 if (!stb__outfile) return 0;
10569
10570 stb__outbytes = 0;
10571
10572 if (!stb_compress_inner((stb_uchar*)input, length))
10573 return 0;
10574
10575 fclose(stb__outfile);
10576
10577 return stb__outbytes;
10578 }
10579
10580 int stb_compress_intofile(FILE *f, char *input, unsigned int length)
10581 {
10582 //int maxlen = length + 512 + (length >> 2); // total guess
10583 //char *buffer = (char*)malloc(maxlen);
10584 //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
10585
10586 stb__out = NULL;
10587 stb__outfile = f;
10588 if (!stb__outfile) return 0;
10589
10590 stb__outbytes = 0;
10591
10592 if (!stb_compress_inner((stb_uchar*)input, length))
10593 return 0;
10594
10595 return stb__outbytes;
10596 }
10597
10598 ////////////////////// streaming I/O version /////////////////////
10599
10600
10601 static size_t stb_out_backpatch_id(void)
10602 {
10603 if (stb__out)
10604 return (size_t) stb__out;
10605 else
10606 return ftell(stb__outfile);
10607 }
10608
10609 static void stb_out_backpatch(size_t id, stb_uint value)
10610 {
10611 stb_uchar data[4] = { value >> 24, value >> 16, value >> 8, value };
10612 if (stb__out) {
10613 memcpy((void *) id, data, 4);
10614 } else {
10615 stb_uint where = ftell(stb__outfile);
10616 fseek(stb__outfile, id, SEEK_SET);
10617 fwrite(data, 4, 1, stb__outfile);
10618 fseek(stb__outfile, where, SEEK_SET);
10619 }
10620 }
10621
10622 // ok, the wraparound buffer was a total failure. let's instead
10623 // use a copying-in-place buffer, which lets us share the code.
10624 // This is way less efficient but it'll do for now.
10625
10626 static struct
10627 {
10628 stb_uchar *buffer;
10629 int size; // physical size of buffer in bytes
10630
10631 int valid; // amount of valid data in bytes
10632 int start; // bytes of data already output
10633
10634 int window;
10635 int fsize;
10636
10637 int pending_literals; // bytes not-quite output but counted in start
10638 int length_id;
10639
10640 stb_uint total_bytes;
10641
10642 stb_uchar **chash;
10643 stb_uint hashmask;
10644 } xtb;
10645
10646 static int stb_compress_streaming_start(void)
10647 {
10648 stb_uint i;
10649 xtb.size = stb__window * 3;
10650 xtb.buffer = (stb_uchar*)malloc(xtb.size);
10651 if (!xtb.buffer) return 0;
10652
10653 xtb.chash = (stb_uchar**)malloc(sizeof(*xtb.chash) * stb__hashsize);
10654 if (!xtb.chash) {
10655 free(xtb.buffer);
10656 return 0;
10657 }
10658
10659 for (i=0; i < stb__hashsize; ++i)
10660 xtb.chash[i] = NULL;
10661
10662 xtb.hashmask = stb__hashsize-1;
10663
10664 xtb.valid = 0;
10665 xtb.start = 0;
10666 xtb.window = stb__window;
10667 xtb.fsize = stb__window;
10668 xtb.pending_literals = 0;
10669 xtb.total_bytes = 0;
10670
10671 // stream signature
10672 stb_out(0x57); stb_out(0xbc); stb_out2(0);
10673
10674 stb_out4(0); // 64-bit length requires 32-bit leading 0
10675
10676 xtb.length_id = stb_out_backpatch_id();
10677 stb_out4(0); // we don't know the output length yet
10678
10679 stb_out4(stb__window);
10680
10681 stb__running_adler = 1;
10682
10683 return 1;
10684 }
10685
10686 static int stb_compress_streaming_end(void)
10687 {
10688 // flush out any remaining data
10689 stb_compress_chunk(xtb.buffer, xtb.buffer+xtb.start, xtb.buffer+xtb.valid,
10690 xtb.valid-xtb.start, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10691
10692 // write out pending literals
10693 outliterals(xtb.buffer + xtb.valid - xtb.pending_literals, xtb.pending_literals);
10694
10695 stb_out2(0x05fa); // end opcode
10696 stb_out4(stb__running_adler);
10697
10698 stb_out_backpatch(xtb.length_id, xtb.total_bytes);
10699
10700 free(xtb.buffer);
10701 free(xtb.chash);
10702 return 1;
10703 }
10704
10705 void stb_write(char *data, int data_len)
10706 {
10707 stb_uint i;
10708
10709 // @TODO: fast path for filling the buffer and doing nothing else
10710 // if (xtb.valid + data_len < xtb.size)
10711
10712 xtb.total_bytes += data_len;
10713
10714 while (data_len) {
10715 // fill buffer
10716 if (xtb.valid < xtb.size) {
10717 int amt = xtb.size - xtb.valid;
10718 if (data_len < amt) amt = data_len;
10719 memcpy(xtb.buffer + xtb.valid, data, amt);
10720 data_len -= amt;
10721 data += amt;
10722 xtb.valid += amt;
10723 }
10724 if (xtb.valid < xtb.size)
10725 return;
10726
10727 // at this point, the buffer is full
10728
10729 // if we can process some data, go for it; make sure
10730 // we leave an 'fsize's worth of data, though
10731 if (xtb.start + xtb.fsize < xtb.valid) {
10732 int amount = (xtb.valid - xtb.fsize) - xtb.start;
10733 int n;
10734 assert(amount > 0);
10735 n = stb_compress_chunk(xtb.buffer, xtb.buffer + xtb.start, xtb.buffer + xtb.valid,
10736 amount, &xtb.pending_literals, xtb.chash, xtb.hashmask);
10737 xtb.start += n;
10738 }
10739
10740 assert(xtb.start + xtb.fsize >= xtb.valid);
10741 // at this point, our future size is too small, so we
10742 // need to flush some history. we, in fact, flush exactly
10743 // one window's worth of history
10744
10745 {
10746 int flush = xtb.window;
10747 assert(xtb.start >= flush);
10748 assert(xtb.valid >= flush);
10749
10750 // if 'pending literals' extends back into the shift region,
10751 // write them out
10752 if (xtb.start - xtb.pending_literals < flush) {
10753 outliterals(xtb.buffer + xtb.start - xtb.pending_literals, xtb.pending_literals);
10754 xtb.pending_literals = 0;
10755 }
10756
10757 // now shift the window
10758 memmove(xtb.buffer, xtb.buffer + flush, xtb.valid - flush);
10759 xtb.start -= flush;
10760 xtb.valid -= flush;
10761
10762 for (i=0; i <= xtb.hashmask; ++i)
10763 if (xtb.chash[i] < xtb.buffer + flush)
10764 xtb.chash[i] = NULL;
10765 else
10766 xtb.chash[i] -= flush;
10767 }
10768 // and now that we've made room for more data, go back to the top
10769 }
10770 }
10771
10772 int stb_compress_stream_start(FILE *f)
10773 {
10774 stb__out = NULL;
10775 stb__outfile = f;
10776
10777 if (f == NULL)
10778 return 0;
10779
10780 if (!stb_compress_streaming_start())
10781 return 0;
10782
10783 return 1;
10784 }
10785
10786 void stb_compress_stream_end(int close)
10787 {
10788 stb_compress_streaming_end();
10789 if (close && stb__outfile) {
10790 fclose(stb__outfile);
10791 }
10792 }
10793
10794 #endif // STB_DEFINE
10795
10796 //////////////////////////////////////////////////////////////////////////////
10797 //
10798 // File abstraction... tired of not having this... we can write
10799 // compressors to be layers over these that auto-close their children.
10800
10801
10802 typedef struct stbfile
10803 {
10804 int (*getbyte)(struct stbfile *); // -1 on EOF
10805 unsigned int (*getdata)(struct stbfile *, void *block, unsigned int len);
10806
10807 int (*putbyte)(struct stbfile *, int byte);
10808 unsigned int (*putdata)(struct stbfile *, void *block, unsigned int len);
10809
10810 unsigned int (*size)(struct stbfile *);
10811
10812 unsigned int (*tell)(struct stbfile *);
10813 void (*backpatch)(struct stbfile *, unsigned int tell, void *block, unsigned int len);
10814
10815 void (*close)(struct stbfile *);
10816
10817 FILE *f; // file to fread/fwrite
10818 unsigned char *buffer; // input/output buffer
10819 unsigned char *indata, *inend; // input buffer
10820 union {
10821 int various;
10822 void *ptr;
10823 };
10824 } stbfile;
10825
10826 STB_EXTERN unsigned int stb_getc(stbfile *f); // read
10827 STB_EXTERN int stb_putc(stbfile *f, int ch); // write
10828 STB_EXTERN unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len); // read
10829 STB_EXTERN unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len); // write
10830 STB_EXTERN unsigned int stb_tell(stbfile *f); // read
10831 STB_EXTERN unsigned int stb_size(stbfile *f); // read/write
10832 STB_EXTERN void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len); // write
10833
10834 #ifdef STB_DEFINE
10835
10836 unsigned int stb_getc(stbfile *f) { return f->getbyte(f); }
10837 int stb_putc(stbfile *f, int ch) { return f->putbyte(f, ch); }
10838
10839 unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len)
10840 {
10841 return f->getdata(f, buffer, len);
10842 }
10843 unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len)
10844 {
10845 return f->putdata(f, buffer, len);
10846 }
10847 void stb_close(stbfile *f)
10848 {
10849 f->close(f);
10850 free(f);
10851 }
10852 unsigned int stb_tell(stbfile *f) { return f->tell(f); }
10853 unsigned int stb_size(stbfile *f) { return f->size(f); }
10854 void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len)
10855 {
10856 f->backpatch(f,tell,buffer,len);
10857 }
10858
10859 // FILE * implementation
10860 static int stb__fgetbyte(stbfile *f) { return fgetc(f->f); }
10861 static int stb__fputbyte(stbfile *f, int ch) { return fputc(ch, f->f)==0; }
10862 static unsigned int stb__fgetdata(stbfile *f, void *buffer, unsigned int len) { return fread(buffer,1,len,f->f); }
10863 static unsigned int stb__fputdata(stbfile *f, void *buffer, unsigned int len) { return fwrite(buffer,1,len,f->f); }
10864 static unsigned int stb__fsize(stbfile *f) { return stb_filelen(f->f); }
10865 static unsigned int stb__ftell(stbfile *f) { return ftell(f->f); }
10866 static void stb__fbackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len)
10867 {
10868 fseek(f->f, where, SEEK_SET);
10869 fwrite(buffer, 1, len, f->f);
10870 fseek(f->f, 0, SEEK_END);
10871 }
10872 static void stb__fclose(stbfile *f) { fclose(f->f); }
10873
10874 stbfile *stb_openf(FILE *f)
10875 {
10876 stbfile m = { stb__fgetbyte, stb__fgetdata,
10877 stb__fputbyte, stb__fputdata,
10878 stb__fsize, stb__ftell, stb__fbackpatch, stb__fclose,
10879 0,0,0, };
10880 stbfile *z = (stbfile *) malloc(sizeof(*z));
10881 if (z) {
10882 *z = m;
10883 z->f = f;
10884 }
10885 return z;
10886 }
10887
10888 static int stb__nogetbyte(stbfile *f) { assert(0); return -1; }
10889 static unsigned int stb__nogetdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
10890 static int stb__noputbyte(stbfile *f, int ch) { assert(0); return 0; }
10891 static unsigned int stb__noputdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
10892 static void stb__nobackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len) { assert(0); }
10893
10894 static int stb__bgetbyte(stbfile *s)
10895 {
10896 if (s->indata < s->inend)
10897 return *s->indata++;
10898 else
10899 return -1;
10900 }
10901
10902 static unsigned int stb__bgetdata(stbfile *s, void *buffer, unsigned int len)
10903 {
10904 if (s->indata + len > s->inend)
10905 len = s->inend - s->indata;
10906 memcpy(buffer, s->indata, len);
10907 s->indata += len;
10908 return len;
10909 }
10910 static unsigned int stb__bsize(stbfile *s) { return s->inend - s->buffer; }
10911 static unsigned int stb__btell(stbfile *s) { return s->indata - s->buffer; }
10912
10913 static void stb__bclose(stbfile *s)
10914 {
10915 if (s->various)
10916 free(s->buffer);
10917 }
10918
10919 stbfile *stb_open_inbuffer(void *buffer, unsigned int len)
10920 {
10921 stbfile m = { stb__bgetbyte, stb__bgetdata,
10922 stb__noputbyte, stb__noputdata,
10923 stb__bsize, stb__btell, stb__nobackpatch, stb__bclose };
10924 stbfile *z = (stbfile *) malloc(sizeof(*z));
10925 if (z) {
10926 *z = m;
10927 z->buffer = (unsigned char *) buffer;
10928 z->indata = z->buffer;
10929 z->inend = z->indata + len;
10930 }
10931 return z;
10932 }
10933
10934 stbfile *stb_open_inbuffer_free(void *buffer, unsigned int len)
10935 {
10936 stbfile *z = stb_open_inbuffer(buffer, len);
10937 if (z)
10938 z->various = 1; // free
10939 return z;
10940 }
10941
10942 #ifndef STB_VERSION
10943 // if we've been cut-and-pasted elsewhere, you get a limited
10944 // version of stb_open, without the 'k' flag and utf8 support
10945 static void stb__fclose2(stbfile *f)
10946 {
10947 fclose(f->f);
10948 }
10949
10950 stbfile *stb_open(char *filename, char *mode)
10951 {
10952 FILE *f = fopen(filename, mode);
10953 stbfile *s;
10954 if (f == NULL) return NULL;
10955 s = stb_openf(f);
10956 if (s)
10957 s->close = stb__fclose2;
10958 return s;
10959 }
10960 #else
10961 // the full version depends on some code in stb.h; this
10962 // also includes the memory buffer output format implemented with stb_arr
10963 static void stb__fclose2(stbfile *f)
10964 {
10965 stb_fclose(f->f, f->various);
10966 }
10967
10968 stbfile *stb_open(char *filename, char *mode)
10969 {
10970 FILE *f = stb_fopen(filename, mode[0] == 'k' ? mode+1 : mode);
10971 stbfile *s;
10972 if (f == NULL) return NULL;
10973 s = stb_openf(f);
10974 if (s) {
10975 s->close = stb__fclose2;
10976 s->various = mode[0] == 'k' ? stb_keep_if_different : stb_keep_yes;
10977 }
10978 return s;
10979 }
10980
10981 static int stb__aputbyte(stbfile *f, int ch)
10982 {
10983 stb_arr_push(f->buffer, ch);
10984 return 1;
10985 }
10986 static unsigned int stb__aputdata(stbfile *f, void *data, unsigned int len)
10987 {
10988 memcpy(stb_arr_addn(f->buffer, (int) len), data, len);
10989 return len;
10990 }
10991 static unsigned int stb__asize(stbfile *f) { return stb_arr_len(f->buffer); }
10992 static void stb__abackpatch(stbfile *f, unsigned int where, void *data, unsigned int len)
10993 {
10994 memcpy(f->buffer+where, data, len);
10995 }
10996 static void stb__aclose(stbfile *f)
10997 {
10998 *(unsigned char **) f->ptr = f->buffer;
10999 }
11000
11001 stbfile *stb_open_outbuffer(unsigned char **update_on_close)
11002 {
11003 stbfile m = { stb__nogetbyte, stb__nogetdata,
11004 stb__aputbyte, stb__aputdata,
11005 stb__asize, stb__asize, stb__abackpatch, stb__aclose };
11006 stbfile *z = (stbfile *) malloc(sizeof(*z));
11007 if (z) {
11008 z->ptr = update_on_close;
11009 *z = m;
11010 }
11011 return z;
11012 }
11013 #endif
11014 #endif
11015
11016
11017 //////////////////////////////////////////////////////////////////////////////
11018 //
11019 // Arithmetic coder... based on cbloom's notes on the subject, should be
11020 // less code than a huffman code.
11021
11022 typedef struct
11023 {
11024 unsigned int range_low;
11025 unsigned int range_high;
11026 unsigned int code, range; // decode
11027 int buffered_u8;
11028 int pending_ffs;
11029 stbfile *output;
11030 } stb_arith;
11031
11032 STB_EXTERN void stb_arith_init_encode(stb_arith *a, stbfile *out);
11033 STB_EXTERN void stb_arith_init_decode(stb_arith *a, stbfile *in);
11034 STB_EXTERN stbfile *stb_arith_encode_close(stb_arith *a);
11035 STB_EXTERN stbfile *stb_arith_decode_close(stb_arith *a);
11036
11037 STB_EXTERN void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11038 STB_EXTERN void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11039 STB_EXTERN unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq);
11040 STB_EXTERN void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
11041 STB_EXTERN unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2);
11042 STB_EXTERN void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
11043
11044 STB_EXTERN void stb_arith_encode_byte(stb_arith *a, int byte);
11045 STB_EXTERN int stb_arith_decode_byte(stb_arith *a);
11046
11047 // this is a memory-inefficient way of doing things, but it's
11048 // fast(?) and simple
11049 typedef struct
11050 {
11051 unsigned short cumfreq;
11052 unsigned short samples;
11053 } stb_arith_symstate_item;
11054
11055 typedef struct
11056 {
11057 int num_sym;
11058 unsigned int pow2;
11059 int countdown;
11060 stb_arith_symstate_item data[1];
11061 } stb_arith_symstate;
11062
11063 #ifdef STB_DEFINE
11064 void stb_arith_init_encode(stb_arith *a, stbfile *out)
11065 {
11066 a->range_low = 0;
11067 a->range_high = 0xffffffff;
11068 a->pending_ffs = -1; // means no buffered character currently, to speed up normal case
11069 a->output = out;
11070 }
11071
11072 static void stb__arith_carry(stb_arith *a)
11073 {
11074 int i;
11075 assert(a->pending_ffs != -1); // can't carry with no data
11076 stb_putc(a->output, a->buffered_u8);
11077 for (i=0; i < a->pending_ffs; ++i)
11078 stb_putc(a->output, 0);
11079 }
11080
11081 static void stb__arith_putbyte(stb_arith *a, int byte)
11082 {
11083 if (a->pending_ffs) {
11084 if (a->pending_ffs == -1) { // means no buffered data; encoded for fast path efficiency
11085 if (byte == 0xff)
11086 stb_putc(a->output, byte); // just write it immediately
11087 else {
11088 a->buffered_u8 = byte;
11089 a->pending_ffs = 0;
11090 }
11091 } else if (byte == 0xff) {
11092 ++a->pending_ffs;
11093 } else {
11094 int i;
11095 stb_putc(a->output, a->buffered_u8);
11096 for (i=0; i < a->pending_ffs; ++i)
11097 stb_putc(a->output, 0xff);
11098 }
11099 } else if (byte == 0xff) {
11100 ++a->pending_ffs;
11101 } else {
11102 // fast path
11103 stb_putc(a->output, a->buffered_u8);
11104 a->buffered_u8 = byte;
11105 }
11106 }
11107
11108 static void stb__arith_flush(stb_arith *a)
11109 {
11110 if (a->pending_ffs >= 0) {
11111 int i;
11112 stb_putc(a->output, a->buffered_u8);
11113 for (i=0; i < a->pending_ffs; ++i)
11114 stb_putc(a->output, 0xff);
11115 }
11116 }
11117
11118 static void stb__renorm_encoder(stb_arith *a)
11119 {
11120 stb__arith_putbyte(a, a->range_low >> 24);
11121 a->range_low <<= 8;
11122 a->range_high = (a->range_high << 8) | 0xff;
11123 }
11124
11125 static void stb__renorm_decoder(stb_arith *a)
11126 {
11127 int c = stb_getc(a->output);
11128 a->code = (a->code << 8) + (c >= 0 ? c : 0); // if EOF, insert 0
11129 }
11130
11131 void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11132 {
11133 unsigned int range = a->range_high - a->range_low;
11134 unsigned int old = a->range_low;
11135 range /= totalfreq;
11136 a->range_low += range * cumfreq;
11137 a->range_high = a->range_low + range*freq;
11138 if (a->range_low < old)
11139 stb__arith_carry(a);
11140 while (a->range_high - a->range_low < 0x1000000)
11141 stb__renorm_encoder(a);
11142 }
11143
11144 void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11145 {
11146 unsigned int range = a->range_high - a->range_low;
11147 unsigned int old = a->range_low;
11148 range >>= totalfreq2;
11149 a->range_low += range * cumfreq;
11150 a->range_high = a->range_low + range*freq;
11151 if (a->range_low < old)
11152 stb__arith_carry(a);
11153 while (a->range_high - a->range_low < 0x1000000)
11154 stb__renorm_encoder(a);
11155 }
11156
11157 unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq)
11158 {
11159 unsigned int freqsize = a->range / totalfreq;
11160 unsigned int z = a->code / freqsize;
11161 return z >= totalfreq ? totalfreq-1 : z;
11162 }
11163
11164 void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
11165 {
11166 unsigned int freqsize = a->range / totalfreq; // @OPTIMIZE, share with above divide somehow?
11167 a->code -= freqsize * cumfreq;
11168 a->range = freqsize * freq;
11169 while (a->range < 0x1000000)
11170 stb__renorm_decoder(a);
11171 }
11172
11173 unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2)
11174 {
11175 unsigned int freqsize = a->range >> totalfreq2;
11176 unsigned int z = a->code / freqsize;
11177 return z >= (1U<<totalfreq2) ? (1U<<totalfreq2)-1 : z;
11178 }
11179
11180 void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
11181 {
11182 unsigned int freqsize = a->range >> totalfreq2;
11183 a->code -= freqsize * cumfreq;
11184 a->range = freqsize * freq;
11185 while (a->range < 0x1000000)
11186 stb__renorm_decoder(a);
11187 }
11188
11189 stbfile *stb_arith_encode_close(stb_arith *a)
11190 {
11191 // put exactly as many bytes as we'll read, so we can turn on/off arithmetic coding in a stream
11192 stb__arith_putbyte(a, a->range_low >> 24);
11193 stb__arith_putbyte(a, a->range_low >> 16);
11194 stb__arith_putbyte(a, a->range_low >> 8);
11195 stb__arith_putbyte(a, a->range_low >> 0);
11196 stb__arith_flush(a);
11197 return a->output;
11198 }
11199
11200 stbfile *stb_arith_decode_close(stb_arith *a)
11201 {
11202 return a->output;
11203 }
11204
11205 // this is a simple power-of-two based model -- using
11206 // power of two means we need one divide per decode,
11207 // not two.
11208 #define POW2_LIMIT 12
11209 stb_arith_symstate *stb_arith_state_create(int num_sym)
11210 {
11211 stb_arith_symstate *s = (stb_arith_symstate *) malloc(sizeof(*s) + (num_sym-1) * sizeof(s->data[0]));
11212 if (s) {
11213 int i, cf, cf_next, next;
11214 int start_freq, extra;
11215 s->num_sym = num_sym;
11216 s->pow2 = 4;
11217 while (s->pow2 < 15 && (1 << s->pow2) < 3*num_sym) {
11218 ++s->pow2;
11219 }
11220 start_freq = (1 << s->pow2) / num_sym;
11221 assert(start_freq >= 1);
11222 extra = (1 << s->pow2) % num_sym;
11223 // now set up the initial stats
11224
11225 if (s->pow2 < POW2_LIMIT)
11226 next = 0;
11227 else
11228 next = 1;
11229
11230 cf = cf_next = 0;
11231 for (i=0; i < extra; ++i) {
11232 s->data[i].cumfreq = cf;
11233 s->data[i].samples = next;
11234 cf += start_freq+1;
11235 cf_next += next;
11236 }
11237 for (; i < num_sym; ++i) {
11238 s->data[i].cumfreq = cf;
11239 s->data[i].samples = next;
11240 cf += start_freq;
11241 cf_next += next;
11242 }
11243 assert(cf == (1 << s->pow2));
11244 // now, how long should we go until we have 2 << s->pow2 samples?
11245 s->countdown = (2 << s->pow2) - cf - cf_next;
11246 }
11247 return s;
11248 }
11249
11250 static void stb_arith_state_rescale(stb_arith_symstate *s)
11251 {
11252 if (s->pow2 < POW2_LIMIT) {
11253 int pcf, cf, cf_next, next, i;
11254 ++s->pow2;
11255 if (s->pow2 < POW2_LIMIT)
11256 next = 0;
11257 else
11258 next = 1;
11259 cf = cf_next = 0;
11260 pcf = 0;
11261 for (i=0; i < s->num_sym; ++i) {
11262 int sample = s->data[i].cumfreq - pcf + s->data[i].samples;
11263 s->data[i].cumfreq = cf;
11264 cf += sample;
11265 s->data[i].samples = next;
11266 cf_next += next;
11267 }
11268 assert(cf == (1 << s->pow2));
11269 s->countdown = (2 << s->pow2) - cf - cf_next;
11270 } else {
11271 int pcf, cf, cf_next, i;
11272 cf = cf_next = 0;
11273 pcf = 0;
11274 for (i=0; i < s->num_sym; ++i) {
11275 int sample = (s->data[i].cumfreq - pcf + s->data[i].samples) >> 1;
11276 s->data[i].cumfreq = cf;
11277 cf += sample;
11278 s->data[i].samples = 1;
11279 cf_next += 1;
11280 }
11281 assert(cf == (1 << s->pow2)); // this isn't necessarily true, due to rounding down!
11282 s->countdown = (2 << s->pow2) - cf - cf_next;
11283 }
11284 }
11285
11286 void stb_arith_encode_byte(stb_arith *a, int byte)
11287 {
11288 }
11289
11290 int stb_arith_decode_byte(stb_arith *a)
11291 {
11292 return -1;
11293 }
11294 #endif
11295
11296 //////////////////////////////////////////////////////////////////////////////
11297 //
11298 // Threads
11299 //
11300
11301 #ifndef _WIN32
11302 #ifdef STB_THREADS
11303 #error "threads not implemented except for Windows"
11304 #endif
11305 #endif
11306
11307 // call this function to free any global variables for memory testing
11308 STB_EXTERN void stb_thread_cleanup(void);
11309
11310 typedef void * (*stb_thread_func)(void *);
11311
11312 // do not rely on these types, this is an implementation detail.
11313 // compare against STB_THREAD_NULL and ST_SEMAPHORE_NULL
11314 typedef void *stb_thread;
11315 typedef void *stb_semaphore;
11316 typedef void *stb_mutex;
11317 typedef struct stb__sync *stb_sync;
11318
11319 #define STB_SEMAPHORE_NULL NULL
11320 #define STB_THREAD_NULL NULL
11321 #define STB_MUTEX_NULL NULL
11322 #define STB_SYNC_NULL NULL
11323
11324 // get the number of processors (limited to those in the affinity mask for this process).
11325 STB_EXTERN int stb_processor_count(void);
11326 // force to run on a single core -- needed for RDTSC to work, e.g. for iprof
11327 STB_EXTERN void stb_force_uniprocessor(void);
11328
11329 // stb_work functions: queue up work to be done by some worker threads
11330
11331 // set number of threads to serve the queue; you can change this on the fly,
11332 // but if you decrease it, it won't decrease until things currently on the
11333 // queue are finished
11334 STB_EXTERN void stb_work_numthreads(int n);
11335 // set maximum number of units in the queue; you can only set this BEFORE running any work functions
11336 STB_EXTERN int stb_work_maxunits(int n);
11337 // enqueue some work to be done (can do this from any thread, or even from a piece of work);
11338 // return value of f is stored in *return_code if non-NULL
11339 STB_EXTERN int stb_work(stb_thread_func f, void *d, volatile void **return_code);
11340 // as above, but stb_sync_reach is called on 'rel' after work is complete
11341 STB_EXTERN int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11342
11343
11344 // necessary to call this when using volatile to order writes/reads
11345 STB_EXTERN void stb_barrier(void);
11346
11347 // support for independent queues with their own threads
11348
11349 typedef struct stb__workqueue stb_workqueue;
11350
11351 STB_EXTERN stb_workqueue*stb_workq_new(int numthreads, int max_units);
11352 STB_EXTERN stb_workqueue*stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex);
11353 STB_EXTERN void stb_workq_delete(stb_workqueue *q);
11354 STB_EXTERN void stb_workq_numthreads(stb_workqueue *q, int n);
11355 STB_EXTERN int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code);
11356 STB_EXTERN int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
11357 STB_EXTERN int stb_workq_length(stb_workqueue *q);
11358
11359 STB_EXTERN stb_thread stb_create_thread (stb_thread_func f, void *d);
11360 STB_EXTERN stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel);
11361 STB_EXTERN void stb_destroy_thread(stb_thread t);
11362
11363 STB_EXTERN stb_semaphore stb_sem_new(int max_val);
11364 STB_EXTERN stb_semaphore stb_sem_new_extra(int max_val, int start_val);
11365 STB_EXTERN void stb_sem_delete (stb_semaphore s);
11366 STB_EXTERN void stb_sem_waitfor(stb_semaphore s);
11367 STB_EXTERN void stb_sem_release(stb_semaphore s);
11368
11369 STB_EXTERN stb_mutex stb_mutex_new(void);
11370 STB_EXTERN void stb_mutex_delete(stb_mutex m);
11371 STB_EXTERN void stb_mutex_begin(stb_mutex m);
11372 STB_EXTERN void stb_mutex_end(stb_mutex m);
11373
11374 STB_EXTERN stb_sync stb_sync_new(void);
11375 STB_EXTERN void stb_sync_delete(stb_sync s);
11376 STB_EXTERN int stb_sync_set_target(stb_sync s, int count);
11377 STB_EXTERN void stb_sync_reach_and_wait(stb_sync s); // wait for 'target' reachers
11378 STB_EXTERN int stb_sync_reach(stb_sync s);
11379
11380 typedef struct stb__threadqueue stb_threadqueue;
11381 #define STB_THREADQ_DYNAMIC 0
11382 STB_EXTERN stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove);
11383 STB_EXTERN void stb_threadq_delete(stb_threadqueue *tq);
11384 STB_EXTERN int stb_threadq_get(stb_threadqueue *tq, void *output);
11385 STB_EXTERN void stb_threadq_get_block(stb_threadqueue *tq, void *output);
11386 STB_EXTERN int stb_threadq_add(stb_threadqueue *tq, void *input);
11387 // can return FALSE if STB_THREADQ_DYNAMIC and attempt to grow fails
11388 STB_EXTERN int stb_threadq_add_block(stb_threadqueue *tq, void *input);
11389
11390 #ifdef STB_THREADS
11391 #ifdef STB_DEFINE
11392
11393 typedef struct
11394 {
11395 stb_thread_func f;
11396 void *d;
11397 volatile void **return_val;
11398 stb_semaphore sem;
11399 } stb__thread;
11400
11401 // this is initialized along all possible paths to create threads, therefore
11402 // it's always initialized before any other threads are create, therefore
11403 // it's free of races AS LONG AS you only create threads through stb_*
11404 static stb_mutex stb__threadmutex, stb__workmutex;
11405
11406 static void stb__threadmutex_init(void)
11407 {
11408 if (stb__threadmutex == STB_SEMAPHORE_NULL) {
11409 stb__threadmutex = stb_mutex_new();
11410 stb__workmutex = stb_mutex_new();
11411 }
11412 }
11413
11414 #ifdef STB_THREAD_TEST
11415 volatile float stb__t1=1, stb__t2;
11416
11417 static void stb__wait(int n)
11418 {
11419 float z = 0;
11420 int i;
11421 for (i=0; i < n; ++i)
11422 z += 1 / (stb__t1+i);
11423 stb__t2 = z;
11424 }
11425 #else
11426 #define stb__wait(x)
11427 #endif
11428
11429 #ifdef _WIN32
11430
11431 // avoid including windows.h -- note that our definitions aren't
11432 // exactly the same (we don't define the security descriptor struct)
11433 // so if you want to include windows.h, make sure you do it first.
11434 #include <process.h>
11435
11436 #ifndef _WINDOWS_ // check windows.h guard
11437 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
11438 #define STB__DW unsigned long
11439
11440 STB__IMPORT int __stdcall TerminateThread(void *, STB__DW);
11441 STB__IMPORT void * __stdcall CreateSemaphoreA(void *sec, long,long,char*);
11442 STB__IMPORT int __stdcall CloseHandle(void *);
11443 STB__IMPORT STB__DW __stdcall WaitForSingleObject(void *, STB__DW);
11444 STB__IMPORT int __stdcall ReleaseSemaphore(void *, long, long *);
11445 STB__IMPORT void __stdcall Sleep(STB__DW);
11446 #endif
11447
11448 // necessary to call this when using volatile to order writes/reads
11449 void stb_barrier(void)
11450 {
11451 #ifdef MemoryBarrier
11452 MemoryBarrier();
11453 #else
11454 long temp;
11455 __asm xchg temp,eax;
11456 #endif
11457 }
11458
11459 static void stb__thread_run(void *t)
11460 {
11461 void *res;
11462 stb__thread info = * (stb__thread *) t;
11463 free(t);
11464 res = info.f(info.d);
11465 if (info.return_val)
11466 *info.return_val = res;
11467 if (info.sem != STB_SEMAPHORE_NULL)
11468 stb_sem_release(info.sem);
11469 }
11470
11471 static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11472 {
11473 #ifdef _MT
11474 #if defined(STB_FASTMALLOC) && !defined(STB_FASTMALLOC_ITS_OKAY_I_ONLY_MALLOC_IN_ONE_THREAD)
11475 stb_fatal("Error! Cannot use STB_FASTMALLOC with threads.\n");
11476 return STB_THREAD_NULL;
11477 #else
11478 unsigned long id;
11479 stb__thread *data = (stb__thread *) malloc(sizeof(*data));
11480 if (!data) return NULL;
11481 stb__threadmutex_init();
11482 data->f = f;
11483 data->d = d;
11484 data->return_val = return_code;
11485 data->sem = rel;
11486 id = _beginthread(stb__thread_run, 0, data);
11487 if (id == -1) return NULL;
11488 return (void *) id;
11489 #endif
11490 #else
11491 #ifdef STB_NO_STB_STRINGS
11492 stb_fatal("Invalid compilation");
11493 #else
11494 stb_fatal("Must compile mult-threaded to use stb_thread/stb_work.");
11495 #endif
11496 return NULL;
11497 #endif
11498 }
11499
11500 // trivial win32 wrappers
11501 void stb_destroy_thread(stb_thread t) { TerminateThread(t,0); }
11502 stb_semaphore stb_sem_new(int maxv) {return CreateSemaphoreA(NULL,0,maxv,NULL); }
11503 stb_semaphore stb_sem_new_extra(int maxv,int start){return CreateSemaphoreA(NULL,start,maxv,NULL); }
11504 void stb_sem_delete(stb_semaphore s) { if (s != NULL) CloseHandle(s); }
11505 void stb_sem_waitfor(stb_semaphore s) { WaitForSingleObject(s, 0xffffffff); } // INFINITE
11506 void stb_sem_release(stb_semaphore s) { ReleaseSemaphore(s,1,NULL); }
11507 static void stb__thread_sleep(int ms) { Sleep(ms); }
11508
11509 #ifndef _WINDOWS_
11510 STB__IMPORT int __stdcall GetProcessAffinityMask(void *, STB__DW *, STB__DW *);
11511 STB__IMPORT void * __stdcall GetCurrentProcess(void);
11512 STB__IMPORT int __stdcall SetProcessAffinityMask(void *, STB__DW);
11513 #endif
11514
11515 int stb_processor_count(void)
11516 {
11517 unsigned long proc,sys;
11518 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11519 return stb_bitcount(proc);
11520 }
11521
11522 void stb_force_uniprocessor(void)
11523 {
11524 unsigned long proc,sys;
11525 GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
11526 if (stb_bitcount(proc) > 1) {
11527 int z;
11528 for (z=0; z < 32; ++z)
11529 if (proc & (1 << z))
11530 break;
11531 if (z < 32) {
11532 proc = 1 << z;
11533 SetProcessAffinityMask(GetCurrentProcess(), proc);
11534 }
11535 }
11536 }
11537
11538 #ifdef _WINDOWS_
11539 #define STB_MUTEX_NATIVE
11540 void *stb_mutex_new(void)
11541 {
11542 CRITICAL_SECTION *p = (CRITICAL_SECTION *) malloc(sizeof(*p));
11543 if (p)
11544 #if _WIN32_WINNT >= 0x0500
11545 InitializeCriticalSectionAndSpinCount(p, 500);
11546 #else
11547 InitializeCriticalSection(p);
11548 #endif
11549 return p;
11550 }
11551
11552 void stb_mutex_delete(void *p)
11553 {
11554 if (p) {
11555 DeleteCriticalSection((CRITICAL_SECTION *) p);
11556 free(p);
11557 }
11558 }
11559
11560 void stb_mutex_begin(void *p)
11561 {
11562 stb__wait(500);
11563 if (p)
11564 EnterCriticalSection((CRITICAL_SECTION *) p);
11565 }
11566
11567 void stb_mutex_end(void *p)
11568 {
11569 if (p)
11570 LeaveCriticalSection((CRITICAL_SECTION *) p);
11571 stb__wait(500);
11572 }
11573 #endif // _WINDOWS_
11574
11575 #if 0
11576 // for future reference,
11577 // InterlockedCompareExchange for x86:
11578 int cas64_mp(void * dest, void * xcmp, void * xxchg) {
11579 __asm
11580 {
11581 mov esi, [xxchg] ; exchange
11582 mov ebx, [esi + 0]
11583 mov ecx, [esi + 4]
11584
11585 mov esi, [xcmp] ; comparand
11586 mov eax, [esi + 0]
11587 mov edx, [esi + 4]
11588
11589 mov edi, [dest] ; destination
11590 lock cmpxchg8b [edi]
11591 jz yyyy;
11592
11593 mov [esi + 0], eax;
11594 mov [esi + 4], edx;
11595
11596 yyyy:
11597 xor eax, eax;
11598 setz al;
11599 };
11600
11601 inline unsigned __int64 _InterlockedCompareExchange64(volatile unsigned __int64 *dest
11602 ,unsigned __int64 exchange
11603 ,unsigned __int64 comperand)
11604 {
11605 //value returned in eax::edx
11606 __asm {
11607 lea esi,comperand;
11608 lea edi,exchange;
11609
11610 mov eax,[esi];
11611 mov edx,4[esi];
11612 mov ebx,[edi];
11613 mov ecx,4[edi];
11614 mov esi,dest;
11615 lock CMPXCHG8B [esi];
11616 }
11617 #endif // #if 0
11618
11619 #endif // _WIN32
11620
11621 stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
11622 {
11623 return stb_create_thread_raw(f,d,return_code,rel);
11624 }
11625
11626 stb_thread stb_create_thread(stb_thread_func f, void *d)
11627 {
11628 return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL);
11629 }
11630
11631 // mutex implemented by wrapping semaphore
11632 #ifndef STB_MUTEX_NATIVE
11633 stb_mutex stb_mutex_new(void) { return stb_sem_new_extra(1,1); }
11634 void stb_mutex_delete(stb_mutex m) { stb_sem_delete (m); }
11635 void stb_mutex_begin(stb_mutex m) { stb__wait(500); if (m) stb_sem_waitfor(m); }
11636 void stb_mutex_end(stb_mutex m) { if (m) stb_sem_release(m); stb__wait(500); }
11637 #endif
11638
11639 // thread merge operation
11640 struct stb__sync
11641 {
11642 int target; // target number of threads to hit it
11643 int sofar; // total threads that hit it
11644 int waiting; // total threads waiting
11645
11646 stb_mutex start; // mutex to prevent starting again before finishing previous
11647 stb_mutex mutex; // mutex while tweaking state
11648 stb_semaphore release; // semaphore wake up waiting threads
11649 // we have to wake them up one at a time, rather than using a single release
11650 // call, because win32 semaphores don't let you dynamically change the max count!
11651 };
11652
11653 stb_sync stb_sync_new(void)
11654 {
11655 stb_sync s = (stb_sync) malloc(sizeof(*s));
11656 if (!s) return s;
11657
11658 s->target = s->sofar = s->waiting = 0;
11659 s->mutex = stb_mutex_new();
11660 s->start = stb_mutex_new();
11661 s->release = stb_sem_new(1);
11662 if (s->mutex == STB_MUTEX_NULL || s->release == STB_SEMAPHORE_NULL || s->start == STB_MUTEX_NULL) {
11663 stb_mutex_delete(s->mutex);
11664 stb_mutex_delete(s->mutex);
11665 stb_sem_delete(s->release);
11666 free(s);
11667 return NULL;
11668 }
11669 return s;
11670 }
11671
11672 void stb_sync_delete(stb_sync s)
11673 {
11674 if (s->waiting) {
11675 // it's bad to delete while there are threads waiting!
11676 // shall we wait for them to reach, or just bail? just bail
11677 assert(0);
11678 }
11679 stb_mutex_delete(s->mutex);
11680 stb_mutex_delete(s->release);
11681 free(s);
11682 }
11683
11684 int stb_sync_set_target(stb_sync s, int count)
11685 {
11686 // don't allow setting a target until the last one is fully released;
11687 // note that this can lead to inefficient pipelining, and maybe we'd
11688 // be better off ping-ponging between two internal syncs?
11689 // I tried seeing how often this happened using TryEnterCriticalSection
11690 // and could _never_ get it to happen in imv(stb), even with more threads
11691 // than processors. So who knows!
11692 stb_mutex_begin(s->start);
11693
11694 // this mutex is pointless, since it's not valid for threads
11695 // to call reach() before anyone calls set_target() anyway
11696 stb_mutex_begin(s->mutex);
11697
11698 assert(s->target == 0); // enforced by start mutex
11699 s->target = count;
11700 s->sofar = 0;
11701 s->waiting = 0;
11702 stb_mutex_end(s->mutex);
11703 return STB_TRUE;
11704 }
11705
11706 void stb__sync_release(stb_sync s)
11707 {
11708 if (s->waiting)
11709 stb_sem_release(s->release);
11710 else {
11711 s->target = 0;
11712 stb_mutex_end(s->start);
11713 }
11714 }
11715
11716 int stb_sync_reach(stb_sync s)
11717 {
11718 int n;
11719 stb_mutex_begin(s->mutex);
11720 assert(s->sofar < s->target);
11721 n = ++s->sofar; // record this value to avoid possible race if we did 'return s->sofar';
11722 if (s->sofar == s->target)
11723 stb__sync_release(s);
11724 stb_mutex_end(s->mutex);
11725 return n;
11726 }
11727
11728 void stb_sync_reach_and_wait(stb_sync s)
11729 {
11730 stb_mutex_begin(s->mutex);
11731 assert(s->sofar < s->target);
11732 ++s->sofar;
11733 if (s->sofar == s->target) {
11734 stb__sync_release(s);
11735 stb_mutex_end(s->mutex);
11736 } else {
11737 ++s->waiting; // we're waiting, so one more waiter
11738 stb_mutex_end(s->mutex); // release the mutex to other threads
11739
11740 stb_sem_waitfor(s->release); // wait for merge completion
11741
11742 stb_mutex_begin(s->mutex); // on merge completion, grab the mutex
11743 --s->waiting; // we're done waiting
11744 stb__sync_release(s); // restart the next waiter
11745 stb_mutex_end(s->mutex); // and now we're done
11746 // this ends the same as the first case, but it's a lot
11747 // clearer to understand without sharing the code
11748 }
11749 }
11750
11751 struct stb__threadqueue
11752 {
11753 stb_mutex add, remove;
11754 stb_semaphore nonempty, nonfull;
11755 int head_blockers; // number of threads blocking--used to know whether to release(avail)
11756 int tail_blockers;
11757 int head, tail, array_size, growable;
11758 int item_size;
11759 char *data;
11760 };
11761
11762 static int stb__tq_wrap(volatile stb_threadqueue *z, int p)
11763 {
11764 if (p == z->array_size)
11765 return p - z->array_size;
11766 else
11767 return p;
11768 }
11769
11770 int stb__threadq_get_raw(stb_threadqueue *tq2, void *output, int block)
11771 {
11772 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11773 if (tq->head == tq->tail && !block) return 0;
11774
11775 stb_mutex_begin(tq->remove);
11776
11777 while (tq->head == tq->tail) {
11778 if (!block) {
11779 stb_mutex_end(tq->remove);
11780 return 0;
11781 }
11782 ++tq->head_blockers;
11783 stb_mutex_end(tq->remove);
11784
11785 stb_sem_waitfor(tq->nonempty);
11786
11787 stb_mutex_begin(tq->remove);
11788 --tq->head_blockers;
11789 }
11790
11791 memcpy(output, tq->data + tq->head*tq->item_size, tq->item_size);
11792 stb_barrier();
11793 tq->head = stb__tq_wrap(tq, tq->head+1);
11794
11795 stb_sem_release(tq->nonfull);
11796 if (tq->head_blockers) // can't check if actually non-empty due to race?
11797 stb_sem_release(tq->nonempty); // if there are other blockers, wake one
11798
11799 stb_mutex_end(tq->remove);
11800 return STB_TRUE;
11801 }
11802
11803 int stb__threadq_grow(volatile stb_threadqueue *tq)
11804 {
11805 int n;
11806 char *p;
11807 assert(tq->remove != STB_MUTEX_NULL); // must have this to allow growth!
11808 stb_mutex_begin(tq->remove);
11809
11810 n = tq->array_size * 2;
11811 p = (char *) realloc(tq->data, n * tq->item_size);
11812 if (p == NULL) {
11813 stb_mutex_end(tq->remove);
11814 stb_mutex_end(tq->add);
11815 return STB_FALSE;
11816 }
11817 if (tq->tail < tq->head) {
11818 memcpy(p + tq->array_size * tq->item_size, p, tq->tail * tq->item_size);
11819 tq->tail += tq->array_size;
11820 }
11821 tq->data = p;
11822 tq->array_size = n;
11823
11824 stb_mutex_end(tq->remove);
11825 return STB_TRUE;
11826 }
11827
11828 int stb__threadq_add_raw(stb_threadqueue *tq2, void *input, int block)
11829 {
11830 int tail,pos;
11831 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11832 stb_mutex_begin(tq->add);
11833 for(;;) {
11834 pos = tq->tail;
11835 tail = stb__tq_wrap(tq, pos+1);
11836 if (tail != tq->head) break;
11837
11838 // full
11839 if (tq->growable) {
11840 if (!stb__threadq_grow(tq)) {
11841 stb_mutex_end(tq->add);
11842 return STB_FALSE; // out of memory
11843 }
11844 } else if (!block) {
11845 stb_mutex_end(tq->add);
11846 return STB_FALSE;
11847 } else {
11848 ++tq->tail_blockers;
11849 stb_mutex_end(tq->add);
11850
11851 stb_sem_waitfor(tq->nonfull);
11852
11853 stb_mutex_begin(tq->add);
11854 --tq->tail_blockers;
11855 }
11856 }
11857 memcpy(tq->data + tq->item_size * pos, input, tq->item_size);
11858 stb_barrier();
11859 tq->tail = tail;
11860 stb_sem_release(tq->nonempty);
11861 if (tq->tail_blockers) // can't check if actually non-full due to race?
11862 stb_sem_release(tq->nonfull);
11863 stb_mutex_end(tq->add);
11864 return STB_TRUE;
11865 }
11866
11867 int stb_threadq_length(stb_threadqueue *tq2)
11868 {
11869 int a,b,n;
11870 volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
11871 stb_mutex_begin(tq->add);
11872 a = tq->head;
11873 b = tq->tail;
11874 n = tq->array_size;
11875 stb_mutex_end(tq->add);
11876 if (a > b) b += n;
11877 return b-a;
11878 }
11879
11880 int stb_threadq_get(stb_threadqueue *tq, void *output)
11881 {
11882 return stb__threadq_get_raw(tq, output, STB_FALSE);
11883 }
11884
11885 void stb_threadq_get_block(stb_threadqueue *tq, void *output)
11886 {
11887 stb__threadq_get_raw(tq, output, STB_TRUE);
11888 }
11889
11890 int stb_threadq_add(stb_threadqueue *tq, void *input)
11891 {
11892 return stb__threadq_add_raw(tq, input, STB_FALSE);
11893 }
11894
11895 int stb_threadq_add_block(stb_threadqueue *tq, void *input)
11896 {
11897 return stb__threadq_add_raw(tq, input, STB_TRUE);
11898 }
11899
11900 void stb_threadq_delete(stb_threadqueue *tq)
11901 {
11902 if (tq) {
11903 free(tq->data);
11904 stb_mutex_delete(tq->add);
11905 stb_mutex_delete(tq->remove);
11906 stb_sem_delete(tq->nonempty);
11907 stb_sem_delete(tq->nonfull);
11908 free(tq);
11909 }
11910 }
11911
11912 #define STB_THREADQUEUE_DYNAMIC 0
11913 stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove)
11914 {
11915 int error=0;
11916 stb_threadqueue *tq = (stb_threadqueue *) malloc(sizeof(*tq));
11917 if (tq == NULL) return NULL;
11918
11919 if (num_items == STB_THREADQUEUE_DYNAMIC) {
11920 tq->growable = STB_TRUE;
11921 num_items = 32;
11922 } else
11923 tq->growable = STB_FALSE;
11924
11925 tq->item_size = item_size;
11926 tq->array_size = num_items+1;
11927
11928 tq->add = tq->remove = STB_MUTEX_NULL;
11929 tq->nonempty = tq->nonfull = STB_SEMAPHORE_NULL;
11930 tq->data = NULL;
11931 if (many_add)
11932 { tq->add = stb_mutex_new(); if (tq->add == STB_MUTEX_NULL) goto error; }
11933 if (many_remove || tq->growable)
11934 { tq->remove = stb_mutex_new(); if (tq->remove == STB_MUTEX_NULL) goto error; }
11935 tq->nonempty = stb_sem_new(1); if (tq->nonempty == STB_SEMAPHORE_NULL) goto error;
11936 tq->nonfull = stb_sem_new(1); if (tq->nonfull == STB_SEMAPHORE_NULL) goto error;
11937 tq->data = (char *) malloc(tq->item_size * tq->array_size);
11938 if (tq->data == NULL) goto error;
11939
11940 tq->head = tq->tail = 0;
11941 tq->head_blockers = tq->tail_blockers = 0;
11942
11943 return tq;
11944
11945 error:
11946 stb_threadq_delete(tq);
11947 return NULL;
11948 }
11949
11950 typedef struct
11951 {
11952 stb_thread_func f;
11953 void *d;
11954 volatile void **retval;
11955 stb_sync sync;
11956 } stb__workinfo;
11957
11958 //static volatile stb__workinfo *stb__work;
11959
11960 struct stb__workqueue
11961 {
11962 int numthreads;
11963 stb_threadqueue *tq;
11964 };
11965
11966 static stb_workqueue *stb__work_global;
11967
11968 static void *stb__thread_workloop(void *p)
11969 {
11970 volatile stb_workqueue *q = (volatile stb_workqueue *) p;
11971 for(;;) {
11972 void *z;
11973 stb__workinfo w;
11974 stb_threadq_get_block(q->tq, &w);
11975 if (w.f == NULL) // null work is a signal to end the thread
11976 return NULL;
11977 z = w.f(w.d);
11978 if (w.retval) { stb_barrier(); *w.retval = z; }
11979 if (w.sync != STB_SYNC_NULL) stb_sync_reach(w.sync);
11980 }
11981 }
11982
11983 stb_workqueue *stb_workq_new(int num_threads, int max_units)
11984 {
11985 return stb_workq_new_flags(num_threads, max_units, 0,0);
11986 }
11987
11988 stb_workqueue *stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex)
11989 {
11990 stb_workqueue *q = (stb_workqueue *) malloc(sizeof(*q));
11991 if (q == NULL) return NULL;
11992 q->tq = stb_threadq_new(sizeof(stb__workinfo), max_units, !no_add_mutex, !no_remove_mutex);
11993 if (q->tq == NULL) { free(q); return NULL; }
11994 q->numthreads = 0;
11995 stb_workq_numthreads(q, numthreads);
11996 return q;
11997 }
11998
11999 void stb_workq_delete(stb_workqueue *q)
12000 {
12001 while (stb_workq_length(q) != 0)
12002 stb__thread_sleep(1);
12003 stb_threadq_delete(q->tq);
12004 free(q);
12005 }
12006
12007 static int stb__work_maxitems = STB_THREADQUEUE_DYNAMIC;
12008
12009 static void stb_work_init(int num_threads)
12010 {
12011 if (stb__work_global == NULL) {
12012 stb__threadmutex_init();
12013 stb_mutex_begin(stb__workmutex);
12014 stb_barrier();
12015 if (*(stb_workqueue * volatile *) &stb__work_global == NULL)
12016 stb__work_global = stb_workq_new(num_threads, stb__work_maxitems);
12017 stb_mutex_end(stb__workmutex);
12018 }
12019 }
12020
12021 static int stb__work_raw(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12022 {
12023 stb__workinfo w;
12024 if (q == NULL) {
12025 stb_work_init(1);
12026 q = stb__work_global;
12027 }
12028 w.f = f;
12029 w.d = d;
12030 w.retval = return_code;
12031 w.sync = rel;
12032 return stb_threadq_add(q->tq, &w);
12033 }
12034
12035 int stb_workq_length(stb_workqueue *q)
12036 {
12037 return stb_threadq_length(q->tq);
12038 }
12039
12040 int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code)
12041 {
12042 if (f == NULL) return 0;
12043 return stb_workq_reach(q, f, d, return_code, NULL);
12044 }
12045
12046 int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12047 {
12048 if (f == NULL) return 0;
12049 return stb__work_raw(q, f, d, return_code, rel);
12050 }
12051
12052 static void stb__workq_numthreads(stb_workqueue *q, int n)
12053 {
12054 while (q->numthreads < n) {
12055 stb_create_thread(stb__thread_workloop, q);
12056 ++q->numthreads;
12057 }
12058 while (q->numthreads > n) {
12059 stb__work_raw(q, NULL, NULL, NULL, NULL);
12060 --q->numthreads;
12061 }
12062 }
12063
12064 void stb_workq_numthreads(stb_workqueue *q, int n)
12065 {
12066 stb_mutex_begin(stb__threadmutex);
12067 stb__workq_numthreads(q,n);
12068 stb_mutex_end(stb__threadmutex);
12069 }
12070
12071 int stb_work_maxunits(int n)
12072 {
12073 if (stb__work_global == NULL) {
12074 stb__work_maxitems = n;
12075 stb_work_init(1);
12076 }
12077 return stb__work_maxitems;
12078 }
12079
12080 int stb_work(stb_thread_func f, void *d, volatile void **return_code)
12081 {
12082 return stb_workq(stb__work_global, f,d,return_code);
12083 }
12084
12085 int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
12086 {
12087 return stb_workq_reach(stb__work_global, f,d,return_code,rel);
12088 }
12089
12090 void stb_work_numthreads(int n)
12091 {
12092 if (stb__work_global == NULL)
12093 stb_work_init(n);
12094 else
12095 stb_workq_numthreads(stb__work_global, n);
12096 }
12097 #endif // STB_DEFINE
12098
12099
12100 //////////////////////////////////////////////////////////////////////////////
12101 //
12102 // Background disk I/O
12103 //
12104 //
12105
12106 #define STB_BGIO_READ_ALL (-1)
12107 STB_EXTERN int stb_bgio_read (char *filename, int offset, int len, stb_uchar **result, int *olen);
12108 STB_EXTERN int stb_bgio_readf (FILE *f , int offset, int len, stb_uchar **result, int *olen);
12109 STB_EXTERN int stb_bgio_read_to (char *filename, int offset, int len, stb_uchar *buffer, int *olen);
12110 STB_EXTERN int stb_bgio_readf_to(FILE *f , int offset, int len, stb_uchar *buffer, int *olen);
12111
12112 typedef struct
12113 {
12114 int have_data;
12115 int is_valid;
12116 int is_dir;
12117 time_t filetime;
12118 stb_int64 filesize;
12119 } stb_bgstat;
12120
12121 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result);
12122
12123 #ifdef STB_DEFINE
12124
12125 static stb_workqueue *stb__diskio;
12126 static stb_mutex stb__diskio_mutex;
12127
12128 void stb_thread_cleanup(void)
12129 {
12130 if (stb__work_global) stb_workq_delete(stb__work_global); stb__work_global = NULL;
12131 if (stb__threadmutex) stb_mutex_delete(stb__threadmutex); stb__threadmutex = NULL;
12132 if (stb__workmutex) stb_mutex_delete(stb__workmutex); stb__workmutex = NULL;
12133 if (stb__diskio) stb_workq_delete(stb__diskio); stb__diskio = NULL;
12134 if (stb__diskio_mutex)stb_mutex_delete(stb__diskio_mutex);stb__diskio_mutex= NULL;
12135 }
12136
12137
12138 typedef struct
12139 {
12140 char *filename;
12141 FILE *f;
12142 int offset;
12143 int len;
12144
12145 stb_bgstat *stat_out;
12146 stb_uchar *output;
12147 stb_uchar **result;
12148 int *len_output;
12149 int *flag;
12150 } stb__disk_command;
12151
12152 #define STB__MAX_DISK_COMMAND 100
12153 static stb__disk_command stb__dc_queue[STB__MAX_DISK_COMMAND];
12154 static int stb__dc_offset;
12155
12156 void stb__io_init(void)
12157 {
12158 if (!stb__diskio) {
12159 stb__threadmutex_init();
12160 stb_mutex_begin(stb__threadmutex);
12161 stb_barrier();
12162 if (*(stb_thread * volatile *) &stb__diskio == NULL) {
12163 stb__diskio_mutex = stb_mutex_new();
12164 // use many threads so OS can try to schedule seeks
12165 stb__diskio = stb_workq_new_flags(16,STB__MAX_DISK_COMMAND,STB_FALSE,STB_FALSE);
12166 }
12167 stb_mutex_end(stb__threadmutex);
12168 }
12169 }
12170
12171 static void * stb__io_error(stb__disk_command *dc)
12172 {
12173 if (dc->len_output) *dc->len_output = 0;
12174 if (dc->result) *dc->result = NULL;
12175 if (dc->flag) *dc->flag = -1;
12176 return NULL;
12177 }
12178
12179 static void * stb__io_task(void *p)
12180 {
12181 stb__disk_command *dc = (stb__disk_command *) p;
12182 int len;
12183 FILE *f;
12184 stb_uchar *buf;
12185
12186 if (dc->stat_out) {
12187 struct _stati64 s;
12188 if (!_stati64(dc->filename, &s)) {
12189 dc->stat_out->filesize = s.st_size;
12190 dc->stat_out->filetime = s.st_mtime;
12191 dc->stat_out->is_dir = s.st_mode & _S_IFDIR;
12192 dc->stat_out->is_valid = (s.st_mode & _S_IFREG) || dc->stat_out->is_dir;
12193 } else
12194 dc->stat_out->is_valid = 0;
12195 stb_barrier();
12196 dc->stat_out->have_data = 1;
12197 free(dc->filename);
12198 return 0;
12199 }
12200 if (dc->f) {
12201 #ifdef WIN32
12202 f = _fdopen(_dup(_fileno(dc->f)), "rb");
12203 #else
12204 f = fdopen(dup(fileno(dc->f)), "rb");
12205 #endif
12206 if (!f)
12207 return stb__io_error(dc);
12208 } else {
12209 f = fopen(dc->filename, "rb");
12210 free(dc->filename);
12211 if (!f)
12212 return stb__io_error(dc);
12213 }
12214
12215 len = dc->len;
12216 if (len < 0) {
12217 fseek(f, 0, SEEK_END);
12218 len = ftell(f) - dc->offset;
12219 }
12220
12221 if (fseek(f, dc->offset, SEEK_SET)) {
12222 fclose(f);
12223 return stb__io_error(dc);
12224 }
12225
12226 if (dc->output)
12227 buf = dc->output;
12228 else {
12229 buf = (stb_uchar *) malloc(len);
12230 if (buf == NULL) {
12231 fclose(f);
12232 return stb__io_error(dc);
12233 }
12234 }
12235
12236 len = fread(buf, 1, len, f);
12237 fclose(f);
12238 if (dc->len_output) *dc->len_output = len;
12239 if (dc->result) *dc->result = buf;
12240 if (dc->flag) *dc->flag = 1;
12241
12242 return NULL;
12243 }
12244
12245 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)
12246 {
12247 int res;
12248 stb__io_init();
12249 // do memory allocation outside of mutex
12250 if (fname) fname = strdup(fname);
12251 stb_mutex_begin(stb__diskio_mutex);
12252 {
12253 stb__disk_command *dc = &stb__dc_queue[stb__dc_offset];
12254 dc->filename = fname;
12255 dc->f = f;
12256 dc->offset = off;
12257 dc->len = len;
12258 dc->output = out;
12259 dc->result = result;
12260 dc->len_output = olen;
12261 dc->flag = flag;
12262 dc->stat_out = stat;
12263 res = stb_workq(stb__diskio, stb__io_task, dc, NULL);
12264 if (res)
12265 stb__dc_offset = (stb__dc_offset + 1 == STB__MAX_DISK_COMMAND ? 0 : stb__dc_offset+1);
12266 }
12267 stb_mutex_end(stb__diskio_mutex);
12268 return res;
12269 }
12270
12271 int stb_bgio_read(char *filename, int offset, int len, stb_uchar **result, int *olen)
12272 {
12273 return stb__io_add(filename,NULL,offset,len,NULL,result,olen,NULL,NULL);
12274 }
12275
12276 int stb_bgio_readf(FILE *f, int offset, int len, stb_uchar **result, int *olen)
12277 {
12278 return stb__io_add(NULL,f,offset,len,NULL,result,olen,NULL,NULL);
12279 }
12280
12281 int stb_bgio_read_to(char *filename, int offset, int len, stb_uchar *buffer, int *olen)
12282 {
12283 return stb__io_add(filename,NULL,offset,len,buffer,NULL,olen,NULL,NULL);
12284 }
12285
12286 int stb_bgio_readf_to(FILE *f, int offset, int len, stb_uchar *buffer, int *olen)
12287 {
12288 return stb__io_add(NULL,f,offset,len,buffer,NULL,olen,NULL,NULL);
12289 }
12290
12291 STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result)
12292 {
12293 result->have_data = 0;
12294 return stb__io_add(filename,NULL,0,0,0,NULL,0,NULL, result);
12295 }
12296 #endif
12297 #endif
12298
12299
12300
12301 //////////////////////////////////////////////////////////////////////////////
12302 //
12303 // Fast malloc implementation
12304 //
12305 // This is a clone of TCMalloc, but without the thread support.
12306 // 1. large objects are allocated directly, page-aligned
12307 // 2. small objects are allocated in homogeonous heaps, 0 overhead
12308 //
12309 // We keep an allocation table for pages a la TCMalloc. This would
12310 // require 4MB for the entire address space, but we only allocate
12311 // the parts that are in use. The overhead from using homogenous heaps
12312 // everywhere is 3MB. (That is, if you allocate 1 object of each size,
12313 // you'll use 3MB.)
12314
12315 #if defined(STB_DEFINE) && (defined(_WIN32) || defined(STB_FASTMALLOC))
12316
12317 #ifdef _WIN32
12318 #ifndef _WINDOWS_
12319 #ifndef STB__IMPORT
12320 #define STB__IMPORT STB_EXTERN __declspec(dllimport)
12321 #define STB__DW unsigned long
12322 #endif
12323 STB__IMPORT void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
12324 STB__IMPORT int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
12325 #endif
12326 #define stb__alloc_pages_raw(x) (stb_uint32) VirtualAlloc(NULL, (x), 0x3000, 0x04)
12327 #define stb__dealloc_pages_raw(p) VirtualFree((void *) p, 0, 0x8000)
12328 #else
12329 #error "Platform not currently supported"
12330 #endif
12331
12332 typedef struct stb__span
12333 {
12334 int start, len;
12335 struct stb__span *next, *prev;
12336 void *first_free;
12337 unsigned short list; // 1..256 free; 257..511 sizeclass; 0=large block
12338 short allocations; // # outstanding allocations for sizeclass
12339 } stb__span; // 24
12340
12341 static stb__span **stb__span_for_page;
12342 static int stb__firstpage, stb__lastpage;
12343 static void stb__update_page_range(int first, int last)
12344 {
12345 stb__span **sfp;
12346 int i, f,l;
12347 if (first >= stb__firstpage && last <= stb__lastpage) return;
12348 if (stb__span_for_page == NULL) {
12349 f = first;
12350 l = f+stb_max(last-f, 16384);
12351 l = stb_min(l, 1<<20);
12352 } else if (last > stb__lastpage) {
12353 f = stb__firstpage;
12354 l = f + (stb__lastpage - f) * 2;
12355 l = stb_clamp(last, l,1<<20);
12356 } else {
12357 l = stb__lastpage;
12358 f = l - (l - stb__firstpage) * 2;
12359 f = stb_clamp(f, 0,first);
12360 }
12361 sfp = (stb__span **) stb__alloc_pages_raw(sizeof(void *) * (l-f));
12362 for (i=f; i < stb__firstpage; ++i) sfp[i - f] = NULL;
12363 for ( ; i < stb__lastpage ; ++i) sfp[i - f] = stb__span_for_page[i - stb__firstpage];
12364 for ( ; i < l ; ++i) sfp[i - f] = NULL;
12365 if (stb__span_for_page) stb__dealloc_pages_raw(stb__span_for_page);
12366 stb__firstpage = f;
12367 stb__lastpage = l;
12368 stb__span_for_page = sfp;
12369 }
12370
12371 static stb__span *stb__span_free=NULL;
12372 static stb__span *stb__span_first, *stb__span_end;
12373 static stb__span *stb__span_alloc(void)
12374 {
12375 stb__span *s = stb__span_free;
12376 if (s)
12377 stb__span_free = s->next;
12378 else {
12379 if (!stb__span_first) {
12380 stb__span_first = (stb__span *) stb__alloc_pages_raw(65536);
12381 if (stb__span_first == NULL) return NULL;
12382 stb__span_end = stb__span_first + (65536 / sizeof(stb__span));
12383 }
12384 s = stb__span_first++;
12385 if (stb__span_first == stb__span_end) stb__span_first = NULL;
12386 }
12387 return s;
12388 }
12389
12390 static stb__span *stb__spanlist[512];
12391
12392 static void stb__spanlist_unlink(stb__span *s)
12393 {
12394 if (s->prev)
12395 s->prev->next = s->next;
12396 else {
12397 int n = s->list;
12398 assert(stb__spanlist[n] == s);
12399 stb__spanlist[n] = s->next;
12400 }
12401 if (s->next)
12402 s->next->prev = s->prev;
12403 s->next = s->prev = NULL;
12404 s->list = 0;
12405 }
12406
12407 static void stb__spanlist_add(int n, stb__span *s)
12408 {
12409 s->list = n;
12410 s->next = stb__spanlist[n];
12411 s->prev = NULL;
12412 stb__spanlist[n] = s;
12413 if (s->next) s->next->prev = s;
12414 }
12415
12416 #define stb__page_shift 12
12417 #define stb__page_size (1 << stb__page_shift)
12418 #define stb__page_number(x) ((x) >> stb__page_shift)
12419 #define stb__page_address(x) ((x) << stb__page_shift)
12420
12421 static void stb__set_span_for_page(stb__span *s)
12422 {
12423 int i;
12424 for (i=0; i < s->len; ++i)
12425 stb__span_for_page[s->start + i - stb__firstpage] = s;
12426 }
12427
12428 static stb__span *stb__coalesce(stb__span *a, stb__span *b)
12429 {
12430 assert(a->start + a->len == b->start);
12431 if (a->list) stb__spanlist_unlink(a);
12432 if (b->list) stb__spanlist_unlink(b);
12433 a->len += b->len;
12434 b->len = 0;
12435 b->next = stb__span_free;
12436 stb__span_free = b;
12437 stb__set_span_for_page(a);
12438 return a;
12439 }
12440
12441 static void stb__free_span(stb__span *s)
12442 {
12443 stb__span *n = NULL;
12444 if (s->start > stb__firstpage) {
12445 n = stb__span_for_page[s->start-1 - stb__firstpage];
12446 if (n && n->allocations == -2 && n->start + n->len == s->start) s = stb__coalesce(n,s);
12447 }
12448 if (s->start + s->len < stb__lastpage) {
12449 n = stb__span_for_page[s->start + s->len - stb__firstpage];
12450 if (n && n->allocations == -2 && s->start + s->len == n->start) s = stb__coalesce(s,n);
12451 }
12452 s->allocations = -2;
12453 stb__spanlist_add(s->len > 256 ? 256 : s->len, s);
12454 }
12455
12456 static stb__span *stb__alloc_pages(int num)
12457 {
12458 stb__span *s = stb__span_alloc();
12459 int p;
12460 if (!s) return NULL;
12461 p = stb__alloc_pages_raw(num << stb__page_shift);
12462 if (p == 0) { s->next = stb__span_free; stb__span_free = s; return 0; }
12463 assert(stb__page_address(stb__page_number(p)) == p);
12464 p = stb__page_number(p);
12465 stb__update_page_range(p, p+num);
12466 s->start = p;
12467 s->len = num;
12468 s->next = NULL;
12469 s->prev = NULL;
12470 stb__set_span_for_page(s);
12471 return s;
12472 }
12473
12474 static stb__span *stb__alloc_span(int pagecount)
12475 {
12476 int i;
12477 stb__span *p = NULL;
12478 for(i=pagecount; i < 256; ++i)
12479 if (stb__spanlist[i]) {
12480 p = stb__spanlist[i];
12481 break;
12482 }
12483 if (!p) {
12484 p = stb__spanlist[256];
12485 while (p && p->len < pagecount)
12486 p = p->next;
12487 }
12488 if (!p) {
12489 p = stb__alloc_pages(pagecount < 16 ? 16 : pagecount);
12490 if (p == NULL) return 0;
12491 } else
12492 stb__spanlist_unlink(p);
12493
12494 if (p->len > pagecount) {
12495 stb__span *q = stb__span_alloc();
12496 if (q) {
12497 q->start = p->start + pagecount;
12498 q->len = p->len - pagecount;
12499 p->len = pagecount;
12500 for (i=0; i < q->len; ++i)
12501 stb__span_for_page[q->start+i - stb__firstpage] = q;
12502 stb__spanlist_add(q->len > 256 ? 256 : q->len, q);
12503 }
12504 }
12505 return p;
12506 }
12507
12508 #define STB__MAX_SMALL_SIZE 32768
12509 #define STB__MAX_SIZE_CLASSES 256
12510
12511 static unsigned char stb__class_base[32];
12512 static unsigned char stb__class_shift[32];
12513 static unsigned char stb__pages_for_class[STB__MAX_SIZE_CLASSES];
12514 static int stb__size_for_class[STB__MAX_SIZE_CLASSES];
12515
12516 stb__span *stb__get_nonempty_sizeclass(int c)
12517 {
12518 int s = c + 256, i, size, tsize; // remap to span-list index
12519 char *z;
12520 void *q;
12521 stb__span *p = stb__spanlist[s];
12522 if (p) {
12523 if (p->first_free) return p; // fast path: it's in the first one in list
12524 for (p=p->next; p; p=p->next)
12525 if (p->first_free) {
12526 // move to front for future queries
12527 stb__spanlist_unlink(p);
12528 stb__spanlist_add(s, p);
12529 return p;
12530 }
12531 }
12532 // no non-empty ones, so allocate a new one
12533 p = stb__alloc_span(stb__pages_for_class[c]);
12534 if (!p) return NULL;
12535 // create the free list up front
12536 size = stb__size_for_class[c];
12537 tsize = stb__pages_for_class[c] << stb__page_shift;
12538 i = 0;
12539 z = (char *) stb__page_address(p->start);
12540 q = NULL;
12541 while (i + size <= tsize) {
12542 * (void **) z = q; q = z;
12543 z += size;
12544 i += size;
12545 }
12546 p->first_free = q;
12547 p->allocations = 0;
12548 stb__spanlist_add(s,p);
12549 return p;
12550 }
12551
12552 static int stb__sizeclass(size_t sz)
12553 {
12554 int z = stb_log2_floor(sz); // -1 below to group e.g. 13,14,15,16 correctly
12555 return stb__class_base[z] + ((sz-1) >> stb__class_shift[z]);
12556 }
12557
12558 static void stb__init_sizeclass(void)
12559 {
12560 int i, size, overhead;
12561 int align_shift = 2; // allow 4-byte and 12-byte blocks as well, vs. TCMalloc
12562 int next_class = 1;
12563 int last_log = 0;
12564
12565 for (i = 0; i < align_shift; i++) {
12566 stb__class_base [i] = next_class;
12567 stb__class_shift[i] = align_shift;
12568 }
12569
12570 for (size = 1 << align_shift; size <= STB__MAX_SMALL_SIZE; size += 1 << align_shift) {
12571 i = stb_log2_floor(size);
12572 if (i > last_log) {
12573 if (size == 16) ++align_shift; // switch from 4-byte to 8-byte alignment
12574 else if (size >= 128 && align_shift < 8) ++align_shift;
12575 stb__class_base[i] = next_class - ((size-1) >> align_shift);
12576 stb__class_shift[i] = align_shift;
12577 last_log = i;
12578 }
12579 stb__size_for_class[next_class++] = size;
12580 }
12581
12582 for (i=1; i <= STB__MAX_SMALL_SIZE; ++i)
12583 assert(i <= stb__size_for_class[stb__sizeclass(i)]);
12584
12585 overhead = 0;
12586 for (i = 1; i < next_class; i++) {
12587 int s = stb__size_for_class[i];
12588 size = stb__page_size;
12589 while (size % s > size >> 3)
12590 size += stb__page_size;
12591 stb__pages_for_class[i] = (unsigned char) (size >> stb__page_shift);
12592 overhead += size;
12593 }
12594 assert(overhead < (4 << 20)); // make sure it's under 4MB of overhead
12595 }
12596
12597 #ifdef STB_DEBUG
12598 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12599 #elif defined(STB_FASTMALLOC_INIT)
12600 #define stb__smemset(a,b,c) memset((void *) a, b, c)
12601 #else
12602 #define stb__smemset(a,b,c)
12603 #endif
12604 void *stb_smalloc(size_t sz)
12605 {
12606 stb__span *s;
12607 if (sz == 0) return NULL;
12608 if (stb__size_for_class[1] == 0) stb__init_sizeclass();
12609 if (sz > STB__MAX_SMALL_SIZE) {
12610 s = stb__alloc_span((sz + stb__page_size - 1) >> stb__page_shift);
12611 if (s == NULL) return NULL;
12612 s->list = 0;
12613 s->next = s->prev = NULL;
12614 s->allocations = -32767;
12615 stb__smemset(stb__page_address(s->start), 0xcd, (sz+3)&~3);
12616 return (void *) stb__page_address(s->start);
12617 } else {
12618 void *p;
12619 int c = stb__sizeclass(sz);
12620 s = stb__spanlist[256+c];
12621 if (!s || !s->first_free)
12622 s = stb__get_nonempty_sizeclass(c);
12623 if (s == NULL) return NULL;
12624 p = s->first_free;
12625 s->first_free = * (void **) p;
12626 ++s->allocations;
12627 stb__smemset(p,0xcd, sz);
12628 return p;
12629 }
12630 }
12631
12632 int stb_ssize(void *p)
12633 {
12634 stb__span *s;
12635 if (p == NULL) return 0;
12636 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12637 if (s->list >= 256) {
12638 return stb__size_for_class[s->list - 256];
12639 } else {
12640 assert(s->list == 0);
12641 return s->len << stb__page_shift;
12642 }
12643 }
12644
12645 void stb_sfree(void *p)
12646 {
12647 stb__span *s;
12648 if (p == NULL) return;
12649 s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
12650 if (s->list >= 256) {
12651 stb__smemset(p, 0xfe, stb__size_for_class[s->list-256]);
12652 * (void **) p = s->first_free;
12653 s->first_free = p;
12654 if (--s->allocations == 0) {
12655 stb__spanlist_unlink(s);
12656 stb__free_span(s);
12657 }
12658 } else {
12659 assert(s->list == 0);
12660 stb__smemset(p, 0xfe, stb_ssize(p));
12661 stb__free_span(s);
12662 }
12663 }
12664
12665 void *stb_srealloc(void *p, size_t sz)
12666 {
12667 size_t cur_size;
12668 if (p == NULL) return stb_smalloc(sz);
12669 if (sz == 0) { stb_sfree(p); return NULL; }
12670 cur_size = stb_ssize(p);
12671 if (sz > cur_size || sz <= (cur_size >> 1)) {
12672 void *q;
12673 if (sz > cur_size && sz < (cur_size << 1)) sz = cur_size << 1;
12674 q = stb_smalloc(sz); if (q == NULL) return NULL;
12675 memcpy(q, p, sz < cur_size ? sz : cur_size);
12676 stb_sfree(p);
12677 return q;
12678 }
12679 return p;
12680 }
12681
12682 void *stb_scalloc(size_t n, size_t sz)
12683 {
12684 void *p;
12685 if (n == 0 || sz == 0) return NULL;
12686 if (stb_log2_ceil(n) + stb_log2_ceil(n) >= 32) return NULL;
12687 p = stb_smalloc(n*sz);
12688 if (p) memset(p, 0, n*sz);
12689 return p;
12690 }
12691
12692 char *stb_sstrdup(char *s)
12693 {
12694 int n = strlen(s);
12695 char *p = (char *) stb_smalloc(n+1);
12696 if (p) strcpy(p,s);
12697 return p;
12698 }
12699 #endif // STB_DEFINE
12700
12701
12702
12703 //////////////////////////////////////////////////////////////////////////////
12704 //
12705 // Source code constants
12706 //
12707 // This is a trivial system to let you specify constants in source code,
12708 // then while running you can change the constants.
12709 //
12710 // Note that you can't wrap the #defines, because we need to know their
12711 // names. So we provide a pre-wrapped version without 'STB_' for convenience;
12712 // to request it, #define STB_CONVENIENT_H, yielding:
12713 // KI -- integer
12714 // KU -- unsigned integer
12715 // KF -- float
12716 // KD -- double
12717 // KS -- string constant
12718 //
12719 // Defaults to functioning in debug build, not in release builds.
12720 // To force on, define STB_ALWAYS_H
12721
12722 #ifdef STB_CONVENIENT_H
12723 #define KI(x) STB_I(x)
12724 #define KU(x) STB_UI(x)
12725 #define KF(x) STB_F(x)
12726 #define KD(x) STB_D(x)
12727 #define KS(x) STB_S(x)
12728 #endif
12729
12730 STB_EXTERN void stb_source_path(char *str);
12731 #ifdef STB_DEFINE
12732 char *stb__source_path;
12733 void stb_source_path(char *path)
12734 {
12735 stb__source_path = path;
12736 }
12737
12738 char *stb__get_sourcefile_path(char *file)
12739 {
12740 static char filebuf[512];
12741 if (stb__source_path) {
12742 sprintf(filebuf, "%s/%s", stb__source_path, file);
12743 if (stb_fexists(filebuf)) return filebuf;
12744 }
12745
12746 if (stb_fexists(file)) return file;
12747
12748 sprintf(filebuf, "../%s", file);
12749 if (!stb_fexists(filebuf)) return filebuf;
12750
12751 return file;
12752 }
12753 #endif
12754
12755 #define STB_F(x) ((float) STB_H(x))
12756 #define STB_UI(x) ((unsigned int) STB_I(x))
12757
12758 #if !defined(STB_DEBUG) && !defined(STB_ALWAYS_H)
12759 #define STB_D(x) ((double) (x))
12760 #define STB_I(x) ((int) (x))
12761 #define STB_S(x) ((char *) (x))
12762 #else
12763 #define STB_D(x) stb__double_constant(__FILE__, __LINE__-1, (x))
12764 #define STB_I(x) stb__int_constant(__FILE__, __LINE__-1, (x))
12765 #define STB_S(x) stb__string_constant(__FILE__, __LINE__-1, (x))
12766
12767 STB_EXTERN double stb__double_constant(char *file, int line, double x);
12768 STB_EXTERN int stb__int_constant(char *file, int line, int x);
12769 STB_EXTERN char * stb__string_constant(char *file, int line, char *str);
12770
12771 #ifdef STB_DEFINE
12772
12773 enum
12774 {
12775 STB__CTYPE_int,
12776 STB__CTYPE_uint,
12777 STB__CTYPE_float,
12778 STB__CTYPE_double,
12779 STB__CTYPE_string,
12780 };
12781
12782 typedef struct
12783 {
12784 int line;
12785 int type;
12786 union {
12787 int ival;
12788 double dval;
12789 char *sval;
12790 };
12791 } stb__Entry;
12792
12793 typedef struct
12794 {
12795 stb__Entry *entries;
12796 char *filename;
12797 time_t timestamp;
12798 char **file_data;
12799 int file_len;
12800 unsigned short *line_index;
12801 } stb__FileEntry;
12802
12803 static void stb__constant_parse(stb__FileEntry *f, int i)
12804 {
12805 char *s;
12806 int n;
12807 if (!stb_arr_valid(f->entries, i)) return;
12808 n = f->entries[i].line;
12809 if (n >= f->file_len) return;
12810 s = f->file_data[n];
12811 switch (f->entries[i].type) {
12812 case STB__CTYPE_float:
12813 while (*s) {
12814 if (!strncmp(s, "STB_D(", 6)) { s+=6; goto matched_float; }
12815 if (!strncmp(s, "STB_F(", 6)) { s+=6; goto matched_float; }
12816 if (!strncmp(s, "KD(", 3)) { s+=3; goto matched_float; }
12817 if (!strncmp(s, "KF(", 3)) { s+=3; goto matched_float; }
12818 ++s;
12819 }
12820 break;
12821 matched_float:
12822 f->entries[i].dval = strtod(s, NULL);
12823 break;
12824 case STB__CTYPE_int:
12825 while (*s) {
12826 if (!strncmp(s, "STB_I(", 6)) { s+=6; goto matched_int; }
12827 if (!strncmp(s, "STB_UI(", 7)) { s+=7; goto matched_int; }
12828 if (!strncmp(s, "KI(", 3)) { s+=3; goto matched_int; }
12829 if (!strncmp(s, "KU(", 3)) { s+=3; goto matched_int; }
12830 ++s;
12831 }
12832 break;
12833 matched_int: {
12834 int neg=0;
12835 s = stb_skipwhite(s);
12836 while (*s == '-') { neg = !neg; s = stb_skipwhite(s+1); } // handle '- - 5', pointlessly
12837 if (s[0] == '0' && tolower(s[1]) == 'x')
12838 f->entries[i].ival = strtol(s, NULL, 16);
12839 else if (s[0] == '0')
12840 f->entries[i].ival = strtol(s, NULL, 8);
12841 else
12842 f->entries[i].ival = strtol(s, NULL, 10);
12843 if (neg) f->entries[i].ival = -f->entries[i].ival;
12844 break;
12845 }
12846 case STB__CTYPE_string:
12847 // @TODO
12848 break;
12849 }
12850 }
12851
12852 static stb_sdict *stb__constant_file_hash;
12853
12854 stb__Entry *stb__constant_get_entry(char *filename, int line, int type)
12855 {
12856 int i;
12857 stb__FileEntry *f;
12858 if (stb__constant_file_hash == NULL)
12859 stb__constant_file_hash = stb_sdict_new(STB_TRUE);
12860 f = (stb__FileEntry*) stb_sdict_get(stb__constant_file_hash, filename);
12861 if (f == NULL) {
12862 char *s = stb__get_sourcefile_path(filename);
12863 if (s == NULL || !stb_fexists(s)) return 0;
12864 f = (stb__FileEntry *) malloc(sizeof(*f));
12865 f->timestamp = stb_ftimestamp(s);
12866 f->file_data = stb_stringfile(s, &f->file_len);
12867 f->filename = strdup(s); // cache the full path
12868 f->entries = NULL;
12869 f->line_index = 0;
12870 stb_arr_setlen(f->line_index, f->file_len);
12871 memset(f->line_index, 0xff, stb_arr_storage(f->line_index));
12872 } else {
12873 time_t t = stb_ftimestamp(f->filename);
12874 if (f->timestamp != t) {
12875 f->timestamp = t;
12876 free(f->file_data);
12877 f->file_data = stb_stringfile(f->filename, &f->file_len);
12878 stb_arr_setlen(f->line_index, f->file_len);
12879 for (i=0; i < stb_arr_len(f->entries); ++i)
12880 stb__constant_parse(f, i);
12881 }
12882 }
12883
12884 if (line >= f->file_len) return 0;
12885
12886 if (f->line_index[line] >= stb_arr_len(f->entries)) {
12887 // need a new entry
12888 int n = stb_arr_len(f->entries);
12889 stb__Entry e;
12890 e.line = line;
12891 if (line < f->file_len)
12892 f->line_index[line] = n;
12893 e.type = type;
12894 stb_arr_push(f->entries, e);
12895 stb__constant_parse(f, n);
12896 }
12897 return f->entries + f->line_index[line];
12898 }
12899
12900 double stb__double_constant(char *file, int line, double x)
12901 {
12902 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_float);
12903 if (!e) return x;
12904 return e->dval;
12905 }
12906
12907 int stb__int_constant(char *file, int line, int x)
12908 {
12909 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_int);
12910 if (!e) return x;
12911 return e->ival;
12912 }
12913
12914 char * stb__string_constant(char *file, int line, char *x)
12915 {
12916 stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_string);
12917 if (!e) return x;
12918 return e->sval;
12919 }
12920
12921 #endif // STB_DEFINE
12922 #endif // !STB_DEBUG && !STB_ALWAYS_H
12923
12924
12925 #ifdef STB_STUA
12926 //////////////////////////////////////////////////////////////////////////
12927 //
12928 // stua: little scripting language
12929 //
12930 // define STB_STUA to compile it
12931 //
12932 // see http://nothings.org/stb/stb_stua.html for documentation
12933 //
12934 // basic parsing model:
12935 //
12936 // lexical analysis
12937 // use stb_lex() to parse tokens; keywords get their own tokens
12938 //
12939 // parsing:
12940 // recursive descent parser. too much of a hassle to make an unambiguous
12941 // LR(1) grammar, and one-pass generation is clumsier (recursive descent
12942 // makes it easier to e.g. compile nested functions). on the other hand,
12943 // dictionary syntax required hackery to get extra lookahead.
12944 //
12945 // codegen:
12946 // output into an evaluation tree, using array indices as 'pointers'
12947 //
12948 // run:
12949 // traverse the tree; support for 'break/continue/return' is tricky
12950 //
12951 // garbage collection:
12952 // stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots
12953
12954 typedef stb_int32 stua_obj;
12955
12956 typedef stb_idict stua_dict;
12957
12958 STB_EXTERN void stua_run_script(char *s);
12959 STB_EXTERN void stua_uninit(void);
12960
12961 extern stua_obj stua_globals;
12962
12963 STB_EXTERN double stua_number(stua_obj z);
12964
12965 STB_EXTERN stua_obj stua_getnil(void);
12966 STB_EXTERN stua_obj stua_getfalse(void);
12967 STB_EXTERN stua_obj stua_gettrue(void);
12968 STB_EXTERN stua_obj stua_string(char *z);
12969 STB_EXTERN stua_obj stua_make_number(double d);
12970 STB_EXTERN stua_obj stua_box(int type, void *data, int size);
12971
12972 enum
12973 {
12974 STUA_op_negate=129,
12975 STUA_op_shl, STUA_op_ge,
12976 STUA_op_shr, STUA_op_le,
12977 STUA_op_shru,
12978 STUA_op_last
12979 };
12980
12981 #define STUA_NO_VALUE 2 // equivalent to a tagged NULL
12982 STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c);
12983
12984 STB_EXTERN stua_obj stua_error(char *err, ...);
12985
12986 STB_EXTERN stua_obj stua_pushroot(stua_obj o);
12987 STB_EXTERN void stua_poproot ( void );
12988
12989
12990 #ifdef STB_DEFINE
12991 // INTERPRETER
12992
12993 // 31-bit floating point implementation
12994 // force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent;
12995 // then shift and set the bottom bit
12996
12997 static stua_obj stu__floatp(float *f)
12998 {
12999 unsigned int n = *(unsigned int *) f;
13000 unsigned int e = n & (0xff << 23);
13001
13002 assert(sizeof(int) == 4 && sizeof(float) == 4);
13003
13004 if (!e) // zero?
13005 n = n; // no change
13006 else if (e < (64 << 23)) // underflow of the packed encoding?
13007 n = (n & 0x80000000); // signed 0
13008 else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN)
13009 n = (n & 0x80000000) + (127 << 23); // new INF encoding
13010 else
13011 n -= 0x20000000;
13012
13013 // now we need to shuffle the bits so that the spare bit is at the bottom
13014 assert((n & 0x40000000) == 0);
13015 return (n & 0x80000000) + (n << 1) + 1;
13016 }
13017
13018 static unsigned char stu__getfloat_addend[256];
13019 static float stu__getfloat(stua_obj v)
13020 {
13021 unsigned int n;
13022 unsigned int e = ((unsigned int) v) >> 24;
13023
13024 n = (int) v >> 1; // preserve high bit
13025 n += stu__getfloat_addend[e] << 24;
13026 return *(float *) &n;
13027 }
13028
13029 stua_obj stua_float(float f)
13030 {
13031 return stu__floatp(&f);
13032 }
13033
13034 static void stu__float_init(void)
13035 {
13036 int i;
13037 stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0
13038 for (i=1; i < 127; ++i)
13039 stu__getfloat_addend[i] = 32; // undo the -0x20000000
13040 stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f)
13041
13042 for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down
13043 stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64;
13044 }
13045
13046 // Tagged data type implementation
13047
13048 // TAGS:
13049 #define stu__int_tag 0 // of 2 bits // 00 int
13050 #define stu__float_tag 1 // of 1 bit // 01 float
13051 #define stu__ptr_tag 2 // of 2 bits // 10 boxed
13052 // 11 float
13053
13054 #define stu__tag(x) ((x) & 3)
13055 #define stu__number(x) (stu__tag(x) != stu__ptr_tag)
13056 #define stu__isint(x) (stu__tag(x) == stu__int_tag)
13057
13058 #define stu__int(x) ((x) >> 2)
13059 #define stu__float(x) (stu__getfloat(x))
13060
13061 #define stu__makeint(v) ((v)*4+stu__int_tag)
13062
13063 // boxed data, and tag support for boxed data
13064
13065 enum
13066 {
13067 STU___float = 1, STU___int = 2,
13068 STU___number = 3, STU___string = 4,
13069 STU___function = 5, STU___dict = 6,
13070 STU___boolean = 7, STU___error = 8,
13071 };
13072
13073 // boxed data
13074 #define STU__BOX short type, stua_gc
13075 typedef struct stu__box { STU__BOX; } stu__box;
13076
13077 stu__box stu__nil = { 0, 1 };
13078 stu__box stu__true = { STU___boolean, 1, };
13079 stu__box stu__false = { STU___boolean, 1, };
13080
13081 #define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag)
13082
13083 #define stua_nil stu__makeptr(&stu__nil)
13084 #define stua_true stu__makeptr(&stu__true)
13085 #define stua_false stu__makeptr(&stu__false)
13086
13087 stua_obj stua_getnil(void) { return stua_nil; }
13088 stua_obj stua_getfalse(void) { return stua_false; }
13089 stua_obj stua_gettrue(void) { return stua_true; }
13090
13091 #define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag))
13092
13093 #define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \
13094 (t) == STU___int ? stu__isint(x) : \
13095 (t) == STU___number ? stu__number(x) : \
13096 stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t))
13097
13098 typedef struct
13099 {
13100 STU__BOX;
13101 void *ptr;
13102 } stu__wrapper;
13103
13104 // implementation of a 'function' or function + closure
13105
13106 typedef struct stu__func
13107 {
13108 STU__BOX;
13109 stua_obj closure_source; // 0 - regular function; 4 - C function
13110 // if closure, pointer to source function
13111 union {
13112 stua_obj closure_data; // partial-application data
13113 void *store; // pointer to free that holds 'code'
13114 stua_obj (*func)(stua_dict *context);
13115 } f;
13116 // closure ends here
13117 short *code;
13118 int num_param;
13119 stua_obj *param; // list of parameter strings
13120 } stu__func;
13121
13122 // apply this to 'short *code' to get at data
13123 #define stu__const(f) ((stua_obj *) (f))
13124
13125 static void stu__free_func(stu__func *f)
13126 {
13127 if (f->closure_source == 0) free(f->f.store);
13128 if ((stb_uint) f->closure_source <= 4) free(f->param);
13129 free(f);
13130 }
13131
13132 #define stu__pd(x) ((stua_dict *) stu__ptr(x))
13133 #define stu__pw(x) ((stu__wrapper *) stu__ptr(x))
13134 #define stu__pf(x) ((stu__func *) stu__ptr(x))
13135
13136
13137 // garbage-collection
13138
13139
13140 static stu__box ** stu__gc_ptrlist;
13141 static stua_obj * stu__gc_root_stack;
13142
13143 stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; }
13144 void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); }
13145
13146 static stb_sdict *stu__strings;
13147 static void stu__mark(stua_obj z)
13148 {
13149 int i;
13150 stu__box *p = stu__ptr(z);
13151 if (p->stua_gc == 1) return; // already marked
13152 assert(p->stua_gc == 0);
13153 p->stua_gc = 1;
13154 switch(p->type) {
13155 case STU___function: {
13156 stu__func *f = (stu__func *) p;
13157 if ((stb_uint) f->closure_source <= 4) {
13158 if (f->closure_source == 0) {
13159 for (i=1; i <= f->code[0]; ++i)
13160 if (!stu__number(((stua_obj *) f->code)[-i]))
13161 stu__mark(((stua_obj *) f->code)[-i]);
13162 }
13163 for (i=0; i < f->num_param; ++i)
13164 stu__mark(f->param[i]);
13165 } else {
13166 stu__mark(f->closure_source);
13167 stu__mark(f->f.closure_data);
13168 }
13169 break;
13170 }
13171 case STU___dict: {
13172 stua_dict *e = (stua_dict *) p;
13173 for (i=0; i < e->limit; ++i)
13174 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) {
13175 if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k);
13176 if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v);
13177 }
13178 break;
13179 }
13180 }
13181 }
13182
13183 static int stu__num_allocs, stu__size_allocs;
13184 static stua_obj stu__flow_val = stua_nil; // used for break & return
13185
13186 static void stua_gc(int force)
13187 {
13188 int i;
13189 if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return;
13190 stu__num_allocs = stu__size_allocs = 0;
13191 //printf("[gc]\n");
13192
13193 // clear marks
13194 for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i)
13195 stu__gc_ptrlist[i]->stua_gc = 0;
13196
13197 // stu__mark everything reachable
13198 stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1;
13199 stu__mark(stua_globals);
13200 if (!stu__number(stu__flow_val))
13201 stu__mark(stu__flow_val);
13202 for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i)
13203 if (!stu__number(stu__gc_root_stack[i]))
13204 stu__mark(stu__gc_root_stack[i]);
13205
13206 // sweep unreachables
13207 for (i=0; i < stb_arr_len(stu__gc_ptrlist);) {
13208 stu__box *z = stu__gc_ptrlist[i];
13209 if (!z->stua_gc) {
13210 switch (z->type) {
13211 case STU___dict: stb_idict_destroy((stua_dict *) z); break;
13212 case STU___error: free(((stu__wrapper *) z)->ptr); break;
13213 case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break;
13214 case STU___function: stu__free_func((stu__func *) z); break;
13215 }
13216 // swap in the last item over this, and repeat
13217 z = stb_arr_pop(stu__gc_ptrlist);
13218 stu__gc_ptrlist[i] = z;
13219 } else
13220 ++i;
13221 }
13222 }
13223
13224 static void stu__consider_gc(stua_obj x)
13225 {
13226 if (stu__size_allocs < 100000) return;
13227 if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return;
13228 stb_arr_push(stu__gc_root_stack, x);
13229 stua_gc(0);
13230 stb_arr_pop(stu__gc_root_stack);
13231 }
13232
13233 static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc)
13234 {
13235 stua_obj x = stu__makeptr(data);
13236 ((stu__box *) data)->type = type;
13237 stb_arr_push(stu__gc_ptrlist, (stu__box *) data);
13238 stu__num_allocs += 1;
13239 stu__size_allocs += size;
13240 if (safe_to_gc) stu__consider_gc(x);
13241 return x;
13242 }
13243
13244 stua_obj stua_box(int type, void *data, int size)
13245 {
13246 stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p));
13247 p->ptr = data;
13248 return stu__makeobj(type, p, size, 0);
13249 }
13250
13251 // a stu string can be directly compared for equality, because
13252 // they go into a hash table
13253 stua_obj stua_string(char *z)
13254 {
13255 stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z);
13256 if (b == NULL) {
13257 int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b));
13258 b = stu__pw(o);
13259 stb_sdict_add(stu__strings, z, b);
13260 stb_sdict_getkey(stu__strings, z, (char **) &b->ptr);
13261 }
13262 return stu__makeptr(b);
13263 }
13264
13265 // stb_obj dictionary is just an stb_idict
13266 static void stu__set(stua_dict *d, stua_obj k, stua_obj v)
13267 { if (stb_idict_set(d, k, v)) stu__size_allocs += 8; }
13268
13269 static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res)
13270 {
13271 stb_idict_get_flag(d, k, &res);
13272 return res;
13273 }
13274
13275 static stua_obj make_string(char *z, int len)
13276 {
13277 stua_obj s;
13278 char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q;
13279 while (len > 0) {
13280 if (*z == '\\') {
13281 if (z[1] == 'n') *p = '\n';
13282 else if (z[1] == 'r') *p = '\r';
13283 else if (z[1] == 't') *p = '\t';
13284 else *p = z[1];
13285 p += 1; z += 2; len -= 2;
13286 } else {
13287 *p++ = *z++; len -= 1;
13288 }
13289 }
13290 *p = 0;
13291 s = stua_string(q);
13292 stb_tempfree(temp, q);
13293 return s;
13294 }
13295
13296 enum token_names
13297 {
13298 T__none=128,
13299 ST_shl = STUA_op_shl, ST_ge = STUA_op_ge,
13300 ST_shr = STUA_op_shr, ST_le = STUA_op_le,
13301 ST_shru = STUA_op_shru, STU__negate = STUA_op_negate,
13302 ST__reset_numbering = STUA_op_last,
13303 ST_white,
13304 ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number,
13305 // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them
13306 ST_if, ST_while, ST_for, ST_eq, ST_nil,
13307 ST_then, ST_do, ST_in, ST_ne, ST_true,
13308 ST_else, ST_break, ST_let, ST_and, ST_false,
13309 ST_elseif, ST_continue, ST_into, ST_or, ST_repeat,
13310 ST_end, ST_as, ST_return, ST_var, ST_func,
13311 ST_catch, ST__frame,
13312 ST__max_terminals,
13313
13314 STU__defaultparm, STU__seq,
13315 };
13316
13317 static stua_dict * stu__globaldict;
13318 stua_obj stua_globals;
13319
13320 static enum
13321 {
13322 FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error,
13323 } stu__flow;
13324
13325 stua_obj stua_error(char *z, ...)
13326 {
13327 stua_obj a;
13328 char temp[4096], *x;
13329 va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v);
13330 x = strdup(temp);
13331 a = stua_box(STU___error, x, strlen(x));
13332 stu__flow = FLOW_error;
13333 stu__flow_val = a;
13334 return stua_nil;
13335 }
13336
13337 double stua_number(stua_obj z)
13338 {
13339 return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z);
13340 }
13341
13342 stua_obj stua_make_number(double d)
13343 {
13344 double e = floor(d);
13345 if (e == d && e < (1 << 29) && e >= -(1 << 29))
13346 return stu__makeint((int) e);
13347 else
13348 return stua_float((float) d);
13349 }
13350
13351 stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL;
13352
13353 static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c)
13354 {
13355 stua_obj r = STUA_NO_VALUE;
13356 if (op == '+') {
13357 if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) {
13358 ;// @TODO: string concatenation
13359 } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) {
13360 stu__func *f = (stu__func *) malloc(12);
13361 assert(offsetof(stu__func, code)==12);
13362 f->closure_source = a;
13363 f->f.closure_data = b;
13364 return stu__makeobj(STU___function, f, 16, 1);
13365 }
13366 }
13367 if (stua_overload) r = stua_overload(op,a,b,c);
13368 if (stu__flow != FLOW_error && r == STUA_NO_VALUE)
13369 stua_error("Typecheck for operator %d", op), r=stua_nil;
13370 return r;
13371 }
13372
13373 #define STU__EVAL2(a,b) \
13374 a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \
13375 b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break;
13376
13377 #define STU__FB(op) \
13378 STU__EVAL2(a,b) \
13379 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13380 return ((a) op (b)); \
13381 if (stu__number(a) && stu__number(b)) \
13382 return stua_make_number(stua_number(a) op stua_number(b)); \
13383 return stu__op(stu__f[n], a,b, stua_nil)
13384
13385 #define STU__F(op) \
13386 STU__EVAL2(a,b) \
13387 if (stu__number(a) && stu__number(b)) \
13388 return stua_make_number(stua_number(a) op stua_number(b)); \
13389 return stu__op(stu__f[n], a,b, stua_nil)
13390
13391 #define STU__I(op) \
13392 STU__EVAL2(a,b) \
13393 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
13394 return stu__makeint(stu__int(a) op stu__int(b)); \
13395 return stu__op(stu__f[n], a,b, stua_nil)
13396
13397 #define STU__C(op) \
13398 STU__EVAL2(a,b) \
13399 if (stu__number(a) && stu__number(b)) \
13400 return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \
13401 return stu__op(stu__f[n], a,b, stua_nil)
13402
13403 #define STU__CE(op) \
13404 STU__EVAL2(a,b) \
13405 return (a op b) ? stua_true : stua_false
13406
13407 static short *stu__f;
13408 static stua_obj stu__f_obj;
13409 static stua_dict *stu__c;
13410 static stua_obj stu__funceval(stua_obj fo, stua_obj co);
13411
13412 static int stu__cond(stua_obj x)
13413 {
13414 if (stu__flow) return 0;
13415 if (!stu__checkt(STU___boolean, x))
13416 x = stu__op('!', x, stua_nil, stua_nil);
13417 if (x == stua_true ) return 1;
13418 if (x == stua_false) return 0;
13419 stu__flow = FLOW_error;
13420 return 0;
13421 }
13422
13423 // had to manually eliminate tailcall recursion for debugging complex stuff
13424 #define TAILCALL(x) n = (x); goto top;
13425 static stua_obj stu__eval(int n)
13426 {
13427 top:
13428 if (stu__flow >= FLOW_return) return stua_nil; // is this needed?
13429 if (n < 0) return stu__const(stu__f)[n];
13430 assert(n != 0 && n != 1);
13431 switch (stu__f[n]) {
13432 stua_obj a,b,c;
13433 case ST_catch: a = stu__eval(stu__f[n+1]);
13434 if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; }
13435 return a;
13436 case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break;
13437 stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b);
13438 return b;
13439 case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break;
13440 TAILCALL(stu__f[n+2]);
13441 case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil;
13442 TAILCALL(stu__f[n+2]);
13443 case ST_else: a = stu__cond(stu__eval(stu__f[n+1]));
13444 TAILCALL(stu__f[n + 2 + !a]);
13445 #define STU__HANDLE_BREAK \
13446 if (stu__flow >= FLOW_break) { \
13447 if (stu__flow == FLOW_break) { \
13448 a = stu__flow_val; \
13449 stu__flow = FLOW_normal; \
13450 stu__flow_val = stua_nil; \
13451 return a; \
13452 } \
13453 return stua_nil; \
13454 }
13455 case ST_as: stu__eval(stu__f[n+3]);
13456 STU__HANDLE_BREAK
13457 // fallthrough!
13458 case ST_while: a = stua_nil; stua_pushroot(a);
13459 while (stu__cond(stu__eval(stu__f[n+1]))) {
13460 stua_poproot();
13461 a = stu__eval(stu__f[n+2]);
13462 STU__HANDLE_BREAK
13463 stu__flow = FLOW_normal; // clear 'continue' flag
13464 stua_pushroot(a);
13465 if (stu__f[n+3]) stu__eval(stu__f[n+3]);
13466 STU__HANDLE_BREAK
13467 stu__flow = FLOW_normal; // clear 'continue' flag
13468 }
13469 stua_poproot();
13470 return a;
13471 case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break;
13472 case ST_continue:stu__flow = FLOW_continue; break;
13473 case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break;
13474 case ST__frame: return stu__f_obj;
13475 case '[': STU__EVAL2(a,b);
13476 if (stu__checkt(STU___dict, a))
13477 return stu__get(stu__pd(a), b, stua_nil);
13478 return stu__op(stu__f[n], a, b, stua_nil);
13479 case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break;
13480 n = stu__f[n+1];
13481 if (stu__f[n] == ST_id) {
13482 if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13483 if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a))
13484 return stua_error("Assignment to undefined variable");
13485 } else if (stu__f[n] == '[') {
13486 stua_pushroot(a);
13487 b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; }
13488 stua_pushroot(b);
13489 c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot();
13490 if (stu__flow) break;
13491 if (!stu__checkt(STU___dict, b)) return stua_nil;
13492 stu__set(stu__pd(b), c, a);
13493 } else {
13494 return stu__op(stu__f[n], stu__eval(n), a, stua_nil);
13495 }
13496 return a;
13497 case STU__defaultparm:
13498 a = stu__eval(stu__f[n+2]);
13499 stu__flow = FLOW_normal;
13500 if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
13501 stu__size_allocs += 8;
13502 return stua_nil;
13503 case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable
13504 return a != STUA_NO_VALUE // else try stu__compile_global_scope variable
13505 ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil);
13506 case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13507 return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil);
13508 case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13509 return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil);
13510 case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
13511 a = stu__cond(a); if (stu__flow) break;
13512 return a ? stua_true : stua_false;
13513 case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<);
13514 case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>);
13515 case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<);
13516 case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>);
13517 case '%': STU__I(%); case '^': STU__I(^);
13518 case ST_shru: STU__EVAL2(a,b);
13519 if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag)
13520 return stu__makeint((unsigned) stu__int(a) >> stu__int(b));
13521 return stu__op(stu__f[n], a,b, stua_nil);
13522 case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13523 return a ? stu__eval(stu__f[n+2]) : a;
13524 case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
13525 return a ? b : stu__eval(stu__f[n+2]);
13526 case'(':case':': STU__EVAL2(a,b);
13527 if (!stu__checkt(STU___function, a))
13528 return stu__op(stu__f[n], a,b, stua_nil);
13529 if (!stu__checkt(STU___dict, b))
13530 return stua_nil;
13531 if (stu__f[n] == ':')
13532 b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0);
13533 a = stu__funceval(a,b);
13534 return a;
13535 case '{' : {
13536 stua_dict *d;
13537 d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16);
13538 if (d == NULL)
13539 return stua_nil; // breakpoint fodder
13540 c = stu__makeobj(STU___dict, d, 32, 1);
13541 stua_pushroot(c);
13542 a = stu__f[n+1];
13543 for (b=0; b < a; ++b) {
13544 stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0]));
13545 stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]);
13546 stua_poproot();
13547 if (stu__flow) { stua_poproot(); return stua_nil; }
13548 stu__set(d, x, y);
13549 }
13550 stua_poproot();
13551 return c;
13552 }
13553 default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]];
13554 assert(0); /* NOTREACHED */ // internal error!
13555 }
13556 return stua_nil;
13557 }
13558
13559 int stb__stua_nesting;
13560 static stua_obj stu__funceval(stua_obj fo, stua_obj co)
13561 {
13562 stu__func *f = stu__pf(fo);
13563 stua_dict *context = stu__pd(co);
13564 int i,j;
13565 stua_obj p;
13566 short *tf = stu__f; // save previous function
13567 stua_dict *tc = stu__c;
13568
13569 if (stu__flow == FLOW_error) return stua_nil;
13570 assert(stu__flow == FLOW_normal);
13571
13572 stua_pushroot(fo);
13573 stua_pushroot(co);
13574 stu__consider_gc(stua_nil);
13575
13576 while ((stb_uint) f->closure_source > 4) {
13577 // add data from closure to context
13578 stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data);
13579 for (i=0; i < e->limit; ++i)
13580 if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL)
13581 if (stb_idict_add(context, e->table[i].k, e->table[i].v))
13582 stu__size_allocs += 8;
13583 // use add so if it's already defined, we don't override it; that way
13584 // explicit parameters win over applied ones, and most recent applications
13585 // win over previous ones
13586 f = stu__pf(f->closure_source);
13587 }
13588
13589 for (j=0, i=0; i < f->num_param; ++i)
13590 // if it doesn't already exist, add it from the numbered parameters
13591 if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil)))
13592 ++j;
13593
13594 // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters
13595 // @TODO: ditto too few parameters
13596
13597 if (f->closure_source == 4)
13598 p = f->f.func(context);
13599 else {
13600 stu__f = f->code, stu__c = context;
13601 stu__f_obj = co;
13602 ++stb__stua_nesting;
13603 if (stu__f[1])
13604 p = stu__eval(stu__f[1]);
13605 else
13606 p = stua_nil;
13607 --stb__stua_nesting;
13608 stu__f = tf, stu__c = tc; // restore previous function
13609 if (stu__flow == FLOW_return) {
13610 stu__flow = FLOW_normal;
13611 p = stu__flow_val;
13612 stu__flow_val = stua_nil;
13613 }
13614 }
13615
13616 stua_poproot();
13617 stua_poproot();
13618
13619 return p;
13620 }
13621
13622 // Parser
13623
13624 static int stu__tok;
13625 static stua_obj stu__tokval;
13626
13627 static char *stu__curbuf, *stu__bufstart;
13628
13629 static stb_matcher *stu__lex_matcher;
13630
13631 static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals];
13632
13633 static void stu__nexttoken(void)
13634 {
13635 int len;
13636
13637 retry:
13638 stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len);
13639 if (stu__tok == 0)
13640 return;
13641 switch(stu__tok) {
13642 case ST_white : stu__curbuf += len; goto retry;
13643 case T__none : stu__tok = *stu__curbuf; break;
13644 case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break;
13645 case ST_id : stu__tokval = make_string(stu__curbuf, len); break;
13646 case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break;
13647 case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break;
13648 case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break;
13649 case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2];
13650 if (stu__curbuf[3] == 't') stu__tokval = '\t';
13651 if (stu__curbuf[3] == 'n') stu__tokval = '\n';
13652 if (stu__curbuf[3] == 'r') stu__tokval = '\r';
13653 stu__tokval = stu__makeint(stu__tokval);
13654 stu__tok = ST_number;
13655 break;
13656 }
13657 stu__curbuf += len;
13658 }
13659
13660 static struct { int stu__tok; char *regex; } stu__lexemes[] =
13661 {
13662 ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+",
13663 ST_id , "[_a-zA-Z][_a-zA-Z0-9]*",
13664 ST_hex , "0x[0-9a-fA-F]+",
13665 ST_decimal, "[0-9]+[0-9]*",
13666 ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?",
13667 ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?",
13668 ST_char , "c'(\\\\.|[^\\'])'",
13669 ST_string , "\"(\\\\.|[^\\\"\n\r])*\"",
13670 ST_string , "\'(\\\\.|[^\\\'\n\r])*\'",
13671
13672 #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d,
13673 stua_key4(if,then,else,elseif) stua_key4(while,do,for,in)
13674 stua_key4(func,var,let,break) stua_key4(nil,true,false,end)
13675 stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch)
13676
13677 ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=",
13678 ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=",
13679 ST_shru,">>>", ST_into, "=>",
13680 T__none, ".",
13681 };
13682
13683 typedef struct
13684 {
13685 stua_obj *data; // constants being compiled
13686 short *code; // code being compiled
13687 stua_dict *locals;
13688 short *non_local_refs;
13689 } stu__comp_func;
13690
13691 static stu__comp_func stu__pfunc;
13692 static stu__comp_func *func_stack = NULL;
13693 static void stu__push_func_comp(void)
13694 {
13695 stb_arr_push(func_stack, stu__pfunc);
13696 stu__pfunc.data = NULL;
13697 stu__pfunc.code = NULL;
13698 stu__pfunc.locals = stb_idict_new_size(16);
13699 stu__pfunc.non_local_refs = NULL;
13700 stb_arr_push(stu__pfunc.code, 0); // number of data items
13701 stb_arr_push(stu__pfunc.code, 1); // starting execution address
13702 }
13703
13704 static void stu__pop_func_comp(void)
13705 {
13706 stb_arr_free(stu__pfunc.code);
13707 stb_arr_free(stu__pfunc.data);
13708 stb_idict_destroy(stu__pfunc.locals);
13709 stb_arr_free(stu__pfunc.non_local_refs);
13710 stu__pfunc = stb_arr_pop(func_stack);
13711 }
13712
13713 // if an id is a reference to an outer lexical scope, this
13714 // function returns the "name" of it, and updates the stack
13715 // structures to make sure the names are propogated in.
13716 static int stu__nonlocal_id(stua_obj var_obj)
13717 {
13718 stua_obj dummy, var = var_obj;
13719 int i, n = stb_arr_len(func_stack), j,k;
13720 if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0;
13721 for (i=n-1; i > 1; --i) {
13722 if (stb_idict_get_flag(func_stack[i].locals, var, &dummy))
13723 break;
13724 }
13725 if (i <= 1) return 0; // stu__compile_global_scope
13726 j = i; // need to access variable from j'th frame
13727 for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i)
13728 if (stu__pfunc.non_local_refs[i] == j) return j-n;
13729 stb_arr_push(stu__pfunc.non_local_refs, j-n);
13730 // now make sure all the parents propogate it down
13731 for (k=n-1; k > 1; --k) {
13732 if (j-k >= 0) return j-n; // comes direct from this parent
13733 for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i)
13734 if (func_stack[k].non_local_refs[i] == j-k)
13735 return j-n;
13736 stb_arr_push(func_stack[k].non_local_refs, j-k);
13737 }
13738 assert (k != 1);
13739
13740 return j-n;
13741 }
13742
13743 static int stu__off(void) { return stb_arr_len(stu__pfunc.code); }
13744 static void stu__cc(int a)
13745 {
13746 assert(a >= -2000 && a < 5000);
13747 stb_arr_push(stu__pfunc.code, a);
13748 }
13749 static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; }
13750 static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; }
13751 static int stu__cc3(int a, int b, int c) {
13752 if (a == '=') assert(c != 0);
13753 stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; }
13754 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; }
13755
13756 static int stu__cdv(stua_obj p)
13757 {
13758 int i;
13759 assert(p != STUA_NO_VALUE);
13760 for (i=0; i < stb_arr_len(stu__pfunc.data); ++i)
13761 if (stu__pfunc.data[i] == p)
13762 break;
13763 if (i == stb_arr_len(stu__pfunc.data))
13764 stb_arr_push(stu__pfunc.data, p);
13765 return ~i;
13766 }
13767
13768 static int stu__cdt(void)
13769 {
13770 int z = stu__cdv(stu__tokval);
13771 stu__nexttoken();
13772 return z;
13773 }
13774
13775 static int stu__seq(int a, int b)
13776 {
13777 return !a ? b : !b ? a : stu__cc3(STU__seq, a,b);
13778 }
13779
13780 static char stu__comp_err_str[1024];
13781 static int stu__comp_err_line;
13782 static int stu__err(char *str, ...)
13783 {
13784 va_list v;
13785 char *s = stu__bufstart;
13786 stu__comp_err_line = 1;
13787 while (s < stu__curbuf) {
13788 if (s[0] == '\n' || s[0] == '\r') {
13789 if (s[0]+s[1] == '\n' + '\r') ++s;
13790 ++stu__comp_err_line;
13791 }
13792 ++s;
13793 }
13794 va_start(v, str);
13795 vsprintf(stu__comp_err_str, str, v);
13796 va_end(v);
13797 return 0;
13798 }
13799
13800 static int stu__accept(int p)
13801 {
13802 if (stu__tok != p) return 0;
13803 stu__nexttoken();
13804 return 1;
13805 }
13806
13807 static int stu__demand(int p)
13808 {
13809 if (stu__accept(p)) return 1;
13810 return stu__err("Didn't find expected stu__tok");
13811 }
13812
13813 static int stu__demandv(int p, stua_obj *val)
13814 {
13815 if (stu__tok == p || p==0) {
13816 *val = stu__tokval;
13817 stu__nexttoken();
13818 return 1;
13819 } else
13820 return 0;
13821 }
13822
13823 static int stu__expr(int p);
13824 int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); }
13825 static int stu__statements(int once, int as);
13826
13827 static int stu__parse_if(void) // parse both ST_if and ST_elseif
13828 {
13829 int b,c,a;
13830 a = stu__nexpr(1); if (!a) return 0;
13831 if (!stu__demand(ST_then)) return stu__err("expecting THEN");
13832 b = stu__statements(0,0); if (!b) return 0;
13833 if (b == 1) b = -1;
13834
13835 if (stu__tok == ST_elseif) {
13836 return stu__parse_if();
13837 } else if (stu__accept(ST_else)) {
13838 c = stu__statements(0,0); if (!c) return 0;
13839 if (!stu__demand(ST_end)) return stu__err("expecting END after else clause");
13840 return stu__cc4(ST_else, a, b, c);
13841 } else {
13842 if (!stu__demand(ST_end)) return stu__err("expecting END in if statement");
13843 return stu__cc3(ST_if, a, b);
13844 }
13845 }
13846
13847 int stu__varinit(int z, int in_globals)
13848 {
13849 int a,b;
13850 stu__nexttoken();
13851 while (stu__demandv(ST_id, &b)) {
13852 if (!stb_idict_add(stu__pfunc.locals, b, 1))
13853 if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr);
13854 if (stu__accept('=')) {
13855 a = stu__expr(1); if (!a) return 0;
13856 } else
13857 a = stu__cdv(stua_nil);
13858 z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a));
13859 if (!stu__accept(',')) break;
13860 }
13861 return z;
13862 }
13863
13864 static int stu__compile_unary(int z, int outparm, int require_inparm)
13865 {
13866 int op = stu__tok, a, b;
13867 stu__nexttoken();
13868 if (outparm) {
13869 if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) {
13870 a = stu__expr(1); if (!a) return 0;
13871 } else
13872 a = stu__cdv(stua_nil);
13873 b = stu__cc2(op, a);
13874 } else
13875 b = stu__cc1(op);
13876 return stu__seq(z,b);
13877 }
13878
13879 static int stu__assign(void)
13880 {
13881 int z;
13882 stu__accept(ST_let);
13883 z = stu__expr(1); if (!z) return 0;
13884 if (stu__accept('=')) {
13885 int y,p = (z >= 0 ? stu__pfunc.code[z] : 0);
13886 if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment");
13887 y = stu__assign(); if (!y) return 0;
13888 z = stu__cc3('=', z, y);
13889 }
13890 return z;
13891 }
13892
13893 static int stu__statements(int once, int stop_while)
13894 {
13895 int a,b, c, z=0;
13896 for(;;) {
13897 switch (stu__tok) {
13898 case ST_if : a = stu__parse_if(); if (!a) return 0;
13899 z = stu__seq(z, a);
13900 break;
13901 case ST_while : if (stop_while) return (z ? z:1);
13902 a = stu__nexpr(1); if (!a) return 0;
13903 if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0;
13904 if (!stu__demand(ST_do)) return stu__err("expecting DO");
13905 b = stu__statements(0,0); if (!b) return 0;
13906 if (!stu__demand(ST_end)) return stu__err("expecting END");
13907 if (b == 1) b = -1;
13908 z = stu__seq(z, stu__cc4(ST_while, a, b, c));
13909 break;
13910 case ST_repeat : stu__nexttoken();
13911 c = stu__statements(0,1); if (!c) return 0;
13912 if (!stu__demand(ST_while)) return stu__err("expecting WHILE");
13913 a = stu__expr(1); if (!a) return 0;
13914 if (!stu__demand(ST_do)) return stu__err("expecting DO");
13915 b = stu__statements(0,0); if (!b) return 0;
13916 if (!stu__demand(ST_end)) return stu__err("expecting END");
13917 if (b == 1) b = -1;
13918 z = stu__seq(z, stu__cc4(ST_as, a, b, c));
13919 break;
13920 case ST_catch : a = stu__nexpr(1); if (!a) return 0;
13921 z = stu__seq(z, stu__cc2(ST_catch, a));
13922 break;
13923 case ST_var : z = stu__varinit(z,0); break;
13924 case ST_return : z = stu__compile_unary(z,1,1); break;
13925 case ST_continue:z = stu__compile_unary(z,0,0); break;
13926 case ST_break : z = stu__compile_unary(z,1,0); break;
13927 case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block");
13928 a = stu__nexpr(99);
13929 b = (a >= 0? stu__pfunc.code[a] : 0);
13930 if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>");
13931 z = stu__cc3('=', a, z);
13932 break;
13933 default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1);
13934 a = stu__assign(); if (!a) return 0;
13935 stu__accept(';');
13936 if (stu__tok && !stu__end[stu__tok]) {
13937 if (a < 0)
13938 return stu__err("Constant has no effect");
13939 if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=')
13940 return stu__err("Expression has no effect");
13941 }
13942 z = stu__seq(z, a);
13943 break;
13944 }
13945 if (!z) return 0;
13946 stu__accept(';');
13947 if (once && stu__tok != ST_into) return z;
13948 }
13949 }
13950
13951 static int stu__postexpr(int z, int p);
13952 static int stu__dictdef(int end, int *count)
13953 {
13954 int z,n=0,i,flags=0;
13955 short *dict=NULL;
13956 stu__nexttoken();
13957 while (stu__tok != end) {
13958 if (stu__tok == ST_id) {
13959 stua_obj id = stu__tokval;
13960 stu__nexttoken();
13961 if (stu__tok == '=') {
13962 flags |= 1;
13963 stb_arr_push(dict, stu__cdv(id));
13964 z = stu__nexpr(1); if (!z) return 0;
13965 } else {
13966 z = stu__cc2(ST_id, stu__cdv(id));
13967 z = stu__postexpr(z,1); if (!z) return 0;
13968 flags |= 2;
13969 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
13970 }
13971 } else {
13972 z = stu__expr(1); if (!z) return 0;
13973 flags |= 2;
13974 stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
13975 }
13976 if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;}
13977 stb_arr_push(dict, z);
13978 if (!stu__accept(',')) break;
13979 }
13980 if (!stu__demand(end))
13981 return stu__err(end == ')' ? "Expecting ) at end of function call"
13982 : "Expecting } at end of dictionary definition");
13983 z = stu__cc2('{', stb_arr_len(dict)/2);
13984 for (i=0; i < stb_arr_len(dict); ++i)
13985 stu__cc(dict[i]);
13986 if (count) *count = n;
13987 done:
13988 stb_arr_free(dict);
13989 return z;
13990 }
13991
13992 static int stu__comp_id(void)
13993 {
13994 int z,d;
13995 d = stu__nonlocal_id(stu__tokval);
13996 if (d == 0)
13997 return z = stu__cc2(ST_id, stu__cdt());
13998 // access a non-local frame by naming it with the appropriate int
13999 assert(d < 0);
14000 z = stu__cdv(d); // relative frame # is the 'variable' in our local frame
14001 z = stu__cc2(ST_id, z); // now access that dictionary
14002 return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir
14003 }
14004
14005 static stua_obj stu__funcdef(stua_obj *id, stua_obj *func);
14006 static int stu__expr(int p)
14007 {
14008 int z;
14009 // unary
14010 switch (stu__tok) {
14011 case ST_number: z = stu__cdt(); break;
14012 case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C
14013 case ST_id : z = stu__comp_id(); break;
14014 case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break;
14015 case ST_func : z = stu__funcdef(NULL,NULL); break;
14016 case ST_if : z = stu__parse_if(); break;
14017 case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break;
14018 case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break;
14019 case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break;
14020 case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break;
14021 case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break;
14022 case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break;
14023 case '{' : z = stu__dictdef('}', NULL); break;
14024 default : return stu__err("Unexpected token");
14025 case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )");
14026 }
14027 return stu__postexpr(z,p);
14028 }
14029
14030 static int stu__postexpr(int z, int p)
14031 {
14032 int q;
14033 // postfix
14034 while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') {
14035 if (stu__accept('.')) {
14036 // MUST be followed by a plain identifier! use [] for other stuff
14037 if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead");
14038 z = stu__cc3('[', z, stu__cdv(stu__tokval));
14039 stu__nexttoken();
14040 } else if (stu__accept('[')) {
14041 while (stu__tok != ']') {
14042 int r = stu__expr(1); if (!r) return 0;
14043 z = stu__cc3('[', z, r);
14044 if (!stu__accept(',')) break;
14045 }
14046 if (!stu__demand(']')) return stu__err("Expecting ]");
14047 } else {
14048 int n, p = stu__dictdef(')', &n); if (!p) return 0;
14049 #if 0 // this is incorrect!
14050 if (z > 0 && stu__pfunc.code[z] == ST_id) {
14051 stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil);
14052 if (stu__checkt(STU___function, q))
14053 if ((stu__pf(q))->num_param != n)
14054 return stu__err("Incorrect number of parameters");
14055 }
14056 #endif
14057 z = stu__cc3('(', z, p);
14058 }
14059 }
14060 // binop - this implementation taken from lcc
14061 for (q=stu__prec[stu__tok]; q >= p; --q) {
14062 while (stu__prec[stu__tok] == q) {
14063 int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0;
14064 z = stu__cc3(o,z,y);
14065 }
14066 }
14067 return z;
14068 }
14069
14070 static stua_obj stu__finish_func(stua_obj *param, int start)
14071 {
14072 int n, size;
14073 stu__func *f = (stu__func *) malloc(sizeof(*f));
14074 f->closure_source = 0;
14075 f->num_param = stb_arr_len(param);
14076 f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param));
14077 size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8;
14078 f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data));
14079 f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data));
14080 memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code));
14081 f->code[1] = start;
14082 f->code[0] = stb_arr_len(stu__pfunc.data);
14083 for (n=0; n < f->code[0]; ++n)
14084 ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n];
14085 return stu__makeobj(STU___function, f, size, 0);
14086 }
14087
14088 static int stu__funcdef(stua_obj *id, stua_obj *result)
14089 {
14090 int n,z=0,i,q;
14091 stua_obj *param = NULL;
14092 short *nonlocal;
14093 stua_obj v,f=stua_nil;
14094 assert(stu__tok == ST_func);
14095 stu__nexttoken();
14096 if (id) {
14097 if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name");
14098 } else
14099 stu__accept(ST_id);
14100 if (!stu__demand('(')) return stu__err("Expecting ( for function parameter");
14101 stu__push_func_comp();
14102 while (stu__tok != ')') {
14103 if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; }
14104 stb_idict_add(stu__pfunc.locals, v, 1);
14105 if (stu__tok == '=') {
14106 n = stu__nexpr(1); if (!n) { z=0; goto done; }
14107 z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n));
14108 } else
14109 stb_arr_push(param, v);
14110 if (!stu__accept(',')) break;
14111 }
14112 if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; }
14113 n = stu__statements(0,0); if (!n) { z=0; goto done; }
14114 if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; }
14115 if (n == 1) n = 0;
14116 n = stu__seq(z,n);
14117 f = stu__finish_func(param, n);
14118 if (result) { *result = f; z=1; stu__pop_func_comp(); }
14119 else {
14120 nonlocal = stu__pfunc.non_local_refs;
14121 stu__pfunc.non_local_refs = NULL;
14122 stu__pop_func_comp();
14123 z = stu__cdv(f);
14124 if (nonlocal) { // build a closure with references to the needed frames
14125 short *initcode = NULL;
14126 for (i=0; i < stb_arr_len(nonlocal); ++i) {
14127 int k = nonlocal[i], p;
14128 stb_arr_push(initcode, stu__cdv(k));
14129 if (k == -1) p = stu__cc1(ST__frame);
14130 else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); }
14131 stb_arr_push(initcode, p);
14132 }
14133 q = stu__cc2('{', stb_arr_len(nonlocal));
14134 for (i=0; i < stb_arr_len(initcode); ++i)
14135 stu__cc(initcode[i]);
14136 z = stu__cc3('+', z, q);
14137 stb_arr_free(initcode);
14138 }
14139 stb_arr_free(nonlocal);
14140 }
14141 done:
14142 stb_arr_free(param);
14143 if (!z) stu__pop_func_comp();
14144 return z;
14145 }
14146
14147 static int stu__compile_global_scope(void)
14148 {
14149 stua_obj o;
14150 int z=0;
14151
14152 stu__push_func_comp();
14153 while (stu__tok != 0) {
14154 if (stu__tok == ST_func) {
14155 stua_obj id, f;
14156 if (!stu__funcdef(&id,&f))
14157 goto error;
14158 stu__set(stu__globaldict, id, f);
14159 } else if (stu__tok == ST_var) {
14160 z = stu__varinit(z,1); if (!z) goto error;
14161 } else {
14162 int y = stu__statements(1,0); if (!y) goto error;
14163 z = stu__seq(z,y);
14164 }
14165 stu__accept(';');
14166 }
14167 o = stu__finish_func(NULL, z);
14168 stu__pop_func_comp();
14169
14170 o = stu__funceval(o, stua_globals); // initialize stu__globaldict
14171 if (stu__flow == FLOW_error)
14172 printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr);
14173 return 1;
14174 error:
14175 stu__pop_func_comp();
14176 return 0;
14177 }
14178
14179 stua_obj stu__myprint(stua_dict *context)
14180 {
14181 stua_obj x = stu__get(context, stua_string("x"), stua_nil);
14182 if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x));
14183 else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x));
14184 else {
14185 stu__wrapper *s = stu__pw(x);
14186 if (s->type == STU___string || s->type == STU___error)
14187 printf("%s", s->ptr);
14188 else if (s->type == STU___dict) printf("{{dictionary}}");
14189 else if (s->type == STU___function) printf("[[function]]");
14190 else
14191 printf("[[ERROR:%s]]", s->ptr);
14192 }
14193 return x;
14194 }
14195
14196 void stua_init(void)
14197 {
14198 if (!stu__globaldict) {
14199 int i;
14200 stua_obj s;
14201 stu__func *f;
14202
14203 stu__prec[ST_and] = stu__prec[ST_or] = 1;
14204 stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] =
14205 stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2;
14206 stu__prec[':'] = 3;
14207 stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4;
14208 stu__prec['+'] = stu__prec['-'] = 5;
14209 stu__prec['*'] = stu__prec['/'] = stu__prec['%'] =
14210 stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6;
14211
14212 stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1;
14213 stu__end[ST_do] = stu__end[ST_elseif] = 1;
14214
14215 stu__float_init();
14216 stu__lex_matcher = stb_lex_matcher();
14217 for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i)
14218 stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok);
14219
14220 stu__globaldict = stb_idict_new_size(64);
14221 stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0);
14222 stu__strings = stb_sdict_new(0);
14223
14224 stu__curbuf = stu__bufstart = "func _print(x) end\n"
14225 "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n";
14226 stu__nexttoken();
14227 if (!stu__compile_global_scope())
14228 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14229
14230 s = stu__get(stu__globaldict, stua_string("_print"), stua_nil);
14231 if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) {
14232 f = stu__pf(s);
14233 free(f->f.store);
14234 f->closure_source = 4;
14235 f->f.func = stu__myprint;
14236 f->code = NULL;
14237 }
14238 }
14239 }
14240
14241 void stua_uninit(void)
14242 {
14243 if (stu__globaldict) {
14244 stb_idict_remove_all(stu__globaldict);
14245 stb_arr_setlen(stu__gc_root_stack, 0);
14246 stua_gc(1);
14247 stb_idict_destroy(stu__globaldict);
14248 stb_sdict_delete(stu__strings);
14249 stb_matcher_free(stu__lex_matcher);
14250 stb_arr_free(stu__gc_ptrlist);
14251 stb_arr_free(func_stack);
14252 stb_arr_free(stu__gc_root_stack);
14253 stu__globaldict = NULL;
14254 }
14255 }
14256
14257 void stua_run_script(char *s)
14258 {
14259 stua_init();
14260
14261 stu__curbuf = stu__bufstart = s;
14262 stu__nexttoken();
14263
14264 stu__flow = FLOW_normal;
14265
14266 if (!stu__compile_global_scope())
14267 printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
14268 stua_gc(1);
14269 }
14270 #endif // STB_DEFINE
14271
14272 #endif // STB_STUA
14273
14274
14275 #undef STB_EXTERN
14276 #endif // STB_INCLUDE_STB_H
14277