duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

stb_sprintf.h (58282B)


      1 // stb_sprintf - v1.10 - public domain snprintf() implementation
      2 // originally by Jeff Roberts / RAD Game Tools, 2015/10/20
      3 // http://github.com/nothings/stb
      4 //
      5 // allowed types:  sc uidBboXx p AaGgEef n
      6 // lengths      :  hh h ll j z t I64 I32 I
      7 //
      8 // Contributors:
      9 //    Fabian "ryg" Giesen (reformatting)
     10 //    github:aganm (attribute format)
     11 //
     12 // Contributors (bugfixes):
     13 //    github:d26435
     14 //    github:trex78
     15 //    github:account-login
     16 //    Jari Komppa (SI suffixes)
     17 //    Rohit Nirmal
     18 //    Marcin Wojdyr
     19 //    Leonard Ritter
     20 //    Stefano Zanotti
     21 //    Adam Allison
     22 //    Arvid Gerstmann
     23 //    Markus Kolb
     24 //
     25 // LICENSE:
     26 //
     27 //   See end of file for license information.
     28 
     29 #ifndef STB_SPRINTF_H_INCLUDE
     30 #define STB_SPRINTF_H_INCLUDE
     31 
     32 /*
     33 Single file sprintf replacement.
     34 
     35 Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20.
     36 Hereby placed in public domain.
     37 
     38 This is a full sprintf replacement that supports everything that
     39 the C runtime sprintfs support, including float/double, 64-bit integers,
     40 hex floats, field parameters (%*.*d stuff), length reads backs, etc.
     41 
     42 Why would you need this if sprintf already exists?  Well, first off,
     43 it's *much* faster (see below). It's also much smaller than the CRT
     44 versions code-space-wise. We've also added some simple improvements
     45 that are super handy (commas in thousands, callbacks at buffer full,
     46 for example). Finally, the format strings for MSVC and GCC differ
     47 for 64-bit integers (among other small things), so this lets you use
     48 the same format strings in cross platform code.
     49 
     50 It uses the standard single file trick of being both the header file
     51 and the source itself. If you just include it normally, you just get
     52 the header file function definitions. To get the code, you include
     53 it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first.
     54 
     55 It only uses va_args macros from the C runtime to do it's work. It
     56 does cast doubles to S64s and shifts and divides U64s, which does
     57 drag in CRT code on most platforms.
     58 
     59 It compiles to roughly 8K with float support, and 4K without.
     60 As a comparison, when using MSVC static libs, calling sprintf drags
     61 in 16K.
     62 
     63 API:
     64 ====
     65 int stbsp_sprintf( char * buf, char const * fmt, ... )
     66 int stbsp_snprintf( char * buf, int count, char const * fmt, ... )
     67   Convert an arg list into a buffer.  stbsp_snprintf always returns
     68   a zero-terminated string (unlike regular snprintf).
     69 
     70 int stbsp_vsprintf( char * buf, char const * fmt, va_list va )
     71 int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va )
     72   Convert a va_list arg list into a buffer.  stbsp_vsnprintf always returns
     73   a zero-terminated string (unlike regular snprintf).
     74 
     75 int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va )
     76     typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len );
     77   Convert into a buffer, calling back every STB_SPRINTF_MIN chars.
     78   Your callback can then copy the chars out, print them or whatever.
     79   This function is actually the workhorse for everything else.
     80   The buffer you pass in must hold at least STB_SPRINTF_MIN characters.
     81     // you return the next buffer to use or 0 to stop converting
     82 
     83 void stbsp_set_separators( char comma, char period )
     84   Set the comma and period characters to use.
     85 
     86 FLOATS/DOUBLES:
     87 ===============
     88 This code uses a internal float->ascii conversion method that uses
     89 doubles with error correction (double-doubles, for ~105 bits of
     90 precision).  This conversion is round-trip perfect - that is, an atof
     91 of the values output here will give you the bit-exact double back.
     92 
     93 One difference is that our insignificant digits will be different than
     94 with MSVC or GCC (but they don't match each other either).  We also
     95 don't attempt to find the minimum length matching float (pre-MSVC15
     96 doesn't either).
     97 
     98 If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT
     99 and you'll save 4K of code space.
    100 
    101 64-BIT INTS:
    102 ============
    103 This library also supports 64-bit integers and you can use MSVC style or
    104 GCC style indicators (%I64d or %lld).  It supports the C99 specifiers
    105 for size_t and ptr_diff_t (%jd %zd) as well.
    106 
    107 EXTRAS:
    108 =======
    109 Like some GCCs, for integers and floats, you can use a ' (single quote)
    110 specifier and commas will be inserted on the thousands: "%'d" on 12345
    111 would print 12,345.
    112 
    113 For integers and floats, you can use a "$" specifier and the number
    114 will be converted to float and then divided to get kilo, mega, giga or
    115 tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is
    116 "2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn
    117 2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three
    118 $:s: "%$$$d" -> "2.42 M". To remove the space between the number and the
    119 suffix, add "_" specifier: "%_$d" -> "2.53M".
    120 
    121 In addition to octal and hexadecimal conversions, you can print
    122 integers in binary: "%b" for 256 would print 100.
    123 
    124 PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
    125 ===================================================================
    126 "%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC)
    127 "%24d" across all 32-bit ints (4.5x/4.2x faster)
    128 "%x" across all 32-bit ints (4.5x/3.8x faster)
    129 "%08x" across all 32-bit ints (4.3x/3.8x faster)
    130 "%f" across e-10 to e+10 floats (7.3x/6.0x faster)
    131 "%e" across e-10 to e+10 floats (8.1x/6.0x faster)
    132 "%g" across e-10 to e+10 floats (10.0x/7.1x faster)
    133 "%f" for values near e-300 (7.9x/6.5x faster)
    134 "%f" for values near e+300 (10.0x/9.1x faster)
    135 "%e" for values near e-300 (10.1x/7.0x faster)
    136 "%e" for values near e+300 (9.2x/6.0x faster)
    137 "%.320f" for values near e-300 (12.6x/11.2x faster)
    138 "%a" for random values (8.6x/4.3x faster)
    139 "%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster)
    140 "%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster)
    141 "%s%s%s" for 64 char strings (7.1x/7.3x faster)
    142 "...512 char string..." ( 35.0x/32.5x faster!)
    143 */
    144 
    145 #if defined(__clang__)
    146  #if defined(__has_feature) && defined(__has_attribute)
    147   #if __has_feature(address_sanitizer)
    148    #if __has_attribute(__no_sanitize__)
    149     #define STBSP__ASAN __attribute__((__no_sanitize__("address")))
    150    #elif __has_attribute(__no_sanitize_address__)
    151     #define STBSP__ASAN __attribute__((__no_sanitize_address__))
    152    #elif __has_attribute(__no_address_safety_analysis__)
    153     #define STBSP__ASAN __attribute__((__no_address_safety_analysis__))
    154    #endif
    155   #endif
    156  #endif
    157 #elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
    158  #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__
    159   #define STBSP__ASAN __attribute__((__no_sanitize_address__))
    160  #endif
    161 #endif
    162 
    163 #ifndef STBSP__ASAN
    164 #define STBSP__ASAN
    165 #endif
    166 
    167 #ifdef STB_SPRINTF_STATIC
    168 #define STBSP__PUBLICDEC static
    169 #define STBSP__PUBLICDEF static STBSP__ASAN
    170 #else
    171 #ifdef __cplusplus
    172 #define STBSP__PUBLICDEC extern "C"
    173 #define STBSP__PUBLICDEF extern "C" STBSP__ASAN
    174 #else
    175 #define STBSP__PUBLICDEC extern
    176 #define STBSP__PUBLICDEF STBSP__ASAN
    177 #endif
    178 #endif
    179 
    180 #if defined(__has_attribute)
    181  #if __has_attribute(format)
    182    #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va)))
    183  #endif
    184 #endif
    185 
    186 #ifndef STBSP__ATTRIBUTE_FORMAT
    187 #define STBSP__ATTRIBUTE_FORMAT(fmt,va)
    188 #endif
    189 
    190 #ifdef _MSC_VER
    191 #define STBSP__NOTUSED(v)  (void)(v)
    192 #else
    193 #define STBSP__NOTUSED(v)  (void)sizeof(v)
    194 #endif
    195 
    196 #include <stdarg.h> // for va_arg(), va_list()
    197 #include <stddef.h> // size_t, ptrdiff_t
    198 
    199 #ifndef STB_SPRINTF_MIN
    200 #define STB_SPRINTF_MIN 512 // how many characters per callback
    201 #endif
    202 typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len);
    203 
    204 #ifndef STB_SPRINTF_DECORATE
    205 #define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names
    206 #endif
    207 
    208 STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va);
    209 STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va);
    210 STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3);
    211 STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4);
    212 
    213 STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va);
    214 STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
    215 
    216 #endif // STB_SPRINTF_H_INCLUDE
    217 
    218 #ifdef STB_SPRINTF_IMPLEMENTATION
    219 
    220 #define stbsp__uint32 unsigned int
    221 #define stbsp__int32 signed int
    222 
    223 #ifdef _MSC_VER
    224 #define stbsp__uint64 unsigned __int64
    225 #define stbsp__int64 signed __int64
    226 #else
    227 #define stbsp__uint64 unsigned long long
    228 #define stbsp__int64 signed long long
    229 #endif
    230 #define stbsp__uint16 unsigned short
    231 
    232 #ifndef stbsp__uintptr
    233 #if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__)
    234 #define stbsp__uintptr stbsp__uint64
    235 #else
    236 #define stbsp__uintptr stbsp__uint32
    237 #endif
    238 #endif
    239 
    240 #ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC)
    241 #if defined(_MSC_VER) && (_MSC_VER < 1900)
    242 #define STB_SPRINTF_MSVC_MODE
    243 #endif
    244 #endif
    245 
    246 #ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses
    247 #define STBSP__UNALIGNED(code)
    248 #else
    249 #define STBSP__UNALIGNED(code) code
    250 #endif
    251 
    252 #ifndef STB_SPRINTF_NOFLOAT
    253 // internal float utility functions
    254 static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits);
    255 static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value);
    256 #define STBSP__SPECIAL 0x7000
    257 #endif
    258 
    259 static char stbsp__period = '.';
    260 static char stbsp__comma = ',';
    261 static struct
    262 {
    263    short temp; // force next field to be 2-byte aligned
    264    char pair[201];
    265 } stbsp__digitpair =
    266 {
    267   0,
    268    "00010203040506070809101112131415161718192021222324"
    269    "25262728293031323334353637383940414243444546474849"
    270    "50515253545556575859606162636465666768697071727374"
    271    "75767778798081828384858687888990919293949596979899"
    272 };
    273 
    274 STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod)
    275 {
    276    stbsp__period = pperiod;
    277    stbsp__comma = pcomma;
    278 }
    279 
    280 #define STBSP__LEFTJUST 1
    281 #define STBSP__LEADINGPLUS 2
    282 #define STBSP__LEADINGSPACE 4
    283 #define STBSP__LEADING_0X 8
    284 #define STBSP__LEADINGZERO 16
    285 #define STBSP__INTMAX 32
    286 #define STBSP__TRIPLET_COMMA 64
    287 #define STBSP__NEGATIVE 128
    288 #define STBSP__METRIC_SUFFIX 256
    289 #define STBSP__HALFWIDTH 512
    290 #define STBSP__METRIC_NOSPACE 1024
    291 #define STBSP__METRIC_1024 2048
    292 #define STBSP__METRIC_JEDEC 4096
    293 
    294 static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
    295 {
    296    sign[0] = 0;
    297    if (fl & STBSP__NEGATIVE) {
    298       sign[0] = 1;
    299       sign[1] = '-';
    300    } else if (fl & STBSP__LEADINGSPACE) {
    301       sign[0] = 1;
    302       sign[1] = ' ';
    303    } else if (fl & STBSP__LEADINGPLUS) {
    304       sign[0] = 1;
    305       sign[1] = '+';
    306    }
    307 }
    308 
    309 static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
    310 {
    311    char const * sn = s;
    312 
    313    // get up to 4-byte alignment
    314    for (;;) {
    315       if (((stbsp__uintptr)sn & 3) == 0)
    316          break;
    317 
    318       if (!limit || *sn == 0)
    319          return (stbsp__uint32)(sn - s);
    320 
    321       ++sn;
    322       --limit;
    323    }
    324 
    325    // scan over 4 bytes at a time to find terminating 0
    326    // this will intentionally scan up to 3 bytes past the end of buffers,
    327    // but becase it works 4B aligned, it will never cross page boundaries
    328    // (hence the STBSP__ASAN markup; the over-read here is intentional
    329    // and harmless)
    330    while (limit >= 4) {
    331       stbsp__uint32 v = *(stbsp__uint32 *)sn;
    332       // bit hack to find if there's a 0 byte in there
    333       if ((v - 0x01010101) & (~v) & 0x80808080UL)
    334          break;
    335 
    336       sn += 4;
    337       limit -= 4;
    338    }
    339 
    340    // handle the last few characters to find actual size
    341    while (limit && *sn) {
    342       ++sn;
    343       --limit;
    344    }
    345 
    346    return (stbsp__uint32)(sn - s);
    347 }
    348 
    349 STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
    350 {
    351    static char hex[] = "0123456789abcdefxp";
    352    static char hexu[] = "0123456789ABCDEFXP";
    353    char *bf;
    354    char const *f;
    355    int tlen = 0;
    356 
    357    bf = buf;
    358    f = fmt;
    359    for (;;) {
    360       stbsp__int32 fw, pr, tz;
    361       stbsp__uint32 fl;
    362 
    363       // macros for the callback buffer stuff
    364       #define stbsp__chk_cb_bufL(bytes)                        \
    365          {                                                     \
    366             int len = (int)(bf - buf);                         \
    367             if ((len + (bytes)) >= STB_SPRINTF_MIN) {          \
    368                tlen += len;                                    \
    369                if (0 == (bf = buf = callback(buf, user, len))) \
    370                   goto done;                                   \
    371             }                                                  \
    372          }
    373       #define stbsp__chk_cb_buf(bytes)    \
    374          {                                \
    375             if (callback) {               \
    376                stbsp__chk_cb_bufL(bytes); \
    377             }                             \
    378          }
    379       #define stbsp__flush_cb()                      \
    380          {                                           \
    381             stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \
    382          } // flush if there is even one byte in the buffer
    383       #define stbsp__cb_buf_clamp(cl, v)                \
    384          cl = v;                                        \
    385          if (callback) {                                \
    386             int lg = STB_SPRINTF_MIN - (int)(bf - buf); \
    387             if (cl > lg)                                \
    388                cl = lg;                                 \
    389          }
    390 
    391       // fast copy everything up to the next % (or end of string)
    392       for (;;) {
    393          while (((stbsp__uintptr)f) & 3) {
    394          schk1:
    395             if (f[0] == '%')
    396                goto scandd;
    397          schk2:
    398             if (f[0] == 0)
    399                goto endfmt;
    400             stbsp__chk_cb_buf(1);
    401             *bf++ = f[0];
    402             ++f;
    403          }
    404          for (;;) {
    405             // Check if the next 4 bytes contain %(0x25) or end of string.
    406             // Using the 'hasless' trick:
    407             // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
    408             stbsp__uint32 v, c;
    409             v = *(stbsp__uint32 *)f;
    410             c = (~v) & 0x80808080;
    411             if (((v ^ 0x25252525) - 0x01010101) & c)
    412                goto schk1;
    413             if ((v - 0x01010101) & c)
    414                goto schk2;
    415             if (callback)
    416                if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4)
    417                   goto schk1;
    418             #ifdef STB_SPRINTF_NOUNALIGNED
    419                 if(((stbsp__uintptr)bf) & 3) {
    420                     bf[0] = f[0];
    421                     bf[1] = f[1];
    422                     bf[2] = f[2];
    423                     bf[3] = f[3];
    424                 } else
    425             #endif
    426             {
    427                 *(stbsp__uint32 *)bf = v;
    428             }
    429             bf += 4;
    430             f += 4;
    431          }
    432       }
    433    scandd:
    434 
    435       ++f;
    436 
    437       // ok, we have a percent, read the modifiers first
    438       fw = 0;
    439       pr = -1;
    440       fl = 0;
    441       tz = 0;
    442 
    443       // flags
    444       for (;;) {
    445          switch (f[0]) {
    446          // if we have left justify
    447          case '-':
    448             fl |= STBSP__LEFTJUST;
    449             ++f;
    450             continue;
    451          // if we have leading plus
    452          case '+':
    453             fl |= STBSP__LEADINGPLUS;
    454             ++f;
    455             continue;
    456          // if we have leading space
    457          case ' ':
    458             fl |= STBSP__LEADINGSPACE;
    459             ++f;
    460             continue;
    461          // if we have leading 0x
    462          case '#':
    463             fl |= STBSP__LEADING_0X;
    464             ++f;
    465             continue;
    466          // if we have thousand commas
    467          case '\'':
    468             fl |= STBSP__TRIPLET_COMMA;
    469             ++f;
    470             continue;
    471          // if we have kilo marker (none->kilo->kibi->jedec)
    472          case '$':
    473             if (fl & STBSP__METRIC_SUFFIX) {
    474                if (fl & STBSP__METRIC_1024) {
    475                   fl |= STBSP__METRIC_JEDEC;
    476                } else {
    477                   fl |= STBSP__METRIC_1024;
    478                }
    479             } else {
    480                fl |= STBSP__METRIC_SUFFIX;
    481             }
    482             ++f;
    483             continue;
    484          // if we don't want space between metric suffix and number
    485          case '_':
    486             fl |= STBSP__METRIC_NOSPACE;
    487             ++f;
    488             continue;
    489          // if we have leading zero
    490          case '0':
    491             fl |= STBSP__LEADINGZERO;
    492             ++f;
    493             goto flags_done;
    494          default: goto flags_done;
    495          }
    496       }
    497    flags_done:
    498 
    499       // get the field width
    500       if (f[0] == '*') {
    501          fw = va_arg(va, stbsp__uint32);
    502          ++f;
    503       } else {
    504          while ((f[0] >= '0') && (f[0] <= '9')) {
    505             fw = fw * 10 + f[0] - '0';
    506             f++;
    507          }
    508       }
    509       // get the precision
    510       if (f[0] == '.') {
    511          ++f;
    512          if (f[0] == '*') {
    513             pr = va_arg(va, stbsp__uint32);
    514             ++f;
    515          } else {
    516             pr = 0;
    517             while ((f[0] >= '0') && (f[0] <= '9')) {
    518                pr = pr * 10 + f[0] - '0';
    519                f++;
    520             }
    521          }
    522       }
    523 
    524       // handle integer size overrides
    525       switch (f[0]) {
    526       // are we halfwidth?
    527       case 'h':
    528          fl |= STBSP__HALFWIDTH;
    529          ++f;
    530          if (f[0] == 'h')
    531             ++f;  // QUARTERWIDTH
    532          break;
    533       // are we 64-bit (unix style)
    534       case 'l':
    535          fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0);
    536          ++f;
    537          if (f[0] == 'l') {
    538             fl |= STBSP__INTMAX;
    539             ++f;
    540          }
    541          break;
    542       // are we 64-bit on intmax? (c99)
    543       case 'j':
    544          fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0;
    545          ++f;
    546          break;
    547       // are we 64-bit on size_t or ptrdiff_t? (c99)
    548       case 'z':
    549          fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
    550          ++f;
    551          break;
    552       case 't':
    553          fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
    554          ++f;
    555          break;
    556       // are we 64-bit (msft style)
    557       case 'I':
    558          if ((f[1] == '6') && (f[2] == '4')) {
    559             fl |= STBSP__INTMAX;
    560             f += 3;
    561          } else if ((f[1] == '3') && (f[2] == '2')) {
    562             f += 3;
    563          } else {
    564             fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0);
    565             ++f;
    566          }
    567          break;
    568       default: break;
    569       }
    570 
    571       // handle each replacement
    572       switch (f[0]) {
    573          #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307
    574          char num[STBSP__NUMSZ];
    575          char lead[8];
    576          char tail[8];
    577          char *s;
    578          char const *h;
    579          stbsp__uint32 l, n, cs;
    580          stbsp__uint64 n64;
    581 #ifndef STB_SPRINTF_NOFLOAT
    582          double fv;
    583 #endif
    584          stbsp__int32 dp;
    585          char const *sn;
    586 
    587       case 's':
    588          // get the string
    589          s = va_arg(va, char *);
    590          if (s == 0)
    591             s = (char *)"null";
    592          // get the length, limited to desired precision
    593          // always limit to ~0u chars since our counts are 32b
    594          l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
    595          lead[0] = 0;
    596          tail[0] = 0;
    597          pr = 0;
    598          dp = 0;
    599          cs = 0;
    600          // copy the string in
    601          goto scopy;
    602 
    603       case 'c': // char
    604          // get the character
    605          s = num + STBSP__NUMSZ - 1;
    606          *s = (char)va_arg(va, int);
    607          l = 1;
    608          lead[0] = 0;
    609          tail[0] = 0;
    610          pr = 0;
    611          dp = 0;
    612          cs = 0;
    613          goto scopy;
    614 
    615 #if 0
    616       // Disabled since it's terribly unsafe.
    617       case 'n': // weird write-bytes specifier
    618       {
    619          int *d = va_arg(va, int *);
    620          *d = tlen + (int)(bf - buf);
    621       } break;
    622 #endif
    623 
    624 #ifdef STB_SPRINTF_NOFLOAT
    625       case 'A':              // float
    626       case 'a':              // hex float
    627       case 'G':              // float
    628       case 'g':              // float
    629       case 'E':              // float
    630       case 'e':              // float
    631       case 'f':              // float
    632          va_arg(va, double); // eat it
    633          s = (char *)"No float";
    634          l = 8;
    635          lead[0] = 0;
    636          tail[0] = 0;
    637          pr = 0;
    638          cs = 0;
    639          STBSP__NOTUSED(dp);
    640          goto scopy;
    641 #else
    642       case 'A': // hex float
    643       case 'a': // hex float
    644          h = (f[0] == 'A') ? hexu : hex;
    645          fv = va_arg(va, double);
    646          if (pr == -1)
    647             pr = 6; // default is 6
    648          // read the double into a string
    649          if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv))
    650             fl |= STBSP__NEGATIVE;
    651 
    652          s = num + 64;
    653 
    654          stbsp__lead_sign(fl, lead);
    655 
    656          if (dp == -1023)
    657             dp = (n64) ? -1022 : 0;
    658          else
    659             n64 |= (((stbsp__uint64)1) << 52);
    660          n64 <<= (64 - 56);
    661          if (pr < 15)
    662             n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4));
    663 // add leading chars
    664 
    665 #ifdef STB_SPRINTF_MSVC_MODE
    666          *s++ = '0';
    667          *s++ = 'x';
    668 #else
    669          lead[1 + lead[0]] = '0';
    670          lead[2 + lead[0]] = 'x';
    671          lead[0] += 2;
    672 #endif
    673          *s++ = h[(n64 >> 60) & 15];
    674          n64 <<= 4;
    675          if (pr)
    676             *s++ = stbsp__period;
    677          sn = s;
    678 
    679          // print the bits
    680          n = pr;
    681          if (n > 13)
    682             n = 13;
    683          if (pr > (stbsp__int32)n)
    684             tz = pr - n;
    685          pr = 0;
    686          while (n--) {
    687             *s++ = h[(n64 >> 60) & 15];
    688             n64 <<= 4;
    689          }
    690 
    691          // print the expo
    692          tail[1] = h[17];
    693          if (dp < 0) {
    694             tail[2] = '-';
    695             dp = -dp;
    696          } else
    697             tail[2] = '+';
    698          n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3));
    699          tail[0] = (char)n;
    700          for (;;) {
    701             tail[n] = '0' + dp % 10;
    702             if (n <= 3)
    703                break;
    704             --n;
    705             dp /= 10;
    706          }
    707 
    708          dp = (int)(s - sn);
    709          l = (int)(s - (num + 64));
    710          s = num + 64;
    711          cs = 1 + (3 << 24);
    712          goto scopy;
    713 
    714       case 'G': // float
    715       case 'g': // float
    716          h = (f[0] == 'G') ? hexu : hex;
    717          fv = va_arg(va, double);
    718          if (pr == -1)
    719             pr = 6;
    720          else if (pr == 0)
    721             pr = 1; // default is 6
    722          // read the double into a string
    723          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000))
    724             fl |= STBSP__NEGATIVE;
    725 
    726          // clamp the precision and delete extra zeros after clamp
    727          n = pr;
    728          if (l > (stbsp__uint32)pr)
    729             l = pr;
    730          while ((l > 1) && (pr) && (sn[l - 1] == '0')) {
    731             --pr;
    732             --l;
    733          }
    734 
    735          // should we use %e
    736          if ((dp <= -4) || (dp > (stbsp__int32)n)) {
    737             if (pr > (stbsp__int32)l)
    738                pr = l - 1;
    739             else if (pr)
    740                --pr; // when using %e, there is one digit before the decimal
    741             goto doexpfromg;
    742          }
    743          // this is the insane action to get the pr to match %g semantics for %f
    744          if (dp > 0) {
    745             pr = (dp < (stbsp__int32)l) ? l - dp : 0;
    746          } else {
    747             pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr);
    748          }
    749          goto dofloatfromg;
    750 
    751       case 'E': // float
    752       case 'e': // float
    753          h = (f[0] == 'E') ? hexu : hex;
    754          fv = va_arg(va, double);
    755          if (pr == -1)
    756             pr = 6; // default is 6
    757          // read the double into a string
    758          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000))
    759             fl |= STBSP__NEGATIVE;
    760       doexpfromg:
    761          tail[0] = 0;
    762          stbsp__lead_sign(fl, lead);
    763          if (dp == STBSP__SPECIAL) {
    764             s = (char *)sn;
    765             cs = 0;
    766             pr = 0;
    767             goto scopy;
    768          }
    769          s = num + 64;
    770          // handle leading chars
    771          *s++ = sn[0];
    772 
    773          if (pr)
    774             *s++ = stbsp__period;
    775 
    776          // handle after decimal
    777          if ((l - 1) > (stbsp__uint32)pr)
    778             l = pr + 1;
    779          for (n = 1; n < l; n++)
    780             *s++ = sn[n];
    781          // trailing zeros
    782          tz = pr - (l - 1);
    783          pr = 0;
    784          // dump expo
    785          tail[1] = h[0xe];
    786          dp -= 1;
    787          if (dp < 0) {
    788             tail[2] = '-';
    789             dp = -dp;
    790          } else
    791             tail[2] = '+';
    792 #ifdef STB_SPRINTF_MSVC_MODE
    793          n = 5;
    794 #else
    795          n = (dp >= 100) ? 5 : 4;
    796 #endif
    797          tail[0] = (char)n;
    798          for (;;) {
    799             tail[n] = '0' + dp % 10;
    800             if (n <= 3)
    801                break;
    802             --n;
    803             dp /= 10;
    804          }
    805          cs = 1 + (3 << 24); // how many tens
    806          goto flt_lead;
    807 
    808       case 'f': // float
    809          fv = va_arg(va, double);
    810       doafloat:
    811          // do kilos
    812          if (fl & STBSP__METRIC_SUFFIX) {
    813             double divisor;
    814             divisor = 1000.0f;
    815             if (fl & STBSP__METRIC_1024)
    816                divisor = 1024.0;
    817             while (fl < 0x4000000) {
    818                if ((fv < divisor) && (fv > -divisor))
    819                   break;
    820                fv /= divisor;
    821                fl += 0x1000000;
    822             }
    823          }
    824          if (pr == -1)
    825             pr = 6; // default is 6
    826          // read the double into a string
    827          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr))
    828             fl |= STBSP__NEGATIVE;
    829       dofloatfromg:
    830          tail[0] = 0;
    831          stbsp__lead_sign(fl, lead);
    832          if (dp == STBSP__SPECIAL) {
    833             s = (char *)sn;
    834             cs = 0;
    835             pr = 0;
    836             goto scopy;
    837          }
    838          s = num + 64;
    839 
    840          // handle the three decimal varieties
    841          if (dp <= 0) {
    842             stbsp__int32 i;
    843             // handle 0.000*000xxxx
    844             *s++ = '0';
    845             if (pr)
    846                *s++ = stbsp__period;
    847             n = -dp;
    848             if ((stbsp__int32)n > pr)
    849                n = pr;
    850             i = n;
    851             while (i) {
    852                if ((((stbsp__uintptr)s) & 3) == 0)
    853                   break;
    854                *s++ = '0';
    855                --i;
    856             }
    857             while (i >= 4) {
    858                *(stbsp__uint32 *)s = 0x30303030;
    859                s += 4;
    860                i -= 4;
    861             }
    862             while (i) {
    863                *s++ = '0';
    864                --i;
    865             }
    866             if ((stbsp__int32)(l + n) > pr)
    867                l = pr - n;
    868             i = l;
    869             while (i) {
    870                *s++ = *sn++;
    871                --i;
    872             }
    873             tz = pr - (n + l);
    874             cs = 1 + (3 << 24); // how many tens did we write (for commas below)
    875          } else {
    876             cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0;
    877             if ((stbsp__uint32)dp >= l) {
    878                // handle xxxx000*000.0
    879                n = 0;
    880                for (;;) {
    881                   if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
    882                      cs = 0;
    883                      *s++ = stbsp__comma;
    884                   } else {
    885                      *s++ = sn[n];
    886                      ++n;
    887                      if (n >= l)
    888                         break;
    889                   }
    890                }
    891                if (n < (stbsp__uint32)dp) {
    892                   n = dp - n;
    893                   if ((fl & STBSP__TRIPLET_COMMA) == 0) {
    894                      while (n) {
    895                         if ((((stbsp__uintptr)s) & 3) == 0)
    896                            break;
    897                         *s++ = '0';
    898                         --n;
    899                      }
    900                      while (n >= 4) {
    901                         *(stbsp__uint32 *)s = 0x30303030;
    902                         s += 4;
    903                         n -= 4;
    904                      }
    905                   }
    906                   while (n) {
    907                      if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
    908                         cs = 0;
    909                         *s++ = stbsp__comma;
    910                      } else {
    911                         *s++ = '0';
    912                         --n;
    913                      }
    914                   }
    915                }
    916                cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
    917                if (pr) {
    918                   *s++ = stbsp__period;
    919                   tz = pr;
    920                }
    921             } else {
    922                // handle xxxxx.xxxx000*000
    923                n = 0;
    924                for (;;) {
    925                   if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
    926                      cs = 0;
    927                      *s++ = stbsp__comma;
    928                   } else {
    929                      *s++ = sn[n];
    930                      ++n;
    931                      if (n >= (stbsp__uint32)dp)
    932                         break;
    933                   }
    934                }
    935                cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
    936                if (pr)
    937                   *s++ = stbsp__period;
    938                if ((l - dp) > (stbsp__uint32)pr)
    939                   l = pr + dp;
    940                while (n < l) {
    941                   *s++ = sn[n];
    942                   ++n;
    943                }
    944                tz = pr - (l - dp);
    945             }
    946          }
    947          pr = 0;
    948 
    949          // handle k,m,g,t
    950          if (fl & STBSP__METRIC_SUFFIX) {
    951             char idx;
    952             idx = 1;
    953             if (fl & STBSP__METRIC_NOSPACE)
    954                idx = 0;
    955             tail[0] = idx;
    956             tail[1] = ' ';
    957             {
    958                if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'.
    959                   if (fl & STBSP__METRIC_1024)
    960                      tail[idx + 1] = "_KMGT"[fl >> 24];
    961                   else
    962                      tail[idx + 1] = "_kMGT"[fl >> 24];
    963                   idx++;
    964                   // If printing kibits and not in jedec, add the 'i'.
    965                   if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) {
    966                      tail[idx + 1] = 'i';
    967                      idx++;
    968                   }
    969                   tail[0] = idx;
    970                }
    971             }
    972          };
    973 
    974       flt_lead:
    975          // get the length that we copied
    976          l = (stbsp__uint32)(s - (num + 64));
    977          s = num + 64;
    978          goto scopy;
    979 #endif
    980 
    981       case 'B': // upper binary
    982       case 'b': // lower binary
    983          h = (f[0] == 'B') ? hexu : hex;
    984          lead[0] = 0;
    985          if (fl & STBSP__LEADING_0X) {
    986             lead[0] = 2;
    987             lead[1] = '0';
    988             lead[2] = h[0xb];
    989          }
    990          l = (8 << 4) | (1 << 8);
    991          goto radixnum;
    992 
    993       case 'o': // octal
    994          h = hexu;
    995          lead[0] = 0;
    996          if (fl & STBSP__LEADING_0X) {
    997             lead[0] = 1;
    998             lead[1] = '0';
    999          }
   1000          l = (3 << 4) | (3 << 8);
   1001          goto radixnum;
   1002 
   1003       case 'p': // pointer
   1004          fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0;
   1005          pr = sizeof(void *) * 2;
   1006          fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros
   1007                                     // fall through - to X
   1008 
   1009       case 'X': // upper hex
   1010       case 'x': // lower hex
   1011          h = (f[0] == 'X') ? hexu : hex;
   1012          l = (4 << 4) | (4 << 8);
   1013          lead[0] = 0;
   1014          if (fl & STBSP__LEADING_0X) {
   1015             lead[0] = 2;
   1016             lead[1] = '0';
   1017             lead[2] = h[16];
   1018          }
   1019       radixnum:
   1020          // get the number
   1021          if (fl & STBSP__INTMAX)
   1022             n64 = va_arg(va, stbsp__uint64);
   1023          else
   1024             n64 = va_arg(va, stbsp__uint32);
   1025 
   1026          s = num + STBSP__NUMSZ;
   1027          dp = 0;
   1028          // clear tail, and clear leading if value is zero
   1029          tail[0] = 0;
   1030          if (n64 == 0) {
   1031             lead[0] = 0;
   1032             if (pr == 0) {
   1033                l = 0;
   1034                cs = 0;
   1035                goto scopy;
   1036             }
   1037          }
   1038          // convert to string
   1039          for (;;) {
   1040             *--s = h[n64 & ((1 << (l >> 8)) - 1)];
   1041             n64 >>= (l >> 8);
   1042             if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr)))
   1043                break;
   1044             if (fl & STBSP__TRIPLET_COMMA) {
   1045                ++l;
   1046                if ((l & 15) == ((l >> 4) & 15)) {
   1047                   l &= ~15;
   1048                   *--s = stbsp__comma;
   1049                }
   1050             }
   1051          };
   1052          // get the tens and the comma pos
   1053          cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24);
   1054          // get the length that we copied
   1055          l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
   1056          // copy it
   1057          goto scopy;
   1058 
   1059       case 'u': // unsigned
   1060       case 'i':
   1061       case 'd': // integer
   1062          // get the integer and abs it
   1063          if (fl & STBSP__INTMAX) {
   1064             stbsp__int64 i64 = va_arg(va, stbsp__int64);
   1065             n64 = (stbsp__uint64)i64;
   1066             if ((f[0] != 'u') && (i64 < 0)) {
   1067                n64 = (stbsp__uint64)-i64;
   1068                fl |= STBSP__NEGATIVE;
   1069             }
   1070          } else {
   1071             stbsp__int32 i = va_arg(va, stbsp__int32);
   1072             n64 = (stbsp__uint32)i;
   1073             if ((f[0] != 'u') && (i < 0)) {
   1074                n64 = (stbsp__uint32)-i;
   1075                fl |= STBSP__NEGATIVE;
   1076             }
   1077          }
   1078 
   1079 #ifndef STB_SPRINTF_NOFLOAT
   1080          if (fl & STBSP__METRIC_SUFFIX) {
   1081             if (n64 < 1024)
   1082                pr = 0;
   1083             else if (pr == -1)
   1084                pr = 1;
   1085             fv = (double)(stbsp__int64)n64;
   1086             goto doafloat;
   1087          }
   1088 #endif
   1089 
   1090          // convert to string
   1091          s = num + STBSP__NUMSZ;
   1092          l = 0;
   1093 
   1094          for (;;) {
   1095             // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators)
   1096             char *o = s - 8;
   1097             if (n64 >= 100000000) {
   1098                n = (stbsp__uint32)(n64 % 100000000);
   1099                n64 /= 100000000;
   1100             } else {
   1101                n = (stbsp__uint32)n64;
   1102                n64 = 0;
   1103             }
   1104             if ((fl & STBSP__TRIPLET_COMMA) == 0) {
   1105                do {
   1106                   s -= 2;
   1107                   *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
   1108                   n /= 100;
   1109                } while (n);
   1110             }
   1111             while (n) {
   1112                if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
   1113                   l = 0;
   1114                   *--s = stbsp__comma;
   1115                   --o;
   1116                } else {
   1117                   *--s = (char)(n % 10) + '0';
   1118                   n /= 10;
   1119                }
   1120             }
   1121             if (n64 == 0) {
   1122                if ((s[0] == '0') && (s != (num + STBSP__NUMSZ)))
   1123                   ++s;
   1124                break;
   1125             }
   1126             while (s != o)
   1127                if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
   1128                   l = 0;
   1129                   *--s = stbsp__comma;
   1130                   --o;
   1131                } else {
   1132                   *--s = '0';
   1133                }
   1134          }
   1135 
   1136          tail[0] = 0;
   1137          stbsp__lead_sign(fl, lead);
   1138 
   1139          // get the length that we copied
   1140          l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
   1141          if (l == 0) {
   1142             *--s = '0';
   1143             l = 1;
   1144          }
   1145          cs = l + (3 << 24);
   1146          if (pr < 0)
   1147             pr = 0;
   1148 
   1149       scopy:
   1150          // get fw=leading/trailing space, pr=leading zeros
   1151          if (pr < (stbsp__int32)l)
   1152             pr = l;
   1153          n = pr + lead[0] + tail[0] + tz;
   1154          if (fw < (stbsp__int32)n)
   1155             fw = n;
   1156          fw -= n;
   1157          pr -= l;
   1158 
   1159          // handle right justify and leading zeros
   1160          if ((fl & STBSP__LEFTJUST) == 0) {
   1161             if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr
   1162             {
   1163                pr = (fw > pr) ? fw : pr;
   1164                fw = 0;
   1165             } else {
   1166                fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas
   1167             }
   1168          }
   1169 
   1170          // copy the spaces and/or zeros
   1171          if (fw + pr) {
   1172             stbsp__int32 i;
   1173             stbsp__uint32 c;
   1174 
   1175             // copy leading spaces (or when doing %8.4d stuff)
   1176             if ((fl & STBSP__LEFTJUST) == 0)
   1177                while (fw > 0) {
   1178                   stbsp__cb_buf_clamp(i, fw);
   1179                   fw -= i;
   1180                   while (i) {
   1181                      if ((((stbsp__uintptr)bf) & 3) == 0)
   1182                         break;
   1183                      *bf++ = ' ';
   1184                      --i;
   1185                   }
   1186                   while (i >= 4) {
   1187                      *(stbsp__uint32 *)bf = 0x20202020;
   1188                      bf += 4;
   1189                      i -= 4;
   1190                   }
   1191                   while (i) {
   1192                      *bf++ = ' ';
   1193                      --i;
   1194                   }
   1195                   stbsp__chk_cb_buf(1);
   1196                }
   1197 
   1198             // copy leader
   1199             sn = lead + 1;
   1200             while (lead[0]) {
   1201                stbsp__cb_buf_clamp(i, lead[0]);
   1202                lead[0] -= (char)i;
   1203                while (i) {
   1204                   *bf++ = *sn++;
   1205                   --i;
   1206                }
   1207                stbsp__chk_cb_buf(1);
   1208             }
   1209 
   1210             // copy leading zeros
   1211             c = cs >> 24;
   1212             cs &= 0xffffff;
   1213             cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0;
   1214             while (pr > 0) {
   1215                stbsp__cb_buf_clamp(i, pr);
   1216                pr -= i;
   1217                if ((fl & STBSP__TRIPLET_COMMA) == 0) {
   1218                   while (i) {
   1219                      if ((((stbsp__uintptr)bf) & 3) == 0)
   1220                         break;
   1221                      *bf++ = '0';
   1222                      --i;
   1223                   }
   1224                   while (i >= 4) {
   1225                      *(stbsp__uint32 *)bf = 0x30303030;
   1226                      bf += 4;
   1227                      i -= 4;
   1228                   }
   1229                }
   1230                while (i) {
   1231                   if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) {
   1232                      cs = 0;
   1233                      *bf++ = stbsp__comma;
   1234                   } else
   1235                      *bf++ = '0';
   1236                   --i;
   1237                }
   1238                stbsp__chk_cb_buf(1);
   1239             }
   1240          }
   1241 
   1242          // copy leader if there is still one
   1243          sn = lead + 1;
   1244          while (lead[0]) {
   1245             stbsp__int32 i;
   1246             stbsp__cb_buf_clamp(i, lead[0]);
   1247             lead[0] -= (char)i;
   1248             while (i) {
   1249                *bf++ = *sn++;
   1250                --i;
   1251             }
   1252             stbsp__chk_cb_buf(1);
   1253          }
   1254 
   1255          // copy the string
   1256          n = l;
   1257          while (n) {
   1258             stbsp__int32 i;
   1259             stbsp__cb_buf_clamp(i, n);
   1260             n -= i;
   1261             STBSP__UNALIGNED(while (i >= 4) {
   1262                *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s;
   1263                bf += 4;
   1264                s += 4;
   1265                i -= 4;
   1266             })
   1267             while (i) {
   1268                *bf++ = *s++;
   1269                --i;
   1270             }
   1271             stbsp__chk_cb_buf(1);
   1272          }
   1273 
   1274          // copy trailing zeros
   1275          while (tz) {
   1276             stbsp__int32 i;
   1277             stbsp__cb_buf_clamp(i, tz);
   1278             tz -= i;
   1279             while (i) {
   1280                if ((((stbsp__uintptr)bf) & 3) == 0)
   1281                   break;
   1282                *bf++ = '0';
   1283                --i;
   1284             }
   1285             while (i >= 4) {
   1286                *(stbsp__uint32 *)bf = 0x30303030;
   1287                bf += 4;
   1288                i -= 4;
   1289             }
   1290             while (i) {
   1291                *bf++ = '0';
   1292                --i;
   1293             }
   1294             stbsp__chk_cb_buf(1);
   1295          }
   1296 
   1297          // copy tail if there is one
   1298          sn = tail + 1;
   1299          while (tail[0]) {
   1300             stbsp__int32 i;
   1301             stbsp__cb_buf_clamp(i, tail[0]);
   1302             tail[0] -= (char)i;
   1303             while (i) {
   1304                *bf++ = *sn++;
   1305                --i;
   1306             }
   1307             stbsp__chk_cb_buf(1);
   1308          }
   1309 
   1310          // handle the left justify
   1311          if (fl & STBSP__LEFTJUST)
   1312             if (fw > 0) {
   1313                while (fw) {
   1314                   stbsp__int32 i;
   1315                   stbsp__cb_buf_clamp(i, fw);
   1316                   fw -= i;
   1317                   while (i) {
   1318                      if ((((stbsp__uintptr)bf) & 3) == 0)
   1319                         break;
   1320                      *bf++ = ' ';
   1321                      --i;
   1322                   }
   1323                   while (i >= 4) {
   1324                      *(stbsp__uint32 *)bf = 0x20202020;
   1325                      bf += 4;
   1326                      i -= 4;
   1327                   }
   1328                   while (i--)
   1329                      *bf++ = ' ';
   1330                   stbsp__chk_cb_buf(1);
   1331                }
   1332             }
   1333          break;
   1334 
   1335       default: // unknown, just copy code
   1336          s = num + STBSP__NUMSZ - 1;
   1337          *s = f[0];
   1338          l = 1;
   1339          fw = fl = 0;
   1340          lead[0] = 0;
   1341          tail[0] = 0;
   1342          pr = 0;
   1343          dp = 0;
   1344          cs = 0;
   1345          goto scopy;
   1346       }
   1347       ++f;
   1348    }
   1349 endfmt:
   1350 
   1351    if (!callback)
   1352       *bf = 0;
   1353    else
   1354       stbsp__flush_cb();
   1355 
   1356 done:
   1357    return tlen + (int)(bf - buf);
   1358 }
   1359 
   1360 // cleanup
   1361 #undef STBSP__LEFTJUST
   1362 #undef STBSP__LEADINGPLUS
   1363 #undef STBSP__LEADINGSPACE
   1364 #undef STBSP__LEADING_0X
   1365 #undef STBSP__LEADINGZERO
   1366 #undef STBSP__INTMAX
   1367 #undef STBSP__TRIPLET_COMMA
   1368 #undef STBSP__NEGATIVE
   1369 #undef STBSP__METRIC_SUFFIX
   1370 #undef STBSP__NUMSZ
   1371 #undef stbsp__chk_cb_bufL
   1372 #undef stbsp__chk_cb_buf
   1373 #undef stbsp__flush_cb
   1374 #undef stbsp__cb_buf_clamp
   1375 
   1376 // ============================================================================
   1377 //   wrapper functions
   1378 
   1379 STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...)
   1380 {
   1381    int result;
   1382    va_list va;
   1383    va_start(va, fmt);
   1384    result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
   1385    va_end(va);
   1386    return result;
   1387 }
   1388 
   1389 typedef struct stbsp__context {
   1390    char *buf;
   1391    int count;
   1392    int length;
   1393    char tmp[STB_SPRINTF_MIN];
   1394 } stbsp__context;
   1395 
   1396 static char *stbsp__clamp_callback(const char *buf, void *user, int len)
   1397 {
   1398    stbsp__context *c = (stbsp__context *)user;
   1399    c->length += len;
   1400 
   1401    if (len > c->count)
   1402       len = c->count;
   1403 
   1404    if (len) {
   1405       if (buf != c->buf) {
   1406          const char *s, *se;
   1407          char *d;
   1408          d = c->buf;
   1409          s = buf;
   1410          se = buf + len;
   1411          do {
   1412             *d++ = *s++;
   1413          } while (s < se);
   1414       }
   1415       c->buf += len;
   1416       c->count -= len;
   1417    }
   1418 
   1419    if (c->count <= 0)
   1420       return c->tmp;
   1421    return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can
   1422 }
   1423 
   1424 static char * stbsp__count_clamp_callback( const char * buf, void * user, int len )
   1425 {
   1426    stbsp__context * c = (stbsp__context*)user;
   1427    (void) sizeof(buf);
   1428 
   1429    c->length += len;
   1430    return c->tmp; // go direct into buffer if you can
   1431 }
   1432 
   1433 STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va )
   1434 {
   1435    stbsp__context c;
   1436 
   1437    if ( (count == 0) && !buf )
   1438    {
   1439       c.length = 0;
   1440 
   1441       STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va );
   1442    }
   1443    else
   1444    {
   1445       int l;
   1446 
   1447       c.buf = buf;
   1448       c.count = count;
   1449       c.length = 0;
   1450 
   1451       STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va );
   1452 
   1453       // zero-terminate
   1454       l = (int)( c.buf - buf );
   1455       if ( l >= count ) // should never be greater, only equal (or less) than count
   1456          l = count - 1;
   1457       buf[l] = 0;
   1458    }
   1459 
   1460    return c.length;
   1461 }
   1462 
   1463 STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...)
   1464 {
   1465    int result;
   1466    va_list va;
   1467    va_start(va, fmt);
   1468 
   1469    result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va);
   1470    va_end(va);
   1471 
   1472    return result;
   1473 }
   1474 
   1475 STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va)
   1476 {
   1477    return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
   1478 }
   1479 
   1480 // =======================================================================
   1481 //   low level float utility functions
   1482 
   1483 #ifndef STB_SPRINTF_NOFLOAT
   1484 
   1485 // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox)
   1486 #define STBSP__COPYFP(dest, src)                   \
   1487    {                                               \
   1488       int cn;                                      \
   1489       for (cn = 0; cn < 8; cn++)                   \
   1490          ((char *)&dest)[cn] = ((char *)&src)[cn]; \
   1491    }
   1492 
   1493 // get float info
   1494 static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value)
   1495 {
   1496    double d;
   1497    stbsp__int64 b = 0;
   1498 
   1499    // load value and round at the frac_digits
   1500    d = value;
   1501 
   1502    STBSP__COPYFP(b, d);
   1503 
   1504    *bits = b & ((((stbsp__uint64)1) << 52) - 1);
   1505    *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023);
   1506 
   1507    return (stbsp__int32)((stbsp__uint64) b >> 63);
   1508 }
   1509 
   1510 static double const stbsp__bot[23] = {
   1511    1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011,
   1512    1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022
   1513 };
   1514 static double const stbsp__negbot[22] = {
   1515    1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011,
   1516    1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022
   1517 };
   1518 static double const stbsp__negboterr[22] = {
   1519    -5.551115123125783e-018,  -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023,
   1520    4.5251888174113739e-024,  -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028,  2.0113352370744385e-029,
   1521    -3.0373745563400371e-030, 1.1806906454401013e-032,  -7.7705399876661076e-032, 2.0902213275965398e-033,  -7.1542424054621921e-034, -7.1542424054621926e-035,
   1522    2.4754073164739869e-036,  5.4846728545790429e-037,  9.2462547772103625e-038,  -4.8596774326570872e-039
   1523 };
   1524 static double const stbsp__top[13] = {
   1525    1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299
   1526 };
   1527 static double const stbsp__negtop[13] = {
   1528    1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299
   1529 };
   1530 static double const stbsp__toperr[13] = {
   1531    8388608,
   1532    6.8601809640529717e+028,
   1533    -7.253143638152921e+052,
   1534    -4.3377296974619174e+075,
   1535    -1.5559416129466825e+098,
   1536    -3.2841562489204913e+121,
   1537    -3.7745893248228135e+144,
   1538    -1.7356668416969134e+167,
   1539    -3.8893577551088374e+190,
   1540    -9.9566444326005119e+213,
   1541    6.3641293062232429e+236,
   1542    -5.2069140800249813e+259,
   1543    -5.2504760255204387e+282
   1544 };
   1545 static double const stbsp__negtoperr[13] = {
   1546    3.9565301985100693e-040,  -2.299904345391321e-063,  3.6506201437945798e-086,  1.1875228833981544e-109,
   1547    -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178,  -5.7778912386589953e-201,
   1548    7.4997100559334532e-224,  -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293,
   1549    8.0970921678014997e-317
   1550 };
   1551 
   1552 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
   1553 static stbsp__uint64 const stbsp__powten[20] = {
   1554    1,
   1555    10,
   1556    100,
   1557    1000,
   1558    10000,
   1559    100000,
   1560    1000000,
   1561    10000000,
   1562    100000000,
   1563    1000000000,
   1564    10000000000,
   1565    100000000000,
   1566    1000000000000,
   1567    10000000000000,
   1568    100000000000000,
   1569    1000000000000000,
   1570    10000000000000000,
   1571    100000000000000000,
   1572    1000000000000000000,
   1573    10000000000000000000U
   1574 };
   1575 #define stbsp__tento19th ((stbsp__uint64)1000000000000000000)
   1576 #else
   1577 static stbsp__uint64 const stbsp__powten[20] = {
   1578    1,
   1579    10,
   1580    100,
   1581    1000,
   1582    10000,
   1583    100000,
   1584    1000000,
   1585    10000000,
   1586    100000000,
   1587    1000000000,
   1588    10000000000ULL,
   1589    100000000000ULL,
   1590    1000000000000ULL,
   1591    10000000000000ULL,
   1592    100000000000000ULL,
   1593    1000000000000000ULL,
   1594    10000000000000000ULL,
   1595    100000000000000000ULL,
   1596    1000000000000000000ULL,
   1597    10000000000000000000ULL
   1598 };
   1599 #define stbsp__tento19th (1000000000000000000ULL)
   1600 #endif
   1601 
   1602 #define stbsp__ddmulthi(oh, ol, xh, yh)                            \
   1603    {                                                               \
   1604       double ahi = 0, alo, bhi = 0, blo;                           \
   1605       stbsp__int64 bt;                                             \
   1606       oh = xh * yh;                                                \
   1607       STBSP__COPYFP(bt, xh);                                       \
   1608       bt &= ((~(stbsp__uint64)0) << 27);                           \
   1609       STBSP__COPYFP(ahi, bt);                                      \
   1610       alo = xh - ahi;                                              \
   1611       STBSP__COPYFP(bt, yh);                                       \
   1612       bt &= ((~(stbsp__uint64)0) << 27);                           \
   1613       STBSP__COPYFP(bhi, bt);                                      \
   1614       blo = yh - bhi;                                              \
   1615       ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \
   1616    }
   1617 
   1618 #define stbsp__ddtoS64(ob, xh, xl)          \
   1619    {                                        \
   1620       double ahi = 0, alo, vh, t;           \
   1621       ob = (stbsp__int64)xh;                \
   1622       vh = (double)ob;                      \
   1623       ahi = (xh - vh);                      \
   1624       t = (ahi - xh);                       \
   1625       alo = (xh - (ahi - t)) - (vh + t);    \
   1626       ob += (stbsp__int64)(ahi + alo + xl); \
   1627    }
   1628 
   1629 #define stbsp__ddrenorm(oh, ol) \
   1630    {                            \
   1631       double s;                 \
   1632       s = oh + ol;              \
   1633       ol = ol - (s - oh);       \
   1634       oh = s;                   \
   1635    }
   1636 
   1637 #define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh);
   1638 
   1639 #define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl);
   1640 
   1641 static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350
   1642 {
   1643    double ph, pl;
   1644    if ((power >= 0) && (power <= 22)) {
   1645       stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]);
   1646    } else {
   1647       stbsp__int32 e, et, eb;
   1648       double p2h, p2l;
   1649 
   1650       e = power;
   1651       if (power < 0)
   1652          e = -e;
   1653       et = (e * 0x2c9) >> 14; /* %23 */
   1654       if (et > 13)
   1655          et = 13;
   1656       eb = e - (et * 23);
   1657 
   1658       ph = d;
   1659       pl = 0.0;
   1660       if (power < 0) {
   1661          if (eb) {
   1662             --eb;
   1663             stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]);
   1664             stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]);
   1665          }
   1666          if (et) {
   1667             stbsp__ddrenorm(ph, pl);
   1668             --et;
   1669             stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]);
   1670             stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]);
   1671             ph = p2h;
   1672             pl = p2l;
   1673          }
   1674       } else {
   1675          if (eb) {
   1676             e = eb;
   1677             if (eb > 22)
   1678                eb = 22;
   1679             e -= eb;
   1680             stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]);
   1681             if (e) {
   1682                stbsp__ddrenorm(ph, pl);
   1683                stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]);
   1684                stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl);
   1685                ph = p2h;
   1686                pl = p2l;
   1687             }
   1688          }
   1689          if (et) {
   1690             stbsp__ddrenorm(ph, pl);
   1691             --et;
   1692             stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]);
   1693             stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]);
   1694             ph = p2h;
   1695             pl = p2l;
   1696          }
   1697       }
   1698    }
   1699    stbsp__ddrenorm(ph, pl);
   1700    *ohi = ph;
   1701    *olo = pl;
   1702 }
   1703 
   1704 // given a float value, returns the significant bits in bits, and the position of the
   1705 //   decimal point in decimal_pos.  +/-INF and NAN are specified by special values
   1706 //   returned in the decimal_pos parameter.
   1707 // frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000
   1708 static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits)
   1709 {
   1710    double d;
   1711    stbsp__int64 bits = 0;
   1712    stbsp__int32 expo, e, ng, tens;
   1713 
   1714    d = value;
   1715    STBSP__COPYFP(bits, d);
   1716    expo = (stbsp__int32)((bits >> 52) & 2047);
   1717    ng = (stbsp__int32)((stbsp__uint64) bits >> 63);
   1718    if (ng)
   1719       d = -d;
   1720 
   1721    if (expo == 2047) // is nan or inf?
   1722    {
   1723       *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf";
   1724       *decimal_pos = STBSP__SPECIAL;
   1725       *len = 3;
   1726       return ng;
   1727    }
   1728 
   1729    if (expo == 0) // is zero or denormal
   1730    {
   1731       if (((stbsp__uint64) bits << 1) == 0) // do zero
   1732       {
   1733          *decimal_pos = 1;
   1734          *start = out;
   1735          out[0] = '0';
   1736          *len = 1;
   1737          return ng;
   1738       }
   1739       // find the right expo for denormals
   1740       {
   1741          stbsp__int64 v = ((stbsp__uint64)1) << 51;
   1742          while ((bits & v) == 0) {
   1743             --expo;
   1744             v >>= 1;
   1745          }
   1746       }
   1747    }
   1748 
   1749    // find the decimal exponent as well as the decimal bits of the value
   1750    {
   1751       double ph, pl;
   1752 
   1753       // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046
   1754       tens = expo - 1023;
   1755       tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1);
   1756 
   1757       // move the significant bits into position and stick them into an int
   1758       stbsp__raise_to_power10(&ph, &pl, d, 18 - tens);
   1759 
   1760       // get full as much precision from double-double as possible
   1761       stbsp__ddtoS64(bits, ph, pl);
   1762 
   1763       // check if we undershot
   1764       if (((stbsp__uint64)bits) >= stbsp__tento19th)
   1765          ++tens;
   1766    }
   1767 
   1768    // now do the rounding in integer land
   1769    frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits);
   1770    if ((frac_digits < 24)) {
   1771       stbsp__uint32 dg = 1;
   1772       if ((stbsp__uint64)bits >= stbsp__powten[9])
   1773          dg = 10;
   1774       while ((stbsp__uint64)bits >= stbsp__powten[dg]) {
   1775          ++dg;
   1776          if (dg == 20)
   1777             goto noround;
   1778       }
   1779       if (frac_digits < dg) {
   1780          stbsp__uint64 r;
   1781          // add 0.5 at the right position and round
   1782          e = dg - frac_digits;
   1783          if ((stbsp__uint32)e >= 24)
   1784             goto noround;
   1785          r = stbsp__powten[e];
   1786          bits = bits + (r / 2);
   1787          if ((stbsp__uint64)bits >= stbsp__powten[dg])
   1788             ++tens;
   1789          bits /= r;
   1790       }
   1791    noround:;
   1792    }
   1793 
   1794    // kill long trailing runs of zeros
   1795    if (bits) {
   1796       stbsp__uint32 n;
   1797       for (;;) {
   1798          if (bits <= 0xffffffff)
   1799             break;
   1800          if (bits % 1000)
   1801             goto donez;
   1802          bits /= 1000;
   1803       }
   1804       n = (stbsp__uint32)bits;
   1805       while ((n % 1000) == 0)
   1806          n /= 1000;
   1807       bits = n;
   1808    donez:;
   1809    }
   1810 
   1811    // convert to string
   1812    out += 64;
   1813    e = 0;
   1814    for (;;) {
   1815       stbsp__uint32 n;
   1816       char *o = out - 8;
   1817       // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned)
   1818       if (bits >= 100000000) {
   1819          n = (stbsp__uint32)(bits % 100000000);
   1820          bits /= 100000000;
   1821       } else {
   1822          n = (stbsp__uint32)bits;
   1823          bits = 0;
   1824       }
   1825       while (n) {
   1826          out -= 2;
   1827          *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
   1828          n /= 100;
   1829          e += 2;
   1830       }
   1831       if (bits == 0) {
   1832          if ((e) && (out[0] == '0')) {
   1833             ++out;
   1834             --e;
   1835          }
   1836          break;
   1837       }
   1838       while (out != o) {
   1839          *--out = '0';
   1840          ++e;
   1841       }
   1842    }
   1843 
   1844    *decimal_pos = tens;
   1845    *start = out;
   1846    *len = e;
   1847    return ng;
   1848 }
   1849 
   1850 #undef stbsp__ddmulthi
   1851 #undef stbsp__ddrenorm
   1852 #undef stbsp__ddmultlo
   1853 #undef stbsp__ddmultlos
   1854 #undef STBSP__SPECIAL
   1855 #undef STBSP__COPYFP
   1856 
   1857 #endif // STB_SPRINTF_NOFLOAT
   1858 
   1859 // clean up
   1860 #undef stbsp__uint16
   1861 #undef stbsp__uint32
   1862 #undef stbsp__int32
   1863 #undef stbsp__uint64
   1864 #undef stbsp__int64
   1865 #undef STBSP__UNALIGNED
   1866 
   1867 #endif // STB_SPRINTF_IMPLEMENTATION
   1868 
   1869 /*
   1870 ------------------------------------------------------------------------------
   1871 This software is available under 2 licenses -- choose whichever you prefer.
   1872 ------------------------------------------------------------------------------
   1873 ALTERNATIVE A - MIT License
   1874 Copyright (c) 2017 Sean Barrett
   1875 Permission is hereby granted, free of charge, to any person obtaining a copy of
   1876 this software and associated documentation files (the "Software"), to deal in
   1877 the Software without restriction, including without limitation the rights to
   1878 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   1879 of the Software, and to permit persons to whom the Software is furnished to do
   1880 so, subject to the following conditions:
   1881 The above copyright notice and this permission notice shall be included in all
   1882 copies or substantial portions of the Software.
   1883 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   1884 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   1885 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   1886 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   1887 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   1888 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   1889 SOFTWARE.
   1890 ------------------------------------------------------------------------------
   1891 ALTERNATIVE B - Public Domain (www.unlicense.org)
   1892 This is free and unencumbered software released into the public domain.
   1893 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
   1894 software, either in source code form or as a compiled binary, for any purpose,
   1895 commercial or non-commercial, and by any means.
   1896 In jurisdictions that recognize copyright laws, the author or authors of this
   1897 software dedicate any and all copyright interest in the software to the public
   1898 domain. We make this dedication for the benefit of the public at large and to
   1899 the detriment of our heirs and successors. We intend this dedication to be an
   1900 overt act of relinquishment in perpetuity of all present and future rights to
   1901 this software under copyright law.
   1902 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   1903 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   1904 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   1905 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   1906 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   1907 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   1908 ------------------------------------------------------------------------------
   1909 */