LCOV - code coverage report
Current view: top level - src - stb_sprintf.h (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 0.0 % 858 0
Test Date: 2026-05-04 07:05:02 Functions: 0.0 % 13 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 647 0

             Branch data     Line data    Source code
       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                 :           0 : STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod)
     275                 :             : {
     276                 :           0 :    stbsp__period = pperiod;
     277                 :           0 :    stbsp__comma = pcomma;
     278                 :           0 : }
     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                 :           0 : static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
     295                 :             : {
     296                 :           0 :    sign[0] = 0;
     297         [ #  # ]:           0 :    if (fl & STBSP__NEGATIVE) {
     298                 :           0 :       sign[0] = 1;
     299                 :           0 :       sign[1] = '-';
     300         [ #  # ]:           0 :    } else if (fl & STBSP__LEADINGSPACE) {
     301                 :           0 :       sign[0] = 1;
     302                 :           0 :       sign[1] = ' ';
     303         [ #  # ]:           0 :    } else if (fl & STBSP__LEADINGPLUS) {
     304                 :           0 :       sign[0] = 1;
     305                 :           0 :       sign[1] = '+';
     306                 :             :    }
     307                 :           0 : }
     308                 :             : 
     309                 :           0 : static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
     310                 :             : {
     311                 :           0 :    char const * sn = s;
     312                 :             : 
     313                 :             :    // get up to 4-byte alignment
     314                 :             :    for (;;) {
     315         [ #  # ]:           0 :       if (((stbsp__uintptr)sn & 3) == 0)
     316                 :           0 :          break;
     317                 :             : 
     318   [ #  #  #  # ]:           0 :       if (!limit || *sn == 0)
     319                 :           0 :          return (stbsp__uint32)(sn - s);
     320                 :             : 
     321                 :           0 :       ++sn;
     322                 :           0 :       --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         [ #  # ]:           0 :    while (limit >= 4) {
     331                 :           0 :       stbsp__uint32 v = *(stbsp__uint32 *)sn;
     332                 :             :       // bit hack to find if there's a 0 byte in there
     333         [ #  # ]:           0 :       if ((v - 0x01010101) & (~v) & 0x80808080UL)
     334                 :           0 :          break;
     335                 :             : 
     336                 :           0 :       sn += 4;
     337                 :           0 :       limit -= 4;
     338                 :             :    }
     339                 :             : 
     340                 :             :    // handle the last few characters to find actual size
     341   [ #  #  #  # ]:           0 :    while (limit && *sn) {
     342                 :           0 :       ++sn;
     343                 :           0 :       --limit;
     344                 :             :    }
     345                 :             : 
     346                 :           0 :    return (stbsp__uint32)(sn - s);
     347                 :             : }
     348                 :             : 
     349                 :           0 : 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                 :           0 :    int tlen = 0;
     356                 :             : 
     357                 :           0 :    bf = buf;
     358                 :           0 :    f = fmt;
     359                 :           0 :    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         [ #  # ]:           0 :          while (((stbsp__uintptr)f) & 3) {
     394                 :           0 :          schk1:
     395         [ #  # ]:           0 :             if (f[0] == '%')
     396                 :           0 :                goto scandd;
     397                 :           0 :          schk2:
     398         [ #  # ]:           0 :             if (f[0] == 0)
     399                 :           0 :                goto endfmt;
     400   [ #  #  #  #  :           0 :             stbsp__chk_cb_buf(1);
                   #  # ]
     401                 :           0 :             *bf++ = f[0];
     402                 :           0 :             ++f;
     403                 :             :          }
     404                 :           0 :          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                 :           0 :             v = *(stbsp__uint32 *)f;
     410                 :           0 :             c = (~v) & 0x80808080;
     411         [ #  # ]:           0 :             if (((v ^ 0x25252525) - 0x01010101) & c)
     412                 :           0 :                goto schk1;
     413         [ #  # ]:           0 :             if ((v - 0x01010101) & c)
     414                 :           0 :                goto schk2;
     415         [ #  # ]:           0 :             if (callback)
     416         [ #  # ]:           0 :                if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4)
     417                 :           0 :                   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                 :           0 :                 *(stbsp__uint32 *)bf = v;
     428                 :             :             }
     429                 :           0 :             bf += 4;
     430                 :           0 :             f += 4;
     431                 :             :          }
     432                 :             :       }
     433                 :           0 :    scandd:
     434                 :             : 
     435                 :           0 :       ++f;
     436                 :             : 
     437                 :             :       // ok, we have a percent, read the modifiers first
     438                 :           0 :       fw = 0;
     439                 :           0 :       pr = -1;
     440                 :           0 :       fl = 0;
     441                 :           0 :       tz = 0;
     442                 :             : 
     443                 :             :       // flags
     444                 :             :       for (;;) {
     445   [ #  #  #  #  :           0 :          switch (f[0]) {
             #  #  #  #  
                      # ]
     446                 :             :          // if we have left justify
     447                 :           0 :          case '-':
     448                 :           0 :             fl |= STBSP__LEFTJUST;
     449                 :           0 :             ++f;
     450                 :           0 :             continue;
     451                 :             :          // if we have leading plus
     452                 :           0 :          case '+':
     453                 :           0 :             fl |= STBSP__LEADINGPLUS;
     454                 :           0 :             ++f;
     455                 :           0 :             continue;
     456                 :             :          // if we have leading space
     457                 :           0 :          case ' ':
     458                 :           0 :             fl |= STBSP__LEADINGSPACE;
     459                 :           0 :             ++f;
     460                 :           0 :             continue;
     461                 :             :          // if we have leading 0x
     462                 :           0 :          case '#':
     463                 :           0 :             fl |= STBSP__LEADING_0X;
     464                 :           0 :             ++f;
     465                 :           0 :             continue;
     466                 :             :          // if we have thousand commas
     467                 :           0 :          case '\'':
     468                 :           0 :             fl |= STBSP__TRIPLET_COMMA;
     469                 :           0 :             ++f;
     470                 :           0 :             continue;
     471                 :             :          // if we have kilo marker (none->kilo->kibi->jedec)
     472                 :           0 :          case '$':
     473         [ #  # ]:           0 :             if (fl & STBSP__METRIC_SUFFIX) {
     474         [ #  # ]:           0 :                if (fl & STBSP__METRIC_1024) {
     475                 :           0 :                   fl |= STBSP__METRIC_JEDEC;
     476                 :             :                } else {
     477                 :           0 :                   fl |= STBSP__METRIC_1024;
     478                 :             :                }
     479                 :             :             } else {
     480                 :           0 :                fl |= STBSP__METRIC_SUFFIX;
     481                 :             :             }
     482                 :           0 :             ++f;
     483                 :           0 :             continue;
     484                 :             :          // if we don't want space between metric suffix and number
     485                 :           0 :          case '_':
     486                 :           0 :             fl |= STBSP__METRIC_NOSPACE;
     487                 :           0 :             ++f;
     488                 :           0 :             continue;
     489                 :             :          // if we have leading zero
     490                 :           0 :          case '0':
     491                 :           0 :             fl |= STBSP__LEADINGZERO;
     492                 :           0 :             ++f;
     493                 :           0 :             goto flags_done;
     494                 :           0 :          default: goto flags_done;
     495                 :             :          }
     496                 :             :       }
     497                 :           0 :    flags_done:
     498                 :             : 
     499                 :             :       // get the field width
     500         [ #  # ]:           0 :       if (f[0] == '*') {
     501                 :           0 :          fw = va_arg(va, stbsp__uint32);
     502                 :           0 :          ++f;
     503                 :             :       } else {
     504   [ #  #  #  # ]:           0 :          while ((f[0] >= '0') && (f[0] <= '9')) {
     505                 :           0 :             fw = fw * 10 + f[0] - '0';
     506                 :           0 :             f++;
     507                 :             :          }
     508                 :             :       }
     509                 :             :       // get the precision
     510         [ #  # ]:           0 :       if (f[0] == '.') {
     511                 :           0 :          ++f;
     512         [ #  # ]:           0 :          if (f[0] == '*') {
     513                 :           0 :             pr = va_arg(va, stbsp__uint32);
     514                 :           0 :             ++f;
     515                 :             :          } else {
     516                 :           0 :             pr = 0;
     517   [ #  #  #  # ]:           0 :             while ((f[0] >= '0') && (f[0] <= '9')) {
     518                 :           0 :                pr = pr * 10 + f[0] - '0';
     519                 :           0 :                f++;
     520                 :             :             }
     521                 :             :          }
     522                 :             :       }
     523                 :             : 
     524                 :             :       // handle integer size overrides
     525   [ #  #  #  #  :           0 :       switch (f[0]) {
                #  #  # ]
     526                 :             :       // are we halfwidth?
     527                 :           0 :       case 'h':
     528                 :           0 :          fl |= STBSP__HALFWIDTH;
     529                 :           0 :          ++f;
     530         [ #  # ]:           0 :          if (f[0] == 'h')
     531                 :           0 :             ++f;  // QUARTERWIDTH
     532                 :           0 :          break;
     533                 :             :       // are we 64-bit (unix style)
     534                 :           0 :       case 'l':
     535                 :           0 :          fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0);
     536                 :           0 :          ++f;
     537         [ #  # ]:           0 :          if (f[0] == 'l') {
     538                 :           0 :             fl |= STBSP__INTMAX;
     539                 :           0 :             ++f;
     540                 :             :          }
     541                 :           0 :          break;
     542                 :             :       // are we 64-bit on intmax? (c99)
     543                 :           0 :       case 'j':
     544                 :           0 :          fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0;
     545                 :           0 :          ++f;
     546                 :           0 :          break;
     547                 :             :       // are we 64-bit on size_t or ptrdiff_t? (c99)
     548                 :           0 :       case 'z':
     549                 :           0 :          fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
     550                 :           0 :          ++f;
     551                 :           0 :          break;
     552                 :           0 :       case 't':
     553                 :           0 :          fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
     554                 :           0 :          ++f;
     555                 :           0 :          break;
     556                 :             :       // are we 64-bit (msft style)
     557                 :           0 :       case 'I':
     558   [ #  #  #  # ]:           0 :          if ((f[1] == '6') && (f[2] == '4')) {
     559                 :           0 :             fl |= STBSP__INTMAX;
     560                 :           0 :             f += 3;
     561   [ #  #  #  # ]:           0 :          } else if ((f[1] == '3') && (f[2] == '2')) {
     562                 :           0 :             f += 3;
     563                 :             :          } else {
     564                 :           0 :             fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0);
     565                 :           0 :             ++f;
     566                 :             :          }
     567                 :           0 :          break;
     568                 :           0 :       default: break;
     569                 :             :       }
     570                 :             : 
     571                 :             :       // handle each replacement
     572   [ #  #  #  #  :           0 :       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                 :           0 :       case 's':
     588                 :             :          // get the string
     589                 :           0 :          s = va_arg(va, char *);
     590         [ #  # ]:           0 :          if (s == 0)
     591                 :           0 :             s = (char *)"null";
     592                 :             :          // get the length, limited to desired precision
     593                 :             :          // always limit to ~0u chars since our counts are 32b
     594         [ #  # ]:           0 :          l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
     595                 :           0 :          lead[0] = 0;
     596                 :           0 :          tail[0] = 0;
     597                 :           0 :          pr = 0;
     598                 :           0 :          dp = 0;
     599                 :           0 :          cs = 0;
     600                 :             :          // copy the string in
     601                 :           0 :          goto scopy;
     602                 :             : 
     603                 :           0 :       case 'c': // char
     604                 :             :          // get the character
     605                 :           0 :          s = num + STBSP__NUMSZ - 1;
     606                 :           0 :          *s = (char)va_arg(va, int);
     607                 :           0 :          l = 1;
     608                 :           0 :          lead[0] = 0;
     609                 :           0 :          tail[0] = 0;
     610                 :           0 :          pr = 0;
     611                 :           0 :          dp = 0;
     612                 :           0 :          cs = 0;
     613                 :           0 :          goto scopy;
     614                 :             : 
     615                 :           0 :       case 'n': // weird write-bytes specifier
     616                 :             :       {
     617                 :           0 :          int *d = va_arg(va, int *);
     618                 :           0 :          *d = tlen + (int)(bf - buf);
     619                 :           0 :       } break;
     620                 :             : 
     621                 :             : #ifdef STB_SPRINTF_NOFLOAT
     622                 :             :       case 'A':              // float
     623                 :             :       case 'a':              // hex float
     624                 :             :       case 'G':              // float
     625                 :             :       case 'g':              // float
     626                 :             :       case 'E':              // float
     627                 :             :       case 'e':              // float
     628                 :             :       case 'f':              // float
     629                 :             :          va_arg(va, double); // eat it
     630                 :             :          s = (char *)"No float";
     631                 :             :          l = 8;
     632                 :             :          lead[0] = 0;
     633                 :             :          tail[0] = 0;
     634                 :             :          pr = 0;
     635                 :             :          cs = 0;
     636                 :             :          STBSP__NOTUSED(dp);
     637                 :             :          goto scopy;
     638                 :             : #else
     639                 :           0 :       case 'A': // hex float
     640                 :             :       case 'a': // hex float
     641         [ #  # ]:           0 :          h = (f[0] == 'A') ? hexu : hex;
     642                 :           0 :          fv = va_arg(va, double);
     643         [ #  # ]:           0 :          if (pr == -1)
     644                 :           0 :             pr = 6; // default is 6
     645                 :             :          // read the double into a string
     646         [ #  # ]:           0 :          if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv))
     647                 :           0 :             fl |= STBSP__NEGATIVE;
     648                 :             : 
     649                 :           0 :          s = num + 64;
     650                 :             : 
     651                 :           0 :          stbsp__lead_sign(fl, lead);
     652                 :             : 
     653         [ #  # ]:           0 :          if (dp == -1023)
     654         [ #  # ]:           0 :             dp = (n64) ? -1022 : 0;
     655                 :             :          else
     656                 :           0 :             n64 |= (((stbsp__uint64)1) << 52);
     657                 :           0 :          n64 <<= (64 - 56);
     658         [ #  # ]:           0 :          if (pr < 15)
     659                 :           0 :             n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4));
     660                 :             : // add leading chars
     661                 :             : 
     662                 :             : #ifdef STB_SPRINTF_MSVC_MODE
     663                 :             :          *s++ = '0';
     664                 :             :          *s++ = 'x';
     665                 :             : #else
     666                 :           0 :          lead[1 + lead[0]] = '0';
     667                 :           0 :          lead[2 + lead[0]] = 'x';
     668                 :           0 :          lead[0] += 2;
     669                 :             : #endif
     670                 :           0 :          *s++ = h[(n64 >> 60) & 15];
     671                 :           0 :          n64 <<= 4;
     672         [ #  # ]:           0 :          if (pr)
     673                 :           0 :             *s++ = stbsp__period;
     674                 :           0 :          sn = s;
     675                 :             : 
     676                 :             :          // print the bits
     677                 :           0 :          n = pr;
     678         [ #  # ]:           0 :          if (n > 13)
     679                 :           0 :             n = 13;
     680         [ #  # ]:           0 :          if (pr > (stbsp__int32)n)
     681                 :           0 :             tz = pr - n;
     682                 :           0 :          pr = 0;
     683         [ #  # ]:           0 :          while (n--) {
     684                 :           0 :             *s++ = h[(n64 >> 60) & 15];
     685                 :           0 :             n64 <<= 4;
     686                 :             :          }
     687                 :             : 
     688                 :             :          // print the expo
     689                 :           0 :          tail[1] = h[17];
     690         [ #  # ]:           0 :          if (dp < 0) {
     691                 :           0 :             tail[2] = '-';
     692                 :           0 :             dp = -dp;
     693                 :             :          } else
     694                 :           0 :             tail[2] = '+';
     695   [ #  #  #  #  :           0 :          n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3));
                   #  # ]
     696                 :           0 :          tail[0] = (char)n;
     697                 :             :          for (;;) {
     698                 :           0 :             tail[n] = '0' + dp % 10;
     699         [ #  # ]:           0 :             if (n <= 3)
     700                 :           0 :                break;
     701                 :           0 :             --n;
     702                 :           0 :             dp /= 10;
     703                 :             :          }
     704                 :             : 
     705                 :           0 :          dp = (int)(s - sn);
     706                 :           0 :          l = (int)(s - (num + 64));
     707                 :           0 :          s = num + 64;
     708                 :           0 :          cs = 1 + (3 << 24);
     709                 :           0 :          goto scopy;
     710                 :             : 
     711                 :           0 :       case 'G': // float
     712                 :             :       case 'g': // float
     713         [ #  # ]:           0 :          h = (f[0] == 'G') ? hexu : hex;
     714                 :           0 :          fv = va_arg(va, double);
     715         [ #  # ]:           0 :          if (pr == -1)
     716                 :           0 :             pr = 6;
     717         [ #  # ]:           0 :          else if (pr == 0)
     718                 :           0 :             pr = 1; // default is 6
     719                 :             :          // read the double into a string
     720         [ #  # ]:           0 :          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000))
     721                 :           0 :             fl |= STBSP__NEGATIVE;
     722                 :             : 
     723                 :             :          // clamp the precision and delete extra zeros after clamp
     724                 :           0 :          n = pr;
     725         [ #  # ]:           0 :          if (l > (stbsp__uint32)pr)
     726                 :           0 :             l = pr;
     727   [ #  #  #  #  :           0 :          while ((l > 1) && (pr) && (sn[l - 1] == '0')) {
                   #  # ]
     728                 :           0 :             --pr;
     729                 :           0 :             --l;
     730                 :             :          }
     731                 :             : 
     732                 :             :          // should we use %e
     733   [ #  #  #  # ]:           0 :          if ((dp <= -4) || (dp > (stbsp__int32)n)) {
     734         [ #  # ]:           0 :             if (pr > (stbsp__int32)l)
     735                 :           0 :                pr = l - 1;
     736         [ #  # ]:           0 :             else if (pr)
     737                 :           0 :                --pr; // when using %e, there is one digit before the decimal
     738                 :           0 :             goto doexpfromg;
     739                 :             :          }
     740                 :             :          // this is the insane action to get the pr to match %g semantics for %f
     741         [ #  # ]:           0 :          if (dp > 0) {
     742         [ #  # ]:           0 :             pr = (dp < (stbsp__int32)l) ? l - dp : 0;
     743                 :             :          } else {
     744                 :           0 :             pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr);
     745                 :             :          }
     746                 :           0 :          goto dofloatfromg;
     747                 :             : 
     748                 :           0 :       case 'E': // float
     749                 :             :       case 'e': // float
     750         [ #  # ]:           0 :          h = (f[0] == 'E') ? hexu : hex;
     751                 :           0 :          fv = va_arg(va, double);
     752         [ #  # ]:           0 :          if (pr == -1)
     753                 :           0 :             pr = 6; // default is 6
     754                 :             :          // read the double into a string
     755         [ #  # ]:           0 :          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000))
     756                 :           0 :             fl |= STBSP__NEGATIVE;
     757                 :           0 :       doexpfromg:
     758                 :           0 :          tail[0] = 0;
     759                 :           0 :          stbsp__lead_sign(fl, lead);
     760         [ #  # ]:           0 :          if (dp == STBSP__SPECIAL) {
     761                 :           0 :             s = (char *)sn;
     762                 :           0 :             cs = 0;
     763                 :           0 :             pr = 0;
     764                 :           0 :             goto scopy;
     765                 :             :          }
     766                 :           0 :          s = num + 64;
     767                 :             :          // handle leading chars
     768                 :           0 :          *s++ = sn[0];
     769                 :             : 
     770         [ #  # ]:           0 :          if (pr)
     771                 :           0 :             *s++ = stbsp__period;
     772                 :             : 
     773                 :             :          // handle after decimal
     774         [ #  # ]:           0 :          if ((l - 1) > (stbsp__uint32)pr)
     775                 :           0 :             l = pr + 1;
     776         [ #  # ]:           0 :          for (n = 1; n < l; n++)
     777                 :           0 :             *s++ = sn[n];
     778                 :             :          // trailing zeros
     779                 :           0 :          tz = pr - (l - 1);
     780                 :           0 :          pr = 0;
     781                 :             :          // dump expo
     782                 :           0 :          tail[1] = h[0xe];
     783                 :           0 :          dp -= 1;
     784         [ #  # ]:           0 :          if (dp < 0) {
     785                 :           0 :             tail[2] = '-';
     786                 :           0 :             dp = -dp;
     787                 :             :          } else
     788                 :           0 :             tail[2] = '+';
     789                 :             : #ifdef STB_SPRINTF_MSVC_MODE
     790                 :             :          n = 5;
     791                 :             : #else
     792         [ #  # ]:           0 :          n = (dp >= 100) ? 5 : 4;
     793                 :             : #endif
     794                 :           0 :          tail[0] = (char)n;
     795                 :             :          for (;;) {
     796                 :           0 :             tail[n] = '0' + dp % 10;
     797         [ #  # ]:           0 :             if (n <= 3)
     798                 :           0 :                break;
     799                 :           0 :             --n;
     800                 :           0 :             dp /= 10;
     801                 :             :          }
     802                 :           0 :          cs = 1 + (3 << 24); // how many tens
     803                 :           0 :          goto flt_lead;
     804                 :             : 
     805                 :           0 :       case 'f': // float
     806                 :           0 :          fv = va_arg(va, double);
     807                 :           0 :       doafloat:
     808                 :             :          // do kilos
     809         [ #  # ]:           0 :          if (fl & STBSP__METRIC_SUFFIX) {
     810                 :             :             double divisor;
     811                 :           0 :             divisor = 1000.0f;
     812         [ #  # ]:           0 :             if (fl & STBSP__METRIC_1024)
     813                 :           0 :                divisor = 1024.0;
     814         [ #  # ]:           0 :             while (fl < 0x4000000) {
     815   [ #  #  #  # ]:           0 :                if ((fv < divisor) && (fv > -divisor))
     816                 :           0 :                   break;
     817                 :           0 :                fv /= divisor;
     818                 :           0 :                fl += 0x1000000;
     819                 :             :             }
     820                 :             :          }
     821         [ #  # ]:           0 :          if (pr == -1)
     822                 :           0 :             pr = 6; // default is 6
     823                 :             :          // read the double into a string
     824         [ #  # ]:           0 :          if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr))
     825                 :           0 :             fl |= STBSP__NEGATIVE;
     826                 :           0 :       dofloatfromg:
     827                 :           0 :          tail[0] = 0;
     828                 :           0 :          stbsp__lead_sign(fl, lead);
     829         [ #  # ]:           0 :          if (dp == STBSP__SPECIAL) {
     830                 :           0 :             s = (char *)sn;
     831                 :           0 :             cs = 0;
     832                 :           0 :             pr = 0;
     833                 :           0 :             goto scopy;
     834                 :             :          }
     835                 :           0 :          s = num + 64;
     836                 :             : 
     837                 :             :          // handle the three decimal varieties
     838         [ #  # ]:           0 :          if (dp <= 0) {
     839                 :             :             stbsp__int32 i;
     840                 :             :             // handle 0.000*000xxxx
     841                 :           0 :             *s++ = '0';
     842         [ #  # ]:           0 :             if (pr)
     843                 :           0 :                *s++ = stbsp__period;
     844                 :           0 :             n = -dp;
     845         [ #  # ]:           0 :             if ((stbsp__int32)n > pr)
     846                 :           0 :                n = pr;
     847                 :           0 :             i = n;
     848         [ #  # ]:           0 :             while (i) {
     849         [ #  # ]:           0 :                if ((((stbsp__uintptr)s) & 3) == 0)
     850                 :           0 :                   break;
     851                 :           0 :                *s++ = '0';
     852                 :           0 :                --i;
     853                 :             :             }
     854         [ #  # ]:           0 :             while (i >= 4) {
     855                 :           0 :                *(stbsp__uint32 *)s = 0x30303030;
     856                 :           0 :                s += 4;
     857                 :           0 :                i -= 4;
     858                 :             :             }
     859         [ #  # ]:           0 :             while (i) {
     860                 :           0 :                *s++ = '0';
     861                 :           0 :                --i;
     862                 :             :             }
     863         [ #  # ]:           0 :             if ((stbsp__int32)(l + n) > pr)
     864                 :           0 :                l = pr - n;
     865                 :           0 :             i = l;
     866         [ #  # ]:           0 :             while (i) {
     867                 :           0 :                *s++ = *sn++;
     868                 :           0 :                --i;
     869                 :             :             }
     870                 :           0 :             tz = pr - (n + l);
     871                 :           0 :             cs = 1 + (3 << 24); // how many tens did we write (for commas below)
     872                 :             :          } else {
     873         [ #  # ]:           0 :             cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0;
     874         [ #  # ]:           0 :             if ((stbsp__uint32)dp >= l) {
     875                 :             :                // handle xxxx000*000.0
     876                 :           0 :                n = 0;
     877                 :             :                for (;;) {
     878   [ #  #  #  # ]:           0 :                   if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
     879                 :           0 :                      cs = 0;
     880                 :           0 :                      *s++ = stbsp__comma;
     881                 :             :                   } else {
     882                 :           0 :                      *s++ = sn[n];
     883                 :           0 :                      ++n;
     884         [ #  # ]:           0 :                      if (n >= l)
     885                 :           0 :                         break;
     886                 :             :                   }
     887                 :             :                }
     888         [ #  # ]:           0 :                if (n < (stbsp__uint32)dp) {
     889                 :           0 :                   n = dp - n;
     890         [ #  # ]:           0 :                   if ((fl & STBSP__TRIPLET_COMMA) == 0) {
     891         [ #  # ]:           0 :                      while (n) {
     892         [ #  # ]:           0 :                         if ((((stbsp__uintptr)s) & 3) == 0)
     893                 :           0 :                            break;
     894                 :           0 :                         *s++ = '0';
     895                 :           0 :                         --n;
     896                 :             :                      }
     897         [ #  # ]:           0 :                      while (n >= 4) {
     898                 :           0 :                         *(stbsp__uint32 *)s = 0x30303030;
     899                 :           0 :                         s += 4;
     900                 :           0 :                         n -= 4;
     901                 :             :                      }
     902                 :             :                   }
     903         [ #  # ]:           0 :                   while (n) {
     904   [ #  #  #  # ]:           0 :                      if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
     905                 :           0 :                         cs = 0;
     906                 :           0 :                         *s++ = stbsp__comma;
     907                 :             :                      } else {
     908                 :           0 :                         *s++ = '0';
     909                 :           0 :                         --n;
     910                 :             :                      }
     911                 :             :                   }
     912                 :             :                }
     913                 :           0 :                cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
     914         [ #  # ]:           0 :                if (pr) {
     915                 :           0 :                   *s++ = stbsp__period;
     916                 :           0 :                   tz = pr;
     917                 :             :                }
     918                 :             :             } else {
     919                 :             :                // handle xxxxx.xxxx000*000
     920                 :           0 :                n = 0;
     921                 :             :                for (;;) {
     922   [ #  #  #  # ]:           0 :                   if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
     923                 :           0 :                      cs = 0;
     924                 :           0 :                      *s++ = stbsp__comma;
     925                 :             :                   } else {
     926                 :           0 :                      *s++ = sn[n];
     927                 :           0 :                      ++n;
     928         [ #  # ]:           0 :                      if (n >= (stbsp__uint32)dp)
     929                 :           0 :                         break;
     930                 :             :                   }
     931                 :             :                }
     932                 :           0 :                cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
     933         [ #  # ]:           0 :                if (pr)
     934                 :           0 :                   *s++ = stbsp__period;
     935         [ #  # ]:           0 :                if ((l - dp) > (stbsp__uint32)pr)
     936                 :           0 :                   l = pr + dp;
     937         [ #  # ]:           0 :                while (n < l) {
     938                 :           0 :                   *s++ = sn[n];
     939                 :           0 :                   ++n;
     940                 :             :                }
     941                 :           0 :                tz = pr - (l - dp);
     942                 :             :             }
     943                 :             :          }
     944                 :           0 :          pr = 0;
     945                 :             : 
     946                 :             :          // handle k,m,g,t
     947         [ #  # ]:           0 :          if (fl & STBSP__METRIC_SUFFIX) {
     948                 :             :             char idx;
     949                 :           0 :             idx = 1;
     950         [ #  # ]:           0 :             if (fl & STBSP__METRIC_NOSPACE)
     951                 :           0 :                idx = 0;
     952                 :           0 :             tail[0] = idx;
     953                 :           0 :             tail[1] = ' ';
     954                 :             :             {
     955         [ #  # ]:           0 :                if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'.
     956         [ #  # ]:           0 :                   if (fl & STBSP__METRIC_1024)
     957                 :           0 :                      tail[idx + 1] = "_KMGT"[fl >> 24];
     958                 :             :                   else
     959                 :           0 :                      tail[idx + 1] = "_kMGT"[fl >> 24];
     960                 :           0 :                   idx++;
     961                 :             :                   // If printing kibits and not in jedec, add the 'i'.
     962   [ #  #  #  # ]:           0 :                   if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) {
     963                 :           0 :                      tail[idx + 1] = 'i';
     964                 :           0 :                      idx++;
     965                 :             :                   }
     966                 :           0 :                   tail[0] = idx;
     967                 :             :                }
     968                 :             :             }
     969                 :             :          };
     970                 :             : 
     971                 :           0 :       flt_lead:
     972                 :             :          // get the length that we copied
     973                 :           0 :          l = (stbsp__uint32)(s - (num + 64));
     974                 :           0 :          s = num + 64;
     975                 :           0 :          goto scopy;
     976                 :             : #endif
     977                 :             : 
     978                 :           0 :       case 'B': // upper binary
     979                 :             :       case 'b': // lower binary
     980         [ #  # ]:           0 :          h = (f[0] == 'B') ? hexu : hex;
     981                 :           0 :          lead[0] = 0;
     982         [ #  # ]:           0 :          if (fl & STBSP__LEADING_0X) {
     983                 :           0 :             lead[0] = 2;
     984                 :           0 :             lead[1] = '0';
     985                 :           0 :             lead[2] = h[0xb];
     986                 :             :          }
     987                 :           0 :          l = (8 << 4) | (1 << 8);
     988                 :           0 :          goto radixnum;
     989                 :             : 
     990                 :           0 :       case 'o': // octal
     991                 :           0 :          h = hexu;
     992                 :           0 :          lead[0] = 0;
     993         [ #  # ]:           0 :          if (fl & STBSP__LEADING_0X) {
     994                 :           0 :             lead[0] = 1;
     995                 :           0 :             lead[1] = '0';
     996                 :             :          }
     997                 :           0 :          l = (3 << 4) | (3 << 8);
     998                 :           0 :          goto radixnum;
     999                 :             : 
    1000                 :           0 :       case 'p': // pointer
    1001                 :           0 :          fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0;
    1002                 :           0 :          pr = sizeof(void *) * 2;
    1003                 :           0 :          fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros
    1004                 :             :                                     // fall through - to X
    1005                 :             : 
    1006                 :           0 :       case 'X': // upper hex
    1007                 :             :       case 'x': // lower hex
    1008         [ #  # ]:           0 :          h = (f[0] == 'X') ? hexu : hex;
    1009                 :           0 :          l = (4 << 4) | (4 << 8);
    1010                 :           0 :          lead[0] = 0;
    1011         [ #  # ]:           0 :          if (fl & STBSP__LEADING_0X) {
    1012                 :           0 :             lead[0] = 2;
    1013                 :           0 :             lead[1] = '0';
    1014                 :           0 :             lead[2] = h[16];
    1015                 :             :          }
    1016                 :           0 :       radixnum:
    1017                 :             :          // get the number
    1018         [ #  # ]:           0 :          if (fl & STBSP__INTMAX)
    1019                 :           0 :             n64 = va_arg(va, stbsp__uint64);
    1020                 :             :          else
    1021                 :           0 :             n64 = va_arg(va, stbsp__uint32);
    1022                 :             : 
    1023                 :           0 :          s = num + STBSP__NUMSZ;
    1024                 :           0 :          dp = 0;
    1025                 :             :          // clear tail, and clear leading if value is zero
    1026                 :           0 :          tail[0] = 0;
    1027         [ #  # ]:           0 :          if (n64 == 0) {
    1028                 :           0 :             lead[0] = 0;
    1029         [ #  # ]:           0 :             if (pr == 0) {
    1030                 :           0 :                l = 0;
    1031                 :           0 :                cs = 0;
    1032                 :           0 :                goto scopy;
    1033                 :             :             }
    1034                 :             :          }
    1035                 :             :          // convert to string
    1036                 :             :          for (;;) {
    1037                 :           0 :             *--s = h[n64 & ((1 << (l >> 8)) - 1)];
    1038                 :           0 :             n64 >>= (l >> 8);
    1039   [ #  #  #  # ]:           0 :             if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr)))
    1040                 :           0 :                break;
    1041         [ #  # ]:           0 :             if (fl & STBSP__TRIPLET_COMMA) {
    1042                 :           0 :                ++l;
    1043         [ #  # ]:           0 :                if ((l & 15) == ((l >> 4) & 15)) {
    1044                 :           0 :                   l &= ~15;
    1045                 :           0 :                   *--s = stbsp__comma;
    1046                 :             :                }
    1047                 :             :             }
    1048                 :             :          };
    1049                 :             :          // get the tens and the comma pos
    1050                 :           0 :          cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24);
    1051                 :             :          // get the length that we copied
    1052                 :           0 :          l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
    1053                 :             :          // copy it
    1054                 :           0 :          goto scopy;
    1055                 :             : 
    1056                 :           0 :       case 'u': // unsigned
    1057                 :             :       case 'i':
    1058                 :             :       case 'd': // integer
    1059                 :             :          // get the integer and abs it
    1060         [ #  # ]:           0 :          if (fl & STBSP__INTMAX) {
    1061                 :           0 :             stbsp__int64 i64 = va_arg(va, stbsp__int64);
    1062                 :           0 :             n64 = (stbsp__uint64)i64;
    1063   [ #  #  #  # ]:           0 :             if ((f[0] != 'u') && (i64 < 0)) {
    1064                 :           0 :                n64 = (stbsp__uint64)-i64;
    1065                 :           0 :                fl |= STBSP__NEGATIVE;
    1066                 :             :             }
    1067                 :             :          } else {
    1068                 :           0 :             stbsp__int32 i = va_arg(va, stbsp__int32);
    1069                 :           0 :             n64 = (stbsp__uint32)i;
    1070   [ #  #  #  # ]:           0 :             if ((f[0] != 'u') && (i < 0)) {
    1071                 :           0 :                n64 = (stbsp__uint32)-i;
    1072                 :           0 :                fl |= STBSP__NEGATIVE;
    1073                 :             :             }
    1074                 :             :          }
    1075                 :             : 
    1076                 :             : #ifndef STB_SPRINTF_NOFLOAT
    1077         [ #  # ]:           0 :          if (fl & STBSP__METRIC_SUFFIX) {
    1078         [ #  # ]:           0 :             if (n64 < 1024)
    1079                 :           0 :                pr = 0;
    1080         [ #  # ]:           0 :             else if (pr == -1)
    1081                 :           0 :                pr = 1;
    1082                 :           0 :             fv = (double)(stbsp__int64)n64;
    1083                 :           0 :             goto doafloat;
    1084                 :             :          }
    1085                 :             : #endif
    1086                 :             : 
    1087                 :             :          // convert to string
    1088                 :           0 :          s = num + STBSP__NUMSZ;
    1089                 :           0 :          l = 0;
    1090                 :             : 
    1091                 :           0 :          for (;;) {
    1092                 :             :             // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators)
    1093                 :           0 :             char *o = s - 8;
    1094         [ #  # ]:           0 :             if (n64 >= 100000000) {
    1095                 :           0 :                n = (stbsp__uint32)(n64 % 100000000);
    1096                 :           0 :                n64 /= 100000000;
    1097                 :             :             } else {
    1098                 :           0 :                n = (stbsp__uint32)n64;
    1099                 :           0 :                n64 = 0;
    1100                 :             :             }
    1101         [ #  # ]:           0 :             if ((fl & STBSP__TRIPLET_COMMA) == 0) {
    1102                 :             :                do {
    1103                 :           0 :                   s -= 2;
    1104                 :           0 :                   *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
    1105                 :           0 :                   n /= 100;
    1106         [ #  # ]:           0 :                } while (n);
    1107                 :             :             }
    1108         [ #  # ]:           0 :             while (n) {
    1109   [ #  #  #  # ]:           0 :                if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
    1110                 :           0 :                   l = 0;
    1111                 :           0 :                   *--s = stbsp__comma;
    1112                 :           0 :                   --o;
    1113                 :             :                } else {
    1114                 :           0 :                   *--s = (char)(n % 10) + '0';
    1115                 :           0 :                   n /= 10;
    1116                 :             :                }
    1117                 :             :             }
    1118         [ #  # ]:           0 :             if (n64 == 0) {
    1119   [ #  #  #  # ]:           0 :                if ((s[0] == '0') && (s != (num + STBSP__NUMSZ)))
    1120                 :           0 :                   ++s;
    1121                 :           0 :                break;
    1122                 :             :             }
    1123         [ #  # ]:           0 :             while (s != o)
    1124   [ #  #  #  # ]:           0 :                if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
    1125                 :           0 :                   l = 0;
    1126                 :           0 :                   *--s = stbsp__comma;
    1127                 :           0 :                   --o;
    1128                 :             :                } else {
    1129                 :           0 :                   *--s = '0';
    1130                 :             :                }
    1131                 :             :          }
    1132                 :             : 
    1133                 :           0 :          tail[0] = 0;
    1134                 :           0 :          stbsp__lead_sign(fl, lead);
    1135                 :             : 
    1136                 :             :          // get the length that we copied
    1137                 :           0 :          l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
    1138         [ #  # ]:           0 :          if (l == 0) {
    1139                 :           0 :             *--s = '0';
    1140                 :           0 :             l = 1;
    1141                 :             :          }
    1142                 :           0 :          cs = l + (3 << 24);
    1143         [ #  # ]:           0 :          if (pr < 0)
    1144                 :           0 :             pr = 0;
    1145                 :             : 
    1146                 :           0 :       scopy:
    1147                 :             :          // get fw=leading/trailing space, pr=leading zeros
    1148         [ #  # ]:           0 :          if (pr < (stbsp__int32)l)
    1149                 :           0 :             pr = l;
    1150                 :           0 :          n = pr + lead[0] + tail[0] + tz;
    1151         [ #  # ]:           0 :          if (fw < (stbsp__int32)n)
    1152                 :           0 :             fw = n;
    1153                 :           0 :          fw -= n;
    1154                 :           0 :          pr -= l;
    1155                 :             : 
    1156                 :             :          // handle right justify and leading zeros
    1157         [ #  # ]:           0 :          if ((fl & STBSP__LEFTJUST) == 0) {
    1158         [ #  # ]:           0 :             if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr
    1159                 :             :             {
    1160                 :           0 :                pr = (fw > pr) ? fw : pr;
    1161                 :           0 :                fw = 0;
    1162                 :             :             } else {
    1163                 :           0 :                fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas
    1164                 :             :             }
    1165                 :             :          }
    1166                 :             : 
    1167                 :             :          // copy the spaces and/or zeros
    1168         [ #  # ]:           0 :          if (fw + pr) {
    1169                 :             :             stbsp__int32 i;
    1170                 :             :             stbsp__uint32 c;
    1171                 :             : 
    1172                 :             :             // copy leading spaces (or when doing %8.4d stuff)
    1173         [ #  # ]:           0 :             if ((fl & STBSP__LEFTJUST) == 0)
    1174         [ #  # ]:           0 :                while (fw > 0) {
    1175   [ #  #  #  # ]:           0 :                   stbsp__cb_buf_clamp(i, fw);
    1176                 :           0 :                   fw -= i;
    1177         [ #  # ]:           0 :                   while (i) {
    1178         [ #  # ]:           0 :                      if ((((stbsp__uintptr)bf) & 3) == 0)
    1179                 :           0 :                         break;
    1180                 :           0 :                      *bf++ = ' ';
    1181                 :           0 :                      --i;
    1182                 :             :                   }
    1183         [ #  # ]:           0 :                   while (i >= 4) {
    1184                 :           0 :                      *(stbsp__uint32 *)bf = 0x20202020;
    1185                 :           0 :                      bf += 4;
    1186                 :           0 :                      i -= 4;
    1187                 :             :                   }
    1188         [ #  # ]:           0 :                   while (i) {
    1189                 :           0 :                      *bf++ = ' ';
    1190                 :           0 :                      --i;
    1191                 :             :                   }
    1192   [ #  #  #  #  :           0 :                   stbsp__chk_cb_buf(1);
                   #  # ]
    1193                 :             :                }
    1194                 :             : 
    1195                 :             :             // copy leader
    1196                 :           0 :             sn = lead + 1;
    1197         [ #  # ]:           0 :             while (lead[0]) {
    1198   [ #  #  #  # ]:           0 :                stbsp__cb_buf_clamp(i, lead[0]);
    1199                 :           0 :                lead[0] -= (char)i;
    1200         [ #  # ]:           0 :                while (i) {
    1201                 :           0 :                   *bf++ = *sn++;
    1202                 :           0 :                   --i;
    1203                 :             :                }
    1204   [ #  #  #  #  :           0 :                stbsp__chk_cb_buf(1);
                   #  # ]
    1205                 :             :             }
    1206                 :             : 
    1207                 :             :             // copy leading zeros
    1208                 :           0 :             c = cs >> 24;
    1209                 :           0 :             cs &= 0xffffff;
    1210         [ #  # ]:           0 :             cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0;
    1211         [ #  # ]:           0 :             while (pr > 0) {
    1212   [ #  #  #  # ]:           0 :                stbsp__cb_buf_clamp(i, pr);
    1213                 :           0 :                pr -= i;
    1214         [ #  # ]:           0 :                if ((fl & STBSP__TRIPLET_COMMA) == 0) {
    1215         [ #  # ]:           0 :                   while (i) {
    1216         [ #  # ]:           0 :                      if ((((stbsp__uintptr)bf) & 3) == 0)
    1217                 :           0 :                         break;
    1218                 :           0 :                      *bf++ = '0';
    1219                 :           0 :                      --i;
    1220                 :             :                   }
    1221         [ #  # ]:           0 :                   while (i >= 4) {
    1222                 :           0 :                      *(stbsp__uint32 *)bf = 0x30303030;
    1223                 :           0 :                      bf += 4;
    1224                 :           0 :                      i -= 4;
    1225                 :             :                   }
    1226                 :             :                }
    1227         [ #  # ]:           0 :                while (i) {
    1228   [ #  #  #  # ]:           0 :                   if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) {
    1229                 :           0 :                      cs = 0;
    1230                 :           0 :                      *bf++ = stbsp__comma;
    1231                 :             :                   } else
    1232                 :           0 :                      *bf++ = '0';
    1233                 :           0 :                   --i;
    1234                 :             :                }
    1235   [ #  #  #  #  :           0 :                stbsp__chk_cb_buf(1);
                   #  # ]
    1236                 :             :             }
    1237                 :             :          }
    1238                 :             : 
    1239                 :             :          // copy leader if there is still one
    1240                 :           0 :          sn = lead + 1;
    1241         [ #  # ]:           0 :          while (lead[0]) {
    1242                 :             :             stbsp__int32 i;
    1243   [ #  #  #  # ]:           0 :             stbsp__cb_buf_clamp(i, lead[0]);
    1244                 :           0 :             lead[0] -= (char)i;
    1245         [ #  # ]:           0 :             while (i) {
    1246                 :           0 :                *bf++ = *sn++;
    1247                 :           0 :                --i;
    1248                 :             :             }
    1249   [ #  #  #  #  :           0 :             stbsp__chk_cb_buf(1);
                   #  # ]
    1250                 :             :          }
    1251                 :             : 
    1252                 :             :          // copy the string
    1253                 :           0 :          n = l;
    1254         [ #  # ]:           0 :          while (n) {
    1255                 :             :             stbsp__int32 i;
    1256   [ #  #  #  # ]:           0 :             stbsp__cb_buf_clamp(i, n);
    1257                 :           0 :             n -= i;
    1258         [ #  # ]:           0 :             STBSP__UNALIGNED(while (i >= 4) {
    1259                 :             :                *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s;
    1260                 :             :                bf += 4;
    1261                 :             :                s += 4;
    1262                 :             :                i -= 4;
    1263                 :             :             })
    1264         [ #  # ]:           0 :             while (i) {
    1265                 :           0 :                *bf++ = *s++;
    1266                 :           0 :                --i;
    1267                 :             :             }
    1268   [ #  #  #  #  :           0 :             stbsp__chk_cb_buf(1);
                   #  # ]
    1269                 :             :          }
    1270                 :             : 
    1271                 :             :          // copy trailing zeros
    1272         [ #  # ]:           0 :          while (tz) {
    1273                 :             :             stbsp__int32 i;
    1274   [ #  #  #  # ]:           0 :             stbsp__cb_buf_clamp(i, tz);
    1275                 :           0 :             tz -= i;
    1276         [ #  # ]:           0 :             while (i) {
    1277         [ #  # ]:           0 :                if ((((stbsp__uintptr)bf) & 3) == 0)
    1278                 :           0 :                   break;
    1279                 :           0 :                *bf++ = '0';
    1280                 :           0 :                --i;
    1281                 :             :             }
    1282         [ #  # ]:           0 :             while (i >= 4) {
    1283                 :           0 :                *(stbsp__uint32 *)bf = 0x30303030;
    1284                 :           0 :                bf += 4;
    1285                 :           0 :                i -= 4;
    1286                 :             :             }
    1287         [ #  # ]:           0 :             while (i) {
    1288                 :           0 :                *bf++ = '0';
    1289                 :           0 :                --i;
    1290                 :             :             }
    1291   [ #  #  #  #  :           0 :             stbsp__chk_cb_buf(1);
                   #  # ]
    1292                 :             :          }
    1293                 :             : 
    1294                 :             :          // copy tail if there is one
    1295                 :           0 :          sn = tail + 1;
    1296         [ #  # ]:           0 :          while (tail[0]) {
    1297                 :             :             stbsp__int32 i;
    1298   [ #  #  #  # ]:           0 :             stbsp__cb_buf_clamp(i, tail[0]);
    1299                 :           0 :             tail[0] -= (char)i;
    1300         [ #  # ]:           0 :             while (i) {
    1301                 :           0 :                *bf++ = *sn++;
    1302                 :           0 :                --i;
    1303                 :             :             }
    1304   [ #  #  #  #  :           0 :             stbsp__chk_cb_buf(1);
                   #  # ]
    1305                 :             :          }
    1306                 :             : 
    1307                 :             :          // handle the left justify
    1308         [ #  # ]:           0 :          if (fl & STBSP__LEFTJUST)
    1309         [ #  # ]:           0 :             if (fw > 0) {
    1310         [ #  # ]:           0 :                while (fw) {
    1311                 :             :                   stbsp__int32 i;
    1312   [ #  #  #  # ]:           0 :                   stbsp__cb_buf_clamp(i, fw);
    1313                 :           0 :                   fw -= i;
    1314         [ #  # ]:           0 :                   while (i) {
    1315         [ #  # ]:           0 :                      if ((((stbsp__uintptr)bf) & 3) == 0)
    1316                 :           0 :                         break;
    1317                 :           0 :                      *bf++ = ' ';
    1318                 :           0 :                      --i;
    1319                 :             :                   }
    1320         [ #  # ]:           0 :                   while (i >= 4) {
    1321                 :           0 :                      *(stbsp__uint32 *)bf = 0x20202020;
    1322                 :           0 :                      bf += 4;
    1323                 :           0 :                      i -= 4;
    1324                 :             :                   }
    1325         [ #  # ]:           0 :                   while (i--)
    1326                 :           0 :                      *bf++ = ' ';
    1327   [ #  #  #  #  :           0 :                   stbsp__chk_cb_buf(1);
                   #  # ]
    1328                 :             :                }
    1329                 :             :             }
    1330                 :           0 :          break;
    1331                 :             : 
    1332                 :           0 :       default: // unknown, just copy code
    1333                 :           0 :          s = num + STBSP__NUMSZ - 1;
    1334                 :           0 :          *s = f[0];
    1335                 :           0 :          l = 1;
    1336                 :           0 :          fw = fl = 0;
    1337                 :           0 :          lead[0] = 0;
    1338                 :           0 :          tail[0] = 0;
    1339                 :           0 :          pr = 0;
    1340                 :           0 :          dp = 0;
    1341                 :           0 :          cs = 0;
    1342                 :           0 :          goto scopy;
    1343                 :             :       }
    1344                 :           0 :       ++f;
    1345                 :             :    }
    1346                 :           0 : endfmt:
    1347                 :             : 
    1348         [ #  # ]:           0 :    if (!callback)
    1349                 :           0 :       *bf = 0;
    1350                 :             :    else
    1351   [ #  #  #  # ]:           0 :       stbsp__flush_cb();
    1352                 :             : 
    1353                 :           0 : done:
    1354                 :           0 :    return tlen + (int)(bf - buf);
    1355                 :             : }
    1356                 :             : 
    1357                 :             : // cleanup
    1358                 :             : #undef STBSP__LEFTJUST
    1359                 :             : #undef STBSP__LEADINGPLUS
    1360                 :             : #undef STBSP__LEADINGSPACE
    1361                 :             : #undef STBSP__LEADING_0X
    1362                 :             : #undef STBSP__LEADINGZERO
    1363                 :             : #undef STBSP__INTMAX
    1364                 :             : #undef STBSP__TRIPLET_COMMA
    1365                 :             : #undef STBSP__NEGATIVE
    1366                 :             : #undef STBSP__METRIC_SUFFIX
    1367                 :             : #undef STBSP__NUMSZ
    1368                 :             : #undef stbsp__chk_cb_bufL
    1369                 :             : #undef stbsp__chk_cb_buf
    1370                 :             : #undef stbsp__flush_cb
    1371                 :             : #undef stbsp__cb_buf_clamp
    1372                 :             : 
    1373                 :             : // ============================================================================
    1374                 :             : //   wrapper functions
    1375                 :             : 
    1376                 :           0 : STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...)
    1377                 :             : {
    1378                 :             :    int result;
    1379                 :             :    va_list va;
    1380                 :           0 :    va_start(va, fmt);
    1381                 :           0 :    result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
    1382                 :           0 :    va_end(va);
    1383                 :           0 :    return result;
    1384                 :             : }
    1385                 :             : 
    1386                 :             : typedef struct stbsp__context {
    1387                 :             :    char *buf;
    1388                 :             :    int count;
    1389                 :             :    int length;
    1390                 :             :    char tmp[STB_SPRINTF_MIN];
    1391                 :             : } stbsp__context;
    1392                 :             : 
    1393                 :           0 : static char *stbsp__clamp_callback(const char *buf, void *user, int len)
    1394                 :             : {
    1395                 :           0 :    stbsp__context *c = (stbsp__context *)user;
    1396                 :           0 :    c->length += len;
    1397                 :             : 
    1398         [ #  # ]:           0 :    if (len > c->count)
    1399                 :           0 :       len = c->count;
    1400                 :             : 
    1401         [ #  # ]:           0 :    if (len) {
    1402         [ #  # ]:           0 :       if (buf != c->buf) {
    1403                 :             :          const char *s, *se;
    1404                 :             :          char *d;
    1405                 :           0 :          d = c->buf;
    1406                 :           0 :          s = buf;
    1407                 :           0 :          se = buf + len;
    1408                 :             :          do {
    1409                 :           0 :             *d++ = *s++;
    1410         [ #  # ]:           0 :          } while (s < se);
    1411                 :             :       }
    1412                 :           0 :       c->buf += len;
    1413                 :           0 :       c->count -= len;
    1414                 :             :    }
    1415                 :             : 
    1416         [ #  # ]:           0 :    if (c->count <= 0)
    1417                 :           0 :       return c->tmp;
    1418         [ #  # ]:           0 :    return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can
    1419                 :             : }
    1420                 :             : 
    1421                 :           0 : static char * stbsp__count_clamp_callback( const char * buf, void * user, int len )
    1422                 :             : {
    1423                 :           0 :    stbsp__context * c = (stbsp__context*)user;
    1424                 :             :    (void) sizeof(buf);
    1425                 :             : 
    1426                 :           0 :    c->length += len;
    1427                 :           0 :    return c->tmp; // go direct into buffer if you can
    1428                 :             : }
    1429                 :             : 
    1430                 :           0 : STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va )
    1431                 :             : {
    1432                 :             :    stbsp__context c;
    1433                 :             : 
    1434   [ #  #  #  # ]:           0 :    if ( (count == 0) && !buf )
    1435                 :             :    {
    1436                 :           0 :       c.length = 0;
    1437                 :             : 
    1438                 :           0 :       STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va );
    1439                 :             :    }
    1440                 :             :    else
    1441                 :             :    {
    1442                 :             :       int l;
    1443                 :             : 
    1444                 :           0 :       c.buf = buf;
    1445                 :           0 :       c.count = count;
    1446                 :           0 :       c.length = 0;
    1447                 :             : 
    1448                 :           0 :       STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va );
    1449                 :             : 
    1450                 :             :       // zero-terminate
    1451                 :           0 :       l = (int)( c.buf - buf );
    1452         [ #  # ]:           0 :       if ( l >= count ) // should never be greater, only equal (or less) than count
    1453                 :           0 :          l = count - 1;
    1454                 :           0 :       buf[l] = 0;
    1455                 :             :    }
    1456                 :             : 
    1457                 :           0 :    return c.length;
    1458                 :             : }
    1459                 :             : 
    1460                 :           0 : STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...)
    1461                 :             : {
    1462                 :             :    int result;
    1463                 :             :    va_list va;
    1464                 :           0 :    va_start(va, fmt);
    1465                 :             : 
    1466                 :           0 :    result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va);
    1467                 :           0 :    va_end(va);
    1468                 :             : 
    1469                 :           0 :    return result;
    1470                 :             : }
    1471                 :             : 
    1472                 :           0 : STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va)
    1473                 :             : {
    1474                 :           0 :    return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
    1475                 :             : }
    1476                 :             : 
    1477                 :             : // =======================================================================
    1478                 :             : //   low level float utility functions
    1479                 :             : 
    1480                 :             : #ifndef STB_SPRINTF_NOFLOAT
    1481                 :             : 
    1482                 :             : // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox)
    1483                 :             : #define STBSP__COPYFP(dest, src)                   \
    1484                 :             :    {                                               \
    1485                 :             :       int cn;                                      \
    1486                 :             :       for (cn = 0; cn < 8; cn++)                   \
    1487                 :             :          ((char *)&dest)[cn] = ((char *)&src)[cn]; \
    1488                 :             :    }
    1489                 :             : 
    1490                 :             : // get float info
    1491                 :           0 : static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value)
    1492                 :             : {
    1493                 :             :    double d;
    1494                 :           0 :    stbsp__int64 b = 0;
    1495                 :             : 
    1496                 :             :    // load value and round at the frac_digits
    1497                 :           0 :    d = value;
    1498                 :             : 
    1499         [ #  # ]:           0 :    STBSP__COPYFP(b, d);
    1500                 :             : 
    1501                 :           0 :    *bits = b & ((((stbsp__uint64)1) << 52) - 1);
    1502                 :           0 :    *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023);
    1503                 :             : 
    1504                 :           0 :    return (stbsp__int32)((stbsp__uint64) b >> 63);
    1505                 :             : }
    1506                 :             : 
    1507                 :             : static double const stbsp__bot[23] = {
    1508                 :             :    1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011,
    1509                 :             :    1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022
    1510                 :             : };
    1511                 :             : static double const stbsp__negbot[22] = {
    1512                 :             :    1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011,
    1513                 :             :    1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022
    1514                 :             : };
    1515                 :             : static double const stbsp__negboterr[22] = {
    1516                 :             :    -5.551115123125783e-018,  -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023,
    1517                 :             :    4.5251888174113739e-024,  -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028,  2.0113352370744385e-029,
    1518                 :             :    -3.0373745563400371e-030, 1.1806906454401013e-032,  -7.7705399876661076e-032, 2.0902213275965398e-033,  -7.1542424054621921e-034, -7.1542424054621926e-035,
    1519                 :             :    2.4754073164739869e-036,  5.4846728545790429e-037,  9.2462547772103625e-038,  -4.8596774326570872e-039
    1520                 :             : };
    1521                 :             : static double const stbsp__top[13] = {
    1522                 :             :    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
    1523                 :             : };
    1524                 :             : static double const stbsp__negtop[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__toperr[13] = {
    1528                 :             :    8388608,
    1529                 :             :    6.8601809640529717e+028,
    1530                 :             :    -7.253143638152921e+052,
    1531                 :             :    -4.3377296974619174e+075,
    1532                 :             :    -1.5559416129466825e+098,
    1533                 :             :    -3.2841562489204913e+121,
    1534                 :             :    -3.7745893248228135e+144,
    1535                 :             :    -1.7356668416969134e+167,
    1536                 :             :    -3.8893577551088374e+190,
    1537                 :             :    -9.9566444326005119e+213,
    1538                 :             :    6.3641293062232429e+236,
    1539                 :             :    -5.2069140800249813e+259,
    1540                 :             :    -5.2504760255204387e+282
    1541                 :             : };
    1542                 :             : static double const stbsp__negtoperr[13] = {
    1543                 :             :    3.9565301985100693e-040,  -2.299904345391321e-063,  3.6506201437945798e-086,  1.1875228833981544e-109,
    1544                 :             :    -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178,  -5.7778912386589953e-201,
    1545                 :             :    7.4997100559334532e-224,  -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293,
    1546                 :             :    8.0970921678014997e-317
    1547                 :             : };
    1548                 :             : 
    1549                 :             : #if defined(_MSC_VER) && (_MSC_VER <= 1200)
    1550                 :             : static stbsp__uint64 const stbsp__powten[20] = {
    1551                 :             :    1,
    1552                 :             :    10,
    1553                 :             :    100,
    1554                 :             :    1000,
    1555                 :             :    10000,
    1556                 :             :    100000,
    1557                 :             :    1000000,
    1558                 :             :    10000000,
    1559                 :             :    100000000,
    1560                 :             :    1000000000,
    1561                 :             :    10000000000,
    1562                 :             :    100000000000,
    1563                 :             :    1000000000000,
    1564                 :             :    10000000000000,
    1565                 :             :    100000000000000,
    1566                 :             :    1000000000000000,
    1567                 :             :    10000000000000000,
    1568                 :             :    100000000000000000,
    1569                 :             :    1000000000000000000,
    1570                 :             :    10000000000000000000U
    1571                 :             : };
    1572                 :             : #define stbsp__tento19th ((stbsp__uint64)1000000000000000000)
    1573                 :             : #else
    1574                 :             : static stbsp__uint64 const stbsp__powten[20] = {
    1575                 :             :    1,
    1576                 :             :    10,
    1577                 :             :    100,
    1578                 :             :    1000,
    1579                 :             :    10000,
    1580                 :             :    100000,
    1581                 :             :    1000000,
    1582                 :             :    10000000,
    1583                 :             :    100000000,
    1584                 :             :    1000000000,
    1585                 :             :    10000000000ULL,
    1586                 :             :    100000000000ULL,
    1587                 :             :    1000000000000ULL,
    1588                 :             :    10000000000000ULL,
    1589                 :             :    100000000000000ULL,
    1590                 :             :    1000000000000000ULL,
    1591                 :             :    10000000000000000ULL,
    1592                 :             :    100000000000000000ULL,
    1593                 :             :    1000000000000000000ULL,
    1594                 :             :    10000000000000000000ULL
    1595                 :             : };
    1596                 :             : #define stbsp__tento19th (1000000000000000000ULL)
    1597                 :             : #endif
    1598                 :             : 
    1599                 :             : #define stbsp__ddmulthi(oh, ol, xh, yh)                            \
    1600                 :             :    {                                                               \
    1601                 :             :       double ahi = 0, alo, bhi = 0, blo;                           \
    1602                 :             :       stbsp__int64 bt;                                             \
    1603                 :             :       oh = xh * yh;                                                \
    1604                 :             :       STBSP__COPYFP(bt, xh);                                       \
    1605                 :             :       bt &= ((~(stbsp__uint64)0) << 27);                           \
    1606                 :             :       STBSP__COPYFP(ahi, bt);                                      \
    1607                 :             :       alo = xh - ahi;                                              \
    1608                 :             :       STBSP__COPYFP(bt, yh);                                       \
    1609                 :             :       bt &= ((~(stbsp__uint64)0) << 27);                           \
    1610                 :             :       STBSP__COPYFP(bhi, bt);                                      \
    1611                 :             :       blo = yh - bhi;                                              \
    1612                 :             :       ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \
    1613                 :             :    }
    1614                 :             : 
    1615                 :             : #define stbsp__ddtoS64(ob, xh, xl)          \
    1616                 :             :    {                                        \
    1617                 :             :       double ahi = 0, alo, vh, t;           \
    1618                 :             :       ob = (stbsp__int64)xh;                \
    1619                 :             :       vh = (double)ob;                      \
    1620                 :             :       ahi = (xh - vh);                      \
    1621                 :             :       t = (ahi - xh);                       \
    1622                 :             :       alo = (xh - (ahi - t)) - (vh + t);    \
    1623                 :             :       ob += (stbsp__int64)(ahi + alo + xl); \
    1624                 :             :    }
    1625                 :             : 
    1626                 :             : #define stbsp__ddrenorm(oh, ol) \
    1627                 :             :    {                            \
    1628                 :             :       double s;                 \
    1629                 :             :       s = oh + ol;              \
    1630                 :             :       ol = ol - (s - oh);       \
    1631                 :             :       oh = s;                   \
    1632                 :             :    }
    1633                 :             : 
    1634                 :             : #define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh);
    1635                 :             : 
    1636                 :             : #define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl);
    1637                 :             : 
    1638                 :           0 : static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350
    1639                 :             : {
    1640                 :             :    double ph, pl;
    1641   [ #  #  #  # ]:           0 :    if ((power >= 0) && (power <= 22)) {
    1642   [ #  #  #  #  :           0 :       stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]);
             #  #  #  # ]
    1643                 :             :    } else {
    1644                 :             :       stbsp__int32 e, et, eb;
    1645                 :             :       double p2h, p2l;
    1646                 :             : 
    1647                 :           0 :       e = power;
    1648         [ #  # ]:           0 :       if (power < 0)
    1649                 :           0 :          e = -e;
    1650                 :           0 :       et = (e * 0x2c9) >> 14; /* %23 */
    1651         [ #  # ]:           0 :       if (et > 13)
    1652                 :           0 :          et = 13;
    1653                 :           0 :       eb = e - (et * 23);
    1654                 :             : 
    1655                 :           0 :       ph = d;
    1656                 :           0 :       pl = 0.0;
    1657         [ #  # ]:           0 :       if (power < 0) {
    1658         [ #  # ]:           0 :          if (eb) {
    1659                 :           0 :             --eb;
    1660   [ #  #  #  #  :           0 :             stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]);
             #  #  #  # ]
    1661                 :           0 :             stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]);
    1662                 :             :          }
    1663         [ #  # ]:           0 :          if (et) {
    1664                 :           0 :             stbsp__ddrenorm(ph, pl);
    1665                 :           0 :             --et;
    1666   [ #  #  #  #  :           0 :             stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]);
             #  #  #  # ]
    1667                 :           0 :             stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]);
    1668                 :           0 :             ph = p2h;
    1669                 :           0 :             pl = p2l;
    1670                 :             :          }
    1671                 :             :       } else {
    1672         [ #  # ]:           0 :          if (eb) {
    1673                 :           0 :             e = eb;
    1674         [ #  # ]:           0 :             if (eb > 22)
    1675                 :           0 :                eb = 22;
    1676                 :           0 :             e -= eb;
    1677   [ #  #  #  #  :           0 :             stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]);
             #  #  #  # ]
    1678         [ #  # ]:           0 :             if (e) {
    1679                 :           0 :                stbsp__ddrenorm(ph, pl);
    1680   [ #  #  #  #  :           0 :                stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]);
             #  #  #  # ]
    1681                 :           0 :                stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl);
    1682                 :           0 :                ph = p2h;
    1683                 :           0 :                pl = p2l;
    1684                 :             :             }
    1685                 :             :          }
    1686         [ #  # ]:           0 :          if (et) {
    1687                 :           0 :             stbsp__ddrenorm(ph, pl);
    1688                 :           0 :             --et;
    1689   [ #  #  #  #  :           0 :             stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]);
             #  #  #  # ]
    1690                 :           0 :             stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]);
    1691                 :           0 :             ph = p2h;
    1692                 :           0 :             pl = p2l;
    1693                 :             :          }
    1694                 :             :       }
    1695                 :             :    }
    1696                 :           0 :    stbsp__ddrenorm(ph, pl);
    1697                 :           0 :    *ohi = ph;
    1698                 :           0 :    *olo = pl;
    1699                 :           0 : }
    1700                 :             : 
    1701                 :             : // given a float value, returns the significant bits in bits, and the position of the
    1702                 :             : //   decimal point in decimal_pos.  +/-INF and NAN are specified by special values
    1703                 :             : //   returned in the decimal_pos parameter.
    1704                 :             : // frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000
    1705                 :           0 : 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)
    1706                 :             : {
    1707                 :             :    double d;
    1708                 :           0 :    stbsp__int64 bits = 0;
    1709                 :             :    stbsp__int32 expo, e, ng, tens;
    1710                 :             : 
    1711                 :           0 :    d = value;
    1712         [ #  # ]:           0 :    STBSP__COPYFP(bits, d);
    1713                 :           0 :    expo = (stbsp__int32)((bits >> 52) & 2047);
    1714                 :           0 :    ng = (stbsp__int32)((stbsp__uint64) bits >> 63);
    1715         [ #  # ]:           0 :    if (ng)
    1716                 :           0 :       d = -d;
    1717                 :             : 
    1718         [ #  # ]:           0 :    if (expo == 2047) // is nan or inf?
    1719                 :             :    {
    1720         [ #  # ]:           0 :       *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf";
    1721                 :           0 :       *decimal_pos = STBSP__SPECIAL;
    1722                 :           0 :       *len = 3;
    1723                 :           0 :       return ng;
    1724                 :             :    }
    1725                 :             : 
    1726         [ #  # ]:           0 :    if (expo == 0) // is zero or denormal
    1727                 :             :    {
    1728         [ #  # ]:           0 :       if (((stbsp__uint64) bits << 1) == 0) // do zero
    1729                 :             :       {
    1730                 :           0 :          *decimal_pos = 1;
    1731                 :           0 :          *start = out;
    1732                 :           0 :          out[0] = '0';
    1733                 :           0 :          *len = 1;
    1734                 :           0 :          return ng;
    1735                 :             :       }
    1736                 :             :       // find the right expo for denormals
    1737                 :             :       {
    1738                 :           0 :          stbsp__int64 v = ((stbsp__uint64)1) << 51;
    1739         [ #  # ]:           0 :          while ((bits & v) == 0) {
    1740                 :           0 :             --expo;
    1741                 :           0 :             v >>= 1;
    1742                 :             :          }
    1743                 :             :       }
    1744                 :             :    }
    1745                 :             : 
    1746                 :             :    // find the decimal exponent as well as the decimal bits of the value
    1747                 :             :    {
    1748                 :             :       double ph, pl;
    1749                 :             : 
    1750                 :             :       // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046
    1751                 :           0 :       tens = expo - 1023;
    1752         [ #  # ]:           0 :       tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1);
    1753                 :             : 
    1754                 :             :       // move the significant bits into position and stick them into an int
    1755                 :           0 :       stbsp__raise_to_power10(&ph, &pl, d, 18 - tens);
    1756                 :             : 
    1757                 :             :       // get full as much precision from double-double as possible
    1758                 :           0 :       stbsp__ddtoS64(bits, ph, pl);
    1759                 :             : 
    1760                 :             :       // check if we undershot
    1761         [ #  # ]:           0 :       if (((stbsp__uint64)bits) >= stbsp__tento19th)
    1762                 :           0 :          ++tens;
    1763                 :             :    }
    1764                 :             : 
    1765                 :             :    // now do the rounding in integer land
    1766         [ #  # ]:           0 :    frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits);
    1767         [ #  # ]:           0 :    if ((frac_digits < 24)) {
    1768                 :           0 :       stbsp__uint32 dg = 1;
    1769         [ #  # ]:           0 :       if ((stbsp__uint64)bits >= stbsp__powten[9])
    1770                 :           0 :          dg = 10;
    1771         [ #  # ]:           0 :       while ((stbsp__uint64)bits >= stbsp__powten[dg]) {
    1772                 :           0 :          ++dg;
    1773         [ #  # ]:           0 :          if (dg == 20)
    1774                 :           0 :             goto noround;
    1775                 :             :       }
    1776         [ #  # ]:           0 :       if (frac_digits < dg) {
    1777                 :             :          stbsp__uint64 r;
    1778                 :             :          // add 0.5 at the right position and round
    1779                 :           0 :          e = dg - frac_digits;
    1780         [ #  # ]:           0 :          if ((stbsp__uint32)e >= 24)
    1781                 :           0 :             goto noround;
    1782                 :           0 :          r = stbsp__powten[e];
    1783                 :           0 :          bits = bits + (r / 2);
    1784         [ #  # ]:           0 :          if ((stbsp__uint64)bits >= stbsp__powten[dg])
    1785                 :           0 :             ++tens;
    1786                 :           0 :          bits /= r;
    1787                 :             :       }
    1788                 :           0 :    noround:;
    1789                 :             :    }
    1790                 :             : 
    1791                 :             :    // kill long trailing runs of zeros
    1792         [ #  # ]:           0 :    if (bits) {
    1793                 :             :       stbsp__uint32 n;
    1794                 :             :       for (;;) {
    1795         [ #  # ]:           0 :          if (bits <= 0xffffffff)
    1796                 :           0 :             break;
    1797         [ #  # ]:           0 :          if (bits % 1000)
    1798                 :           0 :             goto donez;
    1799                 :           0 :          bits /= 1000;
    1800                 :             :       }
    1801                 :           0 :       n = (stbsp__uint32)bits;
    1802         [ #  # ]:           0 :       while ((n % 1000) == 0)
    1803                 :           0 :          n /= 1000;
    1804                 :           0 :       bits = n;
    1805                 :           0 :    donez:;
    1806                 :             :    }
    1807                 :             : 
    1808                 :             :    // convert to string
    1809                 :           0 :    out += 64;
    1810                 :           0 :    e = 0;
    1811                 :           0 :    for (;;) {
    1812                 :             :       stbsp__uint32 n;
    1813                 :           0 :       char *o = out - 8;
    1814                 :             :       // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned)
    1815         [ #  # ]:           0 :       if (bits >= 100000000) {
    1816                 :           0 :          n = (stbsp__uint32)(bits % 100000000);
    1817                 :           0 :          bits /= 100000000;
    1818                 :             :       } else {
    1819                 :           0 :          n = (stbsp__uint32)bits;
    1820                 :           0 :          bits = 0;
    1821                 :             :       }
    1822         [ #  # ]:           0 :       while (n) {
    1823                 :           0 :          out -= 2;
    1824                 :           0 :          *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
    1825                 :           0 :          n /= 100;
    1826                 :           0 :          e += 2;
    1827                 :             :       }
    1828         [ #  # ]:           0 :       if (bits == 0) {
    1829   [ #  #  #  # ]:           0 :          if ((e) && (out[0] == '0')) {
    1830                 :           0 :             ++out;
    1831                 :           0 :             --e;
    1832                 :             :          }
    1833                 :           0 :          break;
    1834                 :             :       }
    1835         [ #  # ]:           0 :       while (out != o) {
    1836                 :           0 :          *--out = '0';
    1837                 :           0 :          ++e;
    1838                 :             :       }
    1839                 :             :    }
    1840                 :             : 
    1841                 :           0 :    *decimal_pos = tens;
    1842                 :           0 :    *start = out;
    1843                 :           0 :    *len = e;
    1844                 :           0 :    return ng;
    1845                 :             : }
    1846                 :             : 
    1847                 :             : #undef stbsp__ddmulthi
    1848                 :             : #undef stbsp__ddrenorm
    1849                 :             : #undef stbsp__ddmultlo
    1850                 :             : #undef stbsp__ddmultlos
    1851                 :             : #undef STBSP__SPECIAL
    1852                 :             : #undef STBSP__COPYFP
    1853                 :             : 
    1854                 :             : #endif // STB_SPRINTF_NOFLOAT
    1855                 :             : 
    1856                 :             : // clean up
    1857                 :             : #undef stbsp__uint16
    1858                 :             : #undef stbsp__uint32
    1859                 :             : #undef stbsp__int32
    1860                 :             : #undef stbsp__uint64
    1861                 :             : #undef stbsp__int64
    1862                 :             : #undef STBSP__UNALIGNED
    1863                 :             : 
    1864                 :             : #endif // STB_SPRINTF_IMPLEMENTATION
    1865                 :             : 
    1866                 :             : /*
    1867                 :             : ------------------------------------------------------------------------------
    1868                 :             : This software is available under 2 licenses -- choose whichever you prefer.
    1869                 :             : ------------------------------------------------------------------------------
    1870                 :             : ALTERNATIVE A - MIT License
    1871                 :             : Copyright (c) 2017 Sean Barrett
    1872                 :             : Permission is hereby granted, free of charge, to any person obtaining a copy of
    1873                 :             : this software and associated documentation files (the "Software"), to deal in
    1874                 :             : the Software without restriction, including without limitation the rights to
    1875                 :             : use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
    1876                 :             : of the Software, and to permit persons to whom the Software is furnished to do
    1877                 :             : so, subject to the following conditions:
    1878                 :             : The above copyright notice and this permission notice shall be included in all
    1879                 :             : copies or substantial portions of the Software.
    1880                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1881                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1882                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    1883                 :             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    1884                 :             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    1885                 :             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    1886                 :             : SOFTWARE.
    1887                 :             : ------------------------------------------------------------------------------
    1888                 :             : ALTERNATIVE B - Public Domain (www.unlicense.org)
    1889                 :             : This is free and unencumbered software released into the public domain.
    1890                 :             : Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
    1891                 :             : software, either in source code form or as a compiled binary, for any purpose,
    1892                 :             : commercial or non-commercial, and by any means.
    1893                 :             : In jurisdictions that recognize copyright laws, the author or authors of this
    1894                 :             : software dedicate any and all copyright interest in the software to the public
    1895                 :             : domain. We make this dedication for the benefit of the public at large and to
    1896                 :             : the detriment of our heirs and successors. We intend this dedication to be an
    1897                 :             : overt act of relinquishment in perpetuity of all present and future rights to
    1898                 :             : this software under copyright law.
    1899                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1900                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1901                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    1902                 :             : AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
    1903                 :             : ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    1904                 :             : WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    1905                 :             : ------------------------------------------------------------------------------
    1906                 :             : */
        

Generated by: LCOV version 2.0-1