10 #define alloca _alloca
13 typedef __int64 LONGLONG
;
14 typedef unsigned __int64 ULONGLONG
;
17 unsigned int mantissa
:23;
18 unsigned int exponent
:8;
23 unsigned int mantissal
:32;
24 unsigned int mantissah
:20;
25 unsigned int exponent
:11;
30 unsigned int mantissal
:32;
31 unsigned int mantissah
:32;
32 unsigned int exponent
:15;
34 unsigned int empty
:16;
37 std::string
ssprintf ( const char* fmt
, ... )
41 std::string f
= ssvprintf ( fmt
, arg
);
46 #define ZEROPAD 1 /* pad with zero */
47 #define SIGN 2 /* unsigned/signed long */
48 #define PLUS 4 /* show plus */
49 #define SPACE 8 /* space if plus */
50 #define LEFT 16 /* left justified */
51 #define SPECIAL 32 /* 0x */
52 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
53 #define ZEROTRUNC 128 /* truncate zero 's */
56 static int skip_atoi(const char **s
)
61 i
= i
*10 + *((*s
)++) - '0';
66 static int do_div(LONGLONG
*n
,int base
)
68 int __res
= ((ULONGLONG
) *n
) % (unsigned) base
;
69 *n
= ((ULONGLONG
) *n
) / (unsigned) base
;
74 static bool number(std::string
& f
, LONGLONG num
, int base
, int size
, int precision
,int type
)
77 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
81 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
84 if (base
< 2 || base
> 36)
86 c
= (type
& ZEROPAD
) ? '0' : ' ';
93 } else if (type
& PLUS
) {
96 } else if (type
& SPACE
) {
101 if (type
& SPECIAL
) {
110 else while (num
!= 0)
111 tmp
[i
++] = digits
[do_div(&num
,base
)];
115 if (!(type
&(ZEROPAD
+LEFT
)))
135 while (i
< precision
--)
151 static bool numberf(std::string
& f
, double __n
, char exp_sign
, int size
, int precision
, int type
)
153 double exponent
= 0.0;
178 if ( exp_sign
== 'g' || exp_sign
== 'G' || exp_sign
== 'e' || exp_sign
== 'E' ) {
179 ie
= ((unsigned int)n
.n
->exponent
- (unsigned int)0x3ff);
180 exponent
= ie
/3.321928;
183 if ( exp_sign
== 'g' || exp_sign
== 'G' ) {
185 if ( exponent
< -4 || fabs(exponent
) >= precision
)
186 exp_sign
-= 2; // g -> e and G -> E
189 if ( exp_sign
== 'e' || exp_sign
== 'E' ) {
190 frac
= modf(exponent
,&e
);
193 else if ( frac
< -0.5 )
196 result
= numberf(f
,__n
/pow(10.0L,e
),'f',size
-4, precision
, type
);
206 result
= number(f
,ie
, 10,2, 2,type
);
212 if ( exp_sign
== 'f' ) {
213 buf
= (char*)alloca(4096);
218 c
= (type
& ZEROPAD
) ? '0' : ' ';
225 } else if (type
& PLUS
) {
228 } else if (type
& SPACE
) {
234 frac
= modf(__n
,&intr
);
236 // # flags forces a . and prevents trucation of trailing zero's
238 if ( precision
> 0 ) {
239 //frac = modfl(__n,&intr);
243 frac
= modf(frac
, &p
);
244 buf
[i
] = (int)p
+ '0';
255 if ( precision
>= 1 || type
& SPECIAL
) {
266 while ( intr
> 0.0 ) {
273 buf
[i
++] = (int)p
+ '0';
279 while ( j
< i
&& ro
== 1) {
280 if ( buf
[j
] >= '0' && buf
[j
] <= '8' ) {
284 else if ( buf
[j
] == '9' ) {
295 if (!(type
&(ZEROPAD
+LEFT
)))
305 if (!(type
&(ZEROPAD
+LEFT
)))
310 if (type
& SPECIAL
) {
320 if ( type
& ZEROTRUNC
&& ((type
& SPECIAL
) != SPECIAL
) )
323 while ( j
< i
&& ( *tmp
== '0' || *tmp
== '.' ))
330 // while (i < precision--)
345 static bool numberfl(std::string
& f
, long double __n
, char exp_sign
, int size
, int precision
, int type
)
347 long double exponent
= 0.0;
357 long double frac
, intr
;
368 ieee_long_double_t
* n
;
373 if ( exp_sign
== 'g' || exp_sign
== 'G' || exp_sign
== 'e' || exp_sign
== 'E' ) {
374 ie
= ((unsigned int)n
.n
->exponent
- (unsigned int)0x3fff);
375 exponent
= ie
/3.321928;
378 if ( exp_sign
== 'g' || exp_sign
== 'G' ) {
380 if ( exponent
< -4 || fabs(exponent
) >= precision
)
381 exp_sign
-= 2; // g -> e and G -> E
384 if ( exp_sign
== 'e' || exp_sign
== 'E' ) {
385 frac
= modfl(exponent
,&e
);
388 else if ( frac
< -0.5 )
391 result
= numberf(f
,__n
/powl(10.0L,e
),'f',size
-4, precision
, type
);
401 result
= number(f
,ie
, 10,2, 2,type
);
407 if ( exp_sign
== 'f' )
410 buf
= (char*)alloca(4096);
416 c
= (type
& ZEROPAD
) ? '0' : ' ';
425 } else if (type
& PLUS
)
429 } else if (type
& SPACE
)
436 frac
= modfl(__n
,&intr
);
438 // # flags forces a . and prevents trucation of trailing zero's
441 //frac = modfl(__n,&intr);
447 frac
= modfl((long double)frac
, &p
);
448 buf
[i
] = (int)p
+ '0';
460 if ( precision
>= 1 || type
& SPECIAL
)
482 buf
[i
++] = (int)p
+ '0';
488 while ( j
< i
&& ro
== 1) {
489 if ( buf
[j
] >= '0' && buf
[j
] <= '8' )
494 else if ( buf
[j
] == '9' )
506 if (!(type
&(ZEROPAD
+LEFT
)))
516 if (!(type
&(ZEROPAD
+LEFT
)))
521 if (type
& SPECIAL
) {
530 if ( type
& ZEROTRUNC
&& ((type
& SPECIAL
) != SPECIAL
) )
533 while ( j
< i
&& ( *tmp
== '0' || *tmp
== '.' ))
540 // while (i < precision--)
554 static int stringa(std::string
& f
, const char* s
, int len
, int field_width
, int precision
, int flags
)
567 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
572 if ((unsigned int)len
> (unsigned int)precision
)
577 while (len
< field_width
--)
582 for (i
= 0; i
< len
; ++i
)
587 while (len
< field_width
--)
595 static int stringw(std::string
& f
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
608 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
613 if ((unsigned int)len
> (unsigned int)precision
)
618 while (len
< field_width
--)
623 for (i
= 0; i
< len
; ++i
)
625 #define MY_MB_CUR_MAX 1
626 char mb
[MY_MB_CUR_MAX
];
628 mbcount
= wctomb(mb
, *sw
++);
633 for (j
= 0; j
< mbcount
; j
++)
639 while (len
< field_width
--)
647 #define _isnanl _isnan
648 #define _finitel _finite
650 std::string
ssvprintf ( const char *fmt
, va_list args
)
654 long double _ldouble
;
661 int flags
; /* flags to number() */
663 int field_width
; /* width of output field */
664 int precision
; /* min. # of digits for integers; max
665 number of chars for from string */
666 int qualifier
= 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
679 ++fmt
; /* this also skips first '%' */
681 case '-': flags
|= LEFT
; goto repeat
;
682 case '+': flags
|= PLUS
; goto repeat
;
683 case ' ': flags
|= SPACE
; goto repeat
;
684 case '#': flags
|= SPECIAL
; goto repeat
;
685 case '0': flags
|= ZEROPAD
; goto repeat
;
688 /* get field width */
691 field_width
= skip_atoi(&fmt
);
692 else if (*fmt
== '*') {
694 /* it's the next argument */
695 field_width
= va_arg(args
, int);
696 if (field_width
< 0) {
697 field_width
= -field_width
;
702 /* get the precision */
707 precision
= skip_atoi(&fmt
);
708 else if (*fmt
== '*') {
710 /* it's the next argument */
711 precision
= va_arg(args
, int);
717 /* get the conversion qualifier */
719 // %Z can be just stand alone or as size_t qualifier
735 } else if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
== 'w') {
738 } else if (*fmt
== 'I' && *(fmt
+1) == '6' && *(fmt
+2) == '4') {
743 // go fine with ll instead of L
755 while (--field_width
> 0)
759 if (qualifier
== 'l' || qualifier
== 'w')
761 f
+= (char)(unsigned char)(wchar_t) va_arg(args
,int);
765 f
+= (char)(unsigned char) va_arg(args
,int);
767 while (--field_width
> 0)
775 while (--field_width
> 0)
779 if (qualifier
== 'h')
781 f
+= (char)(unsigned char) va_arg(args
,int);
785 f
+= (char)(unsigned char)(wchar_t) va_arg(args
,int);
787 while (--field_width
> 0)
794 if (qualifier
== 'l' || qualifier
== 'w') {
795 /* print unicode string */
796 sw
= (const wchar_t*)va_arg(args
, wchar_t *);
797 result
= stringw(f
, sw
, -1, field_width
, precision
, flags
);
799 /* print ascii string */
800 s
= va_arg(args
, char *);
801 result
= stringa(f
, s
, -1, field_width
, precision
, flags
);
805 assert(!"TODO FIXME handle error better");
811 if (qualifier
== 'h') {
812 /* print ascii string */
813 s
= va_arg(args
, char *);
814 result
= stringa(f
, s
, -1, field_width
, precision
, flags
);
816 /* print unicode string */
817 sw
= (const wchar_t*)va_arg(args
, wchar_t *);
818 result
= stringw(f
, sw
, -1, field_width
, precision
, flags
);
822 assert(!"TODO FIXME handle error better");
828 if (qualifier == 'w') {
829 // print counted unicode string
830 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
831 if ((pus == NULL) || (pus->Buffer == NULL)) {
836 len = pus->Length / sizeof(WCHAR);
838 result = stringw(f, sw, len, field_width, precision, flags);
840 // print counted ascii string
841 PANSI_STRING pas = va_arg(args, PANSI_STRING);
842 if ((pas == NULL) || (pas->Buffer == NULL)) {
849 result = stringa(f, s, -1, field_width, precision, flags);
860 if (qualifier
== 'l' || qualifier
== 'L' ) {
861 _ldouble
= va_arg(args
, long double);
863 if ( _isnanl(_ldouble
) )
867 else if ( !_finitel(_ldouble
) )
874 if ( precision
== -1 )
876 result
= numberfl(f
,_ldouble
,*fmt
,field_width
,precision
,flags
);
879 assert(!"TODO FIXME handle error better");
884 _double
= (double)va_arg(args
, double);
886 if ( _isnan(_double
) )
890 else if ( !_finite(_double
) )
899 if ( precision
== -1 )
901 result
= numberf(f
,_double
,*fmt
,field_width
,precision
,flags
);
904 assert(!"TODO FIXME handle error better");
912 if (field_width
== -1) {
913 field_width
= 2*sizeof(void *);
917 (unsigned long) va_arg(args
, void *), 16,
918 field_width
, precision
, flags
);
921 assert(!"TODO FIXME handle error better");
927 if (qualifier
== 'l') {
928 long * ip
= va_arg(args
, long *);
931 int * ip
= va_arg(args
, int *);
936 /* integer number formats - set up the flags and "break" */
971 if (qualifier
== 'I')
972 num
= va_arg(args
, ULONGLONG
);
973 else if (qualifier
== 'l') {
975 num
= va_arg(args
, long);
977 num
= va_arg(args
, unsigned long);
979 else if (qualifier
== 'h') {
981 num
= va_arg(args
, int);
983 num
= va_arg(args
, unsigned int);
985 else if (flags
& SIGN
)
986 num
= va_arg(args
, int);
988 num
= va_arg(args
, unsigned int);
989 result
= number(f
, num
, base
, field_width
, precision
, flags
);
992 assert(!"TODO FIXME handle error better");