From a27e577c3eb38a2f40d4c55f37c8a58d6a750397 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 14:56:35 +0200 Subject: [PATCH 1/6] The Si prefixes for mega, giga and tera are upper case (lower case m is not mega but milli) --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 23de7e4..0be456e 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -555,7 +555,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb pr = 0; // handle k,m,g,t - if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; + if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kMGT"[fl>>24]; tail[0]=2; } } }; flt_lead: // get the length that we copied From 9a3f9dff13cc07752cfa95b7fcce0a50004f9c30 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 15:08:54 +0200 Subject: [PATCH 2/6] More proper fix for the prefixes (defaults to Ki style, with define for using K style instead) --- stb_sprintf.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 0be456e..c4d9573 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -133,6 +133,9 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #include // for va_list() +// Uncomment for old-school prefixes (KB, MB instead of KiB, MiB) with the $ format +//#define STBSP__JEDEC_PREFIX + #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif @@ -555,7 +558,23 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb pr = 0; // handle k,m,g,t - if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kMGT"[fl>>24]; tail[0]=2; } } }; + if (fl&STBSP__METRIC_SUFFIX) + { + tail[0]=1; + tail[1]=' '; + { + if (fl>>24) + { + tail[2]="_KMGT"[fl>>24]; +#ifdef STBSP__JEDEC_PREFIX + tail[0]=2; +#else // SI prefix + tail[3]='i'; + tail[0]=3; +#endif + } + } + }; flt_lead: // get the length that we copied From 0e63382be0f569f080698174a25d59f40a4d69f3 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 17:23:01 +0200 Subject: [PATCH 3/6] A bit more involved change: support for both 1000 and 1024 divisors, and SI and JEDEC suffixes, as well as removing the space between number and suffix. --- stb_sprintf.h | 70 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index c4d9573..3842a03 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -91,8 +91,11 @@ would print 12,345. For integers and floats, you can use a "$" specifier and the number will be converted to float and then divided to get kilo, mega, giga or -tera and then printed, so "%$d" 1024 is "1.0 k", "%$.2d" 2536000 is -"2.42 m", etc. +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". In addition to octal and hexadecimal conversions, you can print integers in binary: "%b" for 256 would print 100. @@ -133,9 +136,6 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #include // for va_list() -// Uncomment for old-school prefixes (KB, MB instead of KiB, MiB) with the $ format -//#define STBSP__JEDEC_PREFIX - #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif @@ -232,6 +232,9 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb #define STBSP__NEGATIVE 128 #define STBSP__METRIC_SUFFIX 256 #define STBSP__HALFWIDTH 512 + #define STBSP__METRIC_NOSPACE 1024 + #define STBSP__METRIC_1024 2048 + #define STBSP__METRIC_JEDEC 4096 // macros for the callback buffer stuff #define stbsp__chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=STB_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } @@ -279,8 +282,26 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb case '#': fl|=STBSP__LEADING_0X; ++f; continue; // if we have thousand commas case '\'': fl|=STBSP__TRIPLET_COMMA; ++f; continue; - // if we have kilo marker - case '$': fl|=STBSP__METRIC_SUFFIX; ++f; continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl&STBSP__METRIC_SUFFIX) + { + if (fl&STBSP__METRIC_1024) + { + fl|=STBSP__METRIC_JEDEC; + } + else + { + fl|=STBSP__METRIC_1024; + } + } + else + { + fl|=STBSP__METRIC_SUFFIX; + } + ++f; continue; + // if we don't want space between metric suffix and number + case '_': fl|=STBSP__METRIC_NOSPACE; ++f; continue; // if we have leading zero case '0': fl|=STBSP__LEADINGZERO; ++f; goto flags_done; default: goto flags_done; @@ -505,7 +526,13 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fv = va_arg(va,double); doafloat: // do kilos - if (fl&STBSP__METRIC_SUFFIX) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} + if (fl&STBSP__METRIC_SUFFIX) + { + double divisor; + divisor=1000.0f; + if (fl&STBSP__METRIC_1024) divisor = 1024.0; + while(fl<0x4000000) { if ((fv-divisor)) break; fv/=divisor; fl+=0x1000000; } + } if (pr==-1) pr=6; // default is 6 // read the double into a string if ( stbsp__real_to_str( &sn, &l, num, &dp, fv, pr ) ) @@ -560,18 +587,27 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb // handle k,m,g,t if (fl&STBSP__METRIC_SUFFIX) { - tail[0]=1; + char idx; + idx=1; + if (fl&STBSP__METRIC_NOSPACE) + idx=0; + tail[0]=idx; tail[1]=' '; { if (fl>>24) - { - tail[2]="_KMGT"[fl>>24]; -#ifdef STBSP__JEDEC_PREFIX - tail[0]=2; -#else // SI prefix - tail[3]='i'; - tail[0]=3; -#endif + { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl&STBSP__METRIC_1024) + tail[idx+1]="_KMGT"[fl>>24]; + else + tail[idx+1]="_kMGT"[fl>>24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl&STBSP__METRIC_1024&&!(fl&STBSP__METRIC_JEDEC)) + { + tail[idx+1]='i'; + idx++; + } + tail[0]=idx; } } }; From 13927ac386d02815f139d29f12d60382a3c33b01 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Mon, 5 Dec 2016 18:18:20 -0600 Subject: [PATCH 4/6] stb_printf.h: Reuse code for assigning lead sign. --- stb_sprintf.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 7521f7e..1f79e87 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -235,6 +235,18 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb #define stbsp__chk_cb_buf(bytes) { if ( callback ) { stbsp__chk_cb_bufL(bytes); } } #define stbsp__flush_cb() { stbsp__chk_cb_bufL(STB_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer #define stbsp__cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = STB_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } + #define stbsp__lead_sign(fl, lead) \ + lead[0] = 0;\ + if (fl&STBSP__NEGATIVE) {\ + lead[0]=1;\ + lead[1]='-';\ + } else if (fl&STBSP__LEADINGSPACE) {\ + lead[0]=1;\ + lead[1]=' ';\ + } else if (fl&STBSP__LEADINGPLUS) {\ + lead[0]=1;\ + lead[1]='+';\ + } // fast copy everything up to the next % (or end of string) for(;;) @@ -396,8 +408,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb s = num+64; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((stbsp__uint64)1)<<52); n64<<=(64-56); @@ -471,7 +482,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fl |= STBSP__NEGATIVE; doexpfromg: tail[0]=0; - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; // handle leading chars @@ -509,8 +520,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fl |= STBSP__NEGATIVE; dofloatfromg: tail[0]=0; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; @@ -649,8 +659,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb } tail[0]=0; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); // get the length that we copied l = (stbsp__uint32) ( (num+STBSP__NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } From 324be64e8082384aca1f3ef305075bb647ae4cdf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:57:09 -0800 Subject: [PATCH 5/6] version number --- stb_sprintf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_sprintf.h b/stb_sprintf.h index 3283156..ad5d9bc 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -8,6 +8,7 @@ // Contributors (bugfixes): // github:d26435 // github:trex78 +// Jari Komppa (SI suffixes) // // LICENSE: // From c918a6b801e6d2c4720c5fc5fd54720a5cc1999f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:02:54 -0800 Subject: [PATCH 6/6] tweak previous PR merge --- stb_sprintf.h | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index e254e0f..0ed30a0 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -226,6 +226,35 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char pcomma, char stbsp__comma=pcomma; } +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl&STBSP__NEGATIVE) { + sign[0]=1; + sign[1]='-'; + } else if (fl&STBSP__LEADINGSPACE) { + sign[0]=1; + sign[1]=' '; + } else if (fl&STBSP__LEADINGPLUS) { + sign[0]=1; + sign[1]='+'; + } +} + STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) { static char hex[]="0123456789abcdefxp"; @@ -240,37 +269,11 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb { stbsp__int32 fw,pr,tz; stbsp__uint32 fl; - #define STBSP__LEFTJUST 1 - #define STBSP__LEADINGPLUS 2 - #define STBSP__LEADINGSPACE 4 - #define STBSP__LEADING_0X 8 - #define STBSP__LEADINGZERO 16 - #define STBSP__INTMAX 32 - #define STBSP__TRIPLET_COMMA 64 - #define STBSP__NEGATIVE 128 - #define STBSP__METRIC_SUFFIX 256 - #define STBSP__HALFWIDTH 512 - #define STBSP__METRIC_NOSPACE 1024 - #define STBSP__METRIC_1024 2048 - #define STBSP__METRIC_JEDEC 4096 - // macros for the callback buffer stuff #define stbsp__chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=STB_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } #define stbsp__chk_cb_buf(bytes) { if ( callback ) { stbsp__chk_cb_bufL(bytes); } } #define stbsp__flush_cb() { stbsp__chk_cb_bufL(STB_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer #define stbsp__cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = STB_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } - #define stbsp__lead_sign(fl, lead) \ - lead[0] = 0;\ - if (fl&STBSP__NEGATIVE) {\ - lead[0]=1;\ - lead[1]='-';\ - } else if (fl&STBSP__LEADINGSPACE) {\ - lead[0]=1;\ - lead[1]=' ';\ - } else if (fl&STBSP__LEADINGPLUS) {\ - lead[0]=1;\ - lead[1]='+';\ - } // fast copy everything up to the next % (or end of string) for(;;)