Tell others to leave our port alone
[reactos.git] / reactos / tools / buildno / ssprintf.cpp
1 // ssprintf.cpp
2
3 #include "pch.h"
4
5 #ifdef __FreeBSD__
6 # include <stdlib.h>
7 #else
8 # include <malloc.h>
9 #endif // __FreeBSD__
10 #include <math.h>
11 #include <float.h>
12 #include <assert.h>
13 #include "ssprintf.h"
14
15 #ifdef __FreeBSD__
16 # define __isnan isnan
17 # define __finite finite
18 # define powl __builtin_powl
19 # define modfl __builtin_modfl
20 #endif // _FreeBSD__
21
22 #ifdef _MSC_VER
23 #define alloca _alloca
24 #endif//_MSC_VER
25
26 #ifdef _MSC_VER
27 typedef __int64 LONGLONG;
28 typedef unsigned __int64 ULONGLONG;
29 #else
30 typedef long long LONGLONG;
31 typedef unsigned long long ULONGLONG;
32 #endif
33
34 typedef struct {
35 unsigned int mantissa:23;
36 unsigned int exponent:8;
37 unsigned int sign:1;
38 } ieee_float_t;
39
40 typedef struct {
41 unsigned int mantissal:32;
42 unsigned int mantissah:20;
43 unsigned int exponent:11;
44 unsigned int sign:1;
45 } ieee_double_t;
46
47 typedef struct {
48 unsigned int mantissal:32;
49 unsigned int mantissah:32;
50 unsigned int exponent:15;
51 unsigned int sign:1;
52 unsigned int empty:16;
53 } ieee_long_double_t;
54
55 std::string
56 ssprintf ( const char* fmt, ... )
57 {
58 va_list arg;
59 va_start(arg, fmt);
60 std::string f = ssvprintf ( fmt, arg );
61 va_end(arg);
62 return f;
63 }
64
65 std::wstring
66 sswprintf ( const wchar_t* fmt, ... )
67 {
68 va_list arg;
69 va_start(arg, fmt);
70 std::wstring f = sswvprintf ( fmt, arg );
71 va_end(arg);
72 return f;
73 }
74
75 #define ZEROPAD 1 /* pad with zero */
76 #define SIGN 2 /* unsigned/signed long */
77 #define PLUS 4 /* show plus */
78 #define SPACE 8 /* space if plus */
79 #define LEFT 16 /* left justified */
80 #define SPECIAL 32 /* 0x */
81 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
82 #define ZEROTRUNC 128 /* truncate zero 's */
83
84
85 static int
86 skip_atoi(const char **s)
87 {
88 int i=0;
89
90 while (isdigit(**s))
91 i = i*10 + *((*s)++) - '0';
92 return i;
93 }
94
95 static int
96 skip_wtoi(const wchar_t **s)
97 {
98 int i=0;
99
100 while (iswdigit(**s))
101 i = i*10 + *((*s)++) - L'0';
102 return i;
103 }
104
105
106 static int
107 do_div(LONGLONG *n,int base)
108 {
109 int __res = ((ULONGLONG) *n) % (unsigned) base;
110 *n = ((ULONGLONG) *n) / (unsigned) base;
111 return __res;
112 }
113
114
115 static bool
116 number(std::string& f, LONGLONG num, int base, int size, int precision ,int type)
117 {
118 char c,sign,tmp[66];
119 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
120 int i;
121
122 if (type & LARGE)
123 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
124 if (type & LEFT)
125 type &= ~ZEROPAD;
126 if (base < 2 || base > 36)
127 return 0;
128 c = (type & ZEROPAD) ? '0' : ' ';
129 sign = 0;
130 if (type & SIGN) {
131 if (num < 0) {
132 sign = '-';
133 num = -num;
134 size--;
135 } else if (type & PLUS) {
136 sign = '+';
137 size--;
138 } else if (type & SPACE) {
139 sign = ' ';
140 size--;
141 }
142 }
143 if (type & SPECIAL) {
144 if (base == 16)
145 size -= 2;
146 else if (base == 8)
147 size--;
148 }
149 i = 0;
150 if (num == 0)
151 tmp[i++]='0';
152 else while (num != 0)
153 tmp[i++] = digits[do_div(&num,base)];
154 if (i > precision)
155 precision = i;
156 size -= precision;
157 if (!(type&(ZEROPAD+LEFT)))
158 while(size-->0)
159 f += ' ';
160 if (sign)
161 f += sign;
162 if (type & SPECIAL)
163 {
164 if (base==8)
165 f += '0';
166 else if (base==16)
167 {
168 f += '0';
169 f += digits[33];
170 }
171 }
172 if (!(type & LEFT))
173 {
174 while (size-- > 0)
175 f += c;
176 }
177 while (i < precision--)
178 {
179 f += '0';
180 }
181 while (i-- > 0)
182 {
183 f += tmp[i];
184 }
185 while (size-- > 0)
186 {
187 f += ' ';
188 }
189 return true;
190 }
191
192 static bool
193 wnumber(std::wstring& f, LONGLONG num, int base, int size, int precision ,int type)
194 {
195 wchar_t c,sign,tmp[66];
196 const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz";
197 int i;
198
199 if (type & LARGE)
200 digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
201 if (type & LEFT)
202 type &= ~ZEROPAD;
203 if (base < 2 || base > 36)
204 return 0;
205 c = (type & ZEROPAD) ? L'0' : L' ';
206 sign = 0;
207 if (type & SIGN) {
208 if (num < 0) {
209 sign = L'-';
210 num = -num;
211 size--;
212 } else if (type & PLUS) {
213 sign = L'+';
214 size--;
215 } else if (type & SPACE) {
216 sign = L' ';
217
218 size--;
219 }
220 }
221 if (type & SPECIAL) {
222 if (base == 16)
223 size -= 2;
224 else if (base == 8)
225 size--;
226 }
227 i = 0;
228 if (num == 0)
229 tmp[i++]=L'0';
230 else while (num != 0)
231 tmp[i++] = digits[do_div(&num,base)];
232 if (i > precision)
233 precision = i;
234 size -= precision;
235 if (!(type&(ZEROPAD+LEFT)))
236 while(size-->0)
237 f += L' ';
238 if (sign)
239 f += sign;
240 if (type & SPECIAL)
241 {
242 if (base==8)
243 f += L'0';
244 else if (base==16)
245 {
246 f += L'0';
247 f += digits[33];
248 }
249 }
250 if (!(type & LEFT))
251 {
252 while (size-- > 0)
253 f += c;
254 }
255 while (i < precision--)
256 {
257 f += L'0';
258 }
259 while (i-- > 0)
260 {
261 f += tmp[i];
262 }
263 while (size-- > 0)
264 {
265 f += L' ';
266 }
267 return true;
268 }
269
270
271 static bool
272 numberf(std::string& f, double __n, char exp_sign, int size, int precision, int type)
273 {
274 double exponent = 0.0;
275 double e;
276 long ie;
277
278 //int x;
279 char *buf, *tmp;
280 int i = 0;
281 int j = 0;
282 //int k = 0;
283
284 double frac, intr;
285 double p;
286 char sign;
287 char c;
288 char ro = 0;
289 int result;
290
291 union
292 {
293 double* __n;
294 ieee_double_t* n;
295 } n;
296
297 n.__n = &__n;
298
299 if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
300 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff);
301 exponent = ie/3.321928;
302 }
303
304 if ( exp_sign == 'g' || exp_sign == 'G' ) {
305 type |= ZEROTRUNC;
306 if ( exponent < -4 || fabs(exponent) >= precision )
307 exp_sign -= 2; // g -> e and G -> E
308 }
309
310 if ( exp_sign == 'e' || exp_sign == 'E' ) {
311 frac = modf(exponent,&e);
312 if ( frac > 0.5 )
313 e++;
314 else if ( frac < -0.5 )
315 e--;
316
317 result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type);
318 if (result < 0)
319 return false;
320 f += exp_sign;
321 size--;
322 ie = (long)e;
323 type = LEFT | PLUS;
324 if ( ie < 0 )
325 type |= SIGN;
326
327 result = number(f,ie, 10,2, 2,type );
328 if (result < 0)
329 return false;
330 return true;
331 }
332
333 if ( exp_sign == 'f' ) {
334 buf = (char*)alloca(4096);
335 if (type & LEFT) {
336 type &= ~ZEROPAD;
337 }
338
339 c = (type & ZEROPAD) ? '0' : ' ';
340 sign = 0;
341 if (type & SIGN) {
342 if (__n < 0) {
343 sign = '-';
344 __n = fabs(__n);
345 size--;
346 } else if (type & PLUS) {
347 sign = '+';
348 size--;
349 } else if (type & SPACE) {
350 sign = ' ';
351 size--;
352 }
353 }
354
355 frac = modf(__n,&intr);
356
357 // # flags forces a . and prevents trucation of trailing zero's
358
359 if ( precision > 0 ) {
360 //frac = modfl(__n,&intr);
361 i = precision-1;
362 while ( i >= 0 ) {
363 frac*=10.0L;
364 frac = modf(frac, &p);
365 buf[i] = (int)p + '0';
366 i--;
367 }
368 i = precision;
369 size -= precision;
370
371 ro = 0;
372 if ( frac > 0.5 ) {
373 ro = 1;
374 }
375
376 if ( precision >= 1 || type & SPECIAL) {
377 buf[i++] = '.';
378 size--;
379 }
380 }
381
382 if ( intr == 0.0 ) {
383 buf[i++] = '0';
384 size--;
385 }
386 else {
387 while ( intr > 0.0 ) {
388 p = intr;
389 intr/=10.0L;
390 modf(intr, &intr);
391
392 p -= 10.0*intr;
393
394 buf[i++] = (int)p + '0';
395 size--;
396 }
397 }
398
399 j = 0;
400 while ( j < i && ro == 1) {
401 if ( buf[j] >= '0' && buf[j] <= '8' ) {
402 buf[j]++;
403 ro = 0;
404 }
405 else if ( buf[j] == '9' ) {
406 buf[j] = '0';
407 }
408 j++;
409 }
410 if ( ro == 1 )
411 buf[i++] = '1';
412
413 buf[i] = 0;
414
415 size -= precision;
416 if (!(type&(ZEROPAD+LEFT)))
417 {
418 while(size-->0)
419 f += ' ';
420 }
421 if (sign)
422 {
423 f += sign;
424 }
425
426 if (!(type&(ZEROPAD+LEFT)))
427 while(size-->0)
428 {
429 f += ' ';
430 }
431 if (type & SPECIAL) {
432 }
433
434 if (!(type & LEFT))
435 while (size-- > 0)
436 {
437 f += c;
438 }
439
440 tmp = buf;
441 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
442 {
443 j = 0;
444 while ( j < i && ( *tmp == '0' || *tmp == '.' ))
445 {
446 tmp++;
447 i--;
448 }
449 }
450 // else
451 // while (i < precision--)
452 // putc('0', f);
453 while (i-- > 0)
454 {
455 f += tmp[i];
456 }
457 while (size-- > 0)
458 {
459 f += ' ';
460 }
461 }
462 return true;
463 }
464
465 static bool
466 wnumberf(std::wstring& f, double __n, wchar_t exp_sign, int size, int precision, int type)
467 {
468 double exponent = 0.0;
469 double e;
470 long ie;
471
472 int i = 0;
473 int j = 0;
474
475 double frac, intr;
476 double p;
477 wchar_t *buf, *tmp, sign, c, ro = 0;
478 int result;
479
480 union
481 {
482 double* __n;
483 ieee_double_t* n;
484 } n;
485
486 n.__n = &__n;
487
488 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
489 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff);
490 exponent = ie/3.321928;
491 }
492
493 if ( exp_sign == L'g' || exp_sign == L'G' )
494 {
495 type |= ZEROTRUNC;
496 if ( exponent < -4 || fabs(exponent) >= precision )
497 exp_sign -= 2; // g -> e and G -> E
498 }
499
500 if ( exp_sign == L'e' || exp_sign == L'E' )
501 {
502 frac = modf(exponent,&e);
503 if ( frac > 0.5 )
504 e++;
505 else if ( frac < -0.5 )
506 e--;
507
508 result = wnumberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type);
509 if (result < 0)
510 return false;
511 f += exp_sign;
512 size--;
513 ie = (long)e;
514 type = LEFT | PLUS;
515 if ( ie < 0 )
516 type |= SIGN;
517
518 result = wnumber(f,ie, 10,2, 2,type );
519 if (result < 0)
520 return false;
521 return true;
522 }
523
524 if ( exp_sign == L'f' )
525 {
526 buf = (wchar_t*)alloca(4096*sizeof(wchar_t));
527 if (type & LEFT)
528 type &= ~ZEROPAD;
529
530 c = (type & ZEROPAD) ? L'0' : L' ';
531 sign = 0;
532 if (type & SIGN)
533 {
534 if (__n < 0)
535 {
536 sign = L'-';
537 __n = fabs(__n);
538 size--;
539 }
540 else if (type & PLUS)
541 {
542 sign = L'+';
543 size--;
544 }
545 else if (type & SPACE)
546 {
547 sign = L' ';
548 size--;
549 }
550 }
551
552 frac = modf(__n,&intr);
553
554 // # flags forces a . and prevents trucation of trailing zero's
555
556 if ( precision > 0 ) {
557 //frac = modfl(__n,&intr);
558 i = precision-1;
559 while ( i >= 0 ) {
560 frac*=10.0L;
561 frac = modf(frac, &p);
562 buf[i] = (int)p + L'0';
563 i--;
564 }
565 i = precision;
566 size -= precision;
567
568 ro = 0;
569 if ( frac > 0.5 ) {
570 ro = 1;
571 }
572
573 if ( precision >= 1 || type & SPECIAL) {
574 buf[i++] = L'.';
575 size--;
576 }
577 }
578
579 if ( intr == 0.0 ) {
580 buf[i++] = L'0';
581 size--;
582 }
583 else {
584 while ( intr > 0.0 ) {
585 p = intr;
586 intr/=10.0L;
587 modf(intr, &intr);
588
589 p -= 10.0*intr;
590
591 buf[i++] = (int)p + L'0';
592 size--;
593 }
594 }
595
596 j = 0;
597 while ( j < i && ro == 1) {
598 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
599 buf[j]++;
600 ro = 0;
601 }
602 else if ( buf[j] == L'9' ) {
603 buf[j] = L'0';
604 }
605 j++;
606 }
607 if ( ro == 1 )
608 buf[i++] = L'1';
609
610 buf[i] = 0;
611
612 size -= precision;
613 if (!(type&(ZEROPAD+LEFT)))
614 {
615 while(size-->0)
616 f += L' ';
617 }
618 if (sign)
619 {
620 f += sign;
621 }
622
623 if (!(type&(ZEROPAD+LEFT)))
624 while(size-->0)
625 {
626 f += L' ';
627 }
628 if (type & SPECIAL) {
629 }
630
631 if (!(type & LEFT))
632 while (size-- > 0)
633 {
634 f += c;
635 }
636
637 tmp = buf;
638 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
639 {
640 j = 0;
641 while ( j < i && ( *tmp == L'0' || *tmp == L'.' ))
642 {
643 tmp++;
644 i--;
645 }
646 }
647 while (i-- > 0)
648 {
649 f += tmp[i];
650 }
651 while (size-- > 0)
652 {
653 f += L' ';
654 }
655 }
656 return true;
657 }
658
659 static bool
660 numberfl(std::string& f, long double __n, char exp_sign, int size, int precision, int type)
661 {
662 long double exponent = 0.0;
663 long double e;
664 long ie;
665
666 //int x;
667 char *buf, *tmp;
668 int i = 0;
669 int j = 0;
670 //int k = 0;
671
672 long double frac, intr;
673 long double p;
674 char sign;
675 char c;
676 char ro = 0;
677
678 int result;
679
680 union
681 {
682 long double* __n;
683 ieee_long_double_t* n;
684 } n;
685
686 n.__n = &__n;
687
688 if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
689 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff);
690 exponent = ie/3.321928;
691 }
692
693 if ( exp_sign == 'g' || exp_sign == 'G' ) {
694 type |= ZEROTRUNC;
695 if ( exponent < -4 || fabs(exponent) >= precision )
696 exp_sign -= 2; // g -> e and G -> E
697 }
698
699 if ( exp_sign == 'e' || exp_sign == 'E' ) {
700 frac = modfl(exponent,&e);
701 if ( frac > 0.5 )
702 e++;
703 else if ( frac < -0.5 )
704 e--;
705
706 result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type);
707 if (result < 0)
708 return false;
709 f += exp_sign;
710 size--;
711 ie = (long)e;
712 type = LEFT | PLUS;
713 if ( ie < 0 )
714 type |= SIGN;
715
716 result = number(f,ie, 10,2, 2,type );
717 if (result < 0)
718 return false;
719 return true;
720
721 }
722
723 if ( exp_sign == 'f' )
724 {
725
726 buf = (char*)alloca(4096);
727 if (type & LEFT)
728 {
729 type &= ~ZEROPAD;
730 }
731
732 c = (type & ZEROPAD) ? '0' : ' ';
733 sign = 0;
734 if (type & SIGN)
735 {
736 if (__n < 0)
737 {
738 sign = '-';
739 __n = fabs(__n);
740 size--;
741 } else if (type & PLUS)
742 {
743 sign = '+';
744 size--;
745 } else if (type & SPACE)
746 {
747 sign = ' ';
748 size--;
749 }
750 }
751
752 frac = modfl(__n,&intr);
753
754 // # flags forces a . and prevents trucation of trailing zero's
755 if ( precision > 0 )
756 {
757 //frac = modfl(__n,&intr);
758
759 i = precision-1;
760 while ( i >= 0 )
761 {
762 frac*=10.0L;
763 frac = modfl((long double)frac, &p);
764 buf[i] = (int)p + '0';
765 i--;
766 }
767 i = precision;
768 size -= precision;
769
770 ro = 0;
771 if ( frac > 0.5 )
772 {
773 ro = 1;
774 }
775
776 if ( precision >= 1 || type & SPECIAL)
777 {
778 buf[i++] = '.';
779 size--;
780 }
781 }
782
783 if ( intr == 0.0 )
784 {
785 buf[i++] = '0';
786 size--;
787 }
788 else
789 {
790 while ( intr > 0.0 )
791 {
792 p=intr;
793 intr/=10.0L;
794 modfl(intr, &intr);
795
796 p -= 10.0L*intr;
797
798 buf[i++] = (int)p + '0';
799 size--;
800 }
801 }
802
803 j = 0;
804 while ( j < i && ro == 1) {
805 if ( buf[j] >= '0' && buf[j] <= '8' )
806 {
807 buf[j]++;
808 ro = 0;
809 }
810 else if ( buf[j] == '9' )
811 {
812 buf[j] = '0';
813 }
814 j++;
815 }
816 if ( ro == 1 )
817 buf[i++] = '1';
818
819 buf[i] = 0;
820
821 size -= precision;
822 if (!(type&(ZEROPAD+LEFT)))
823 {
824 while(size-->0)
825 f += ' ';
826 }
827 if (sign)
828 {
829 f += sign;
830 }
831
832 if (!(type&(ZEROPAD+LEFT)))
833 {
834 while(size-->0)
835 f += ' ';
836 }
837 if (type & SPECIAL) {
838 }
839
840 if (!(type & LEFT))
841 while (size-- > 0)
842 {
843 f += c;
844 }
845 tmp = buf;
846 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
847 {
848 j = 0;
849 while ( j < i && ( *tmp == '0' || *tmp == '.' ))
850 {
851 tmp++;
852 i--;
853 }
854 }
855 while (i-- > 0)
856 {
857 f += tmp[i];
858 }
859 while (size-- > 0)
860 {
861 f += ' ';
862 }
863 }
864 return true;
865 }
866
867 static bool
868 wnumberfl(std::wstring& f, long double __n, wchar_t exp_sign, int size, int precision, int type)
869 {
870 long double exponent = 0.0;
871 long double e;
872 long ie;
873
874 wchar_t *buf, *tmp, sign, c, ro = 0;
875 int i = 0;
876 int j = 0;
877
878 long double frac, intr;
879 long double p;
880
881 int result;
882
883 union
884 {
885 long double* __n;
886 ieee_long_double_t* n;
887 } n;
888
889 n.__n = &__n;
890
891 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
892 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff);
893 exponent = ie/3.321928;
894 }
895
896 if ( exp_sign == L'g' || exp_sign == L'G' ) {
897 type |= ZEROTRUNC;
898 if ( exponent < -4 || fabs(exponent) >= precision )
899 exp_sign -= 2; // g -> e and G -> E
900 }
901
902
903 if ( exp_sign == L'e' || exp_sign == L'E' ) {
904 frac = modfl(exponent,&e);
905 if ( frac > 0.5 )
906 e++;
907 else if ( frac < -0.5 )
908 e--;
909
910 result = wnumberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type);
911 if (result < 0)
912 return false;
913 f += exp_sign;
914 size--;
915 ie = (long)e;
916 type = LEFT | PLUS;
917 if ( ie < 0 )
918 type |= SIGN;
919
920 result = wnumber(f,ie, 10,2, 2,type );
921 if (result < 0)
922 return false;
923 return true;
924 }
925
926 if ( exp_sign == L'f' )
927 {
928
929 buf = (wchar_t*)alloca(4096*sizeof(wchar_t));
930 if (type & LEFT)
931 {
932 type &= ~ZEROPAD;
933 }
934
935 c = (type & ZEROPAD) ? L'0' : L' ';
936 sign = 0;
937 if (type & SIGN)
938 {
939 if (__n < 0)
940 {
941 sign = L'-';
942 __n = fabs(__n);
943 size--;
944 } else if (type & PLUS)
945 {
946 sign = L'+';
947 size--;
948 } else if (type & SPACE)
949 {
950 sign = L' ';
951 size--;
952 }
953 }
954
955 frac = modfl(__n,&intr);
956
957 // # flags forces a . and prevents trucation of trailing zero's
958 if ( precision > 0 )
959 {
960 //frac = modfl(__n,&intr);
961
962 i = precision-1;
963 while ( i >= 0 )
964 {
965 frac*=10.0L;
966 frac = modfl((long double)frac, &p);
967 buf[i] = (int)p + L'0';
968 i--;
969 }
970 i = precision;
971 size -= precision;
972
973 ro = 0;
974 if ( frac > 0.5 )
975 {
976 ro = 1;
977 }
978
979 if ( precision >= 1 || type & SPECIAL)
980 {
981 buf[i++] = L'.';
982 size--;
983 }
984 }
985
986 if ( intr == 0.0 )
987 {
988 buf[i++] = L'0';
989 size--;
990 }
991 else
992 {
993 while ( intr > 0.0 )
994 {
995 p=intr;
996 intr/=10.0L;
997 modfl(intr, &intr);
998
999 p -= 10.0L*intr;
1000
1001 buf[i++] = (int)p + L'0';
1002 size--;
1003 }
1004 }
1005
1006 j = 0;
1007 while ( j < i && ro == 1) {
1008 if ( buf[j] >= L'0' && buf[j] <= L'8' )
1009 {
1010 buf[j]++;
1011 ro = 0;
1012 }
1013 else if ( buf[j] == L'9' )
1014 {
1015 buf[j] = L'0';
1016 }
1017 j++;
1018 }
1019 if ( ro == 1 )
1020 buf[i++] = L'1';
1021
1022 buf[i] = 0;
1023
1024 size -= precision;
1025 if (!(type&(ZEROPAD+LEFT)))
1026 {
1027 while(size-->0)
1028 f += L' ';
1029 }
1030 if (sign)
1031 {
1032 f += sign;
1033 }
1034
1035 if (!(type&(ZEROPAD+LEFT)))
1036 {
1037 while(size-->0)
1038 f += L' ';
1039 }
1040 if (type & SPECIAL) {
1041 }
1042
1043 if (!(type & LEFT))
1044 while (size-- > 0)
1045 {
1046 f += c;
1047 }
1048 tmp = buf;
1049 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
1050 {
1051 j = 0;
1052 while ( j < i && ( *tmp == L'0' || *tmp == L'.' ))
1053 {
1054 tmp++;
1055 i--;
1056 }
1057 }
1058 while (i-- > 0)
1059 {
1060 f += tmp[i];
1061 }
1062 while (size-- > 0)
1063 {
1064 f += L' ';
1065 }
1066 }
1067 return true;
1068 }
1069
1070 static int
1071 do_string(std::string& f, const char* s, int len, int field_width, int precision, int flags)
1072 {
1073 int i, done = 0;
1074 if (s == NULL)
1075 {
1076 s = "<NULL>";
1077 len = 6;
1078 }
1079 else
1080 {
1081 if (len == -1)
1082 {
1083 len = 0;
1084 while ((unsigned int)len < (unsigned int)precision && s[len])
1085 len++;
1086 }
1087 else
1088 {
1089 if ((unsigned int)len > (unsigned int)precision)
1090 len = precision;
1091 }
1092 }
1093 if (!(flags & LEFT))
1094 while (len < field_width--)
1095 {
1096 f += ' ';
1097 done++;
1098 }
1099 for (i = 0; i < len; ++i)
1100 {
1101 f += *s++;
1102 done++;
1103 }
1104 while (len < field_width--)
1105 {
1106 f += ' ';
1107 done++;
1108 }
1109 return done;
1110 }
1111
1112 static int
1113 do_wstring(std::wstring& f, const wchar_t* s, int len, int field_width, int precision, int flags)
1114 {
1115 int i, done = 0;
1116 if (s == NULL)
1117 {
1118 s = L"<NULL>";
1119 len = 6;
1120 }
1121 else
1122 {
1123 if (len == -1)
1124 {
1125 len = 0;
1126 while ((unsigned int)len < (unsigned int)precision && s[len])
1127 len++;
1128 }
1129 else
1130 {
1131 if ((unsigned int)len > (unsigned int)precision)
1132 len = precision;
1133 }
1134 }
1135 if (!(flags & LEFT))
1136 while (len < field_width--)
1137 {
1138 f += L' ';
1139 done++;
1140 }
1141 for (i = 0; i < len; ++i)
1142 {
1143 f += *s++;
1144 done++;
1145 }
1146 while (len < field_width--)
1147 {
1148 f += L' ';
1149 done++;
1150 }
1151 return done;
1152 }
1153
1154 static int
1155 stringw(std::string& f, const wchar_t* sw, int len, int field_width, int precision, int flags)
1156 {
1157 int i, done = 0;
1158 if (sw == NULL)
1159 {
1160 sw = L"<NULL>";
1161 len = 6;
1162 }
1163 else
1164 {
1165 if (len == -1)
1166 {
1167 len = 0;
1168 while ((unsigned int)len < (unsigned int)precision && sw[len])
1169 len++;
1170 }
1171 else
1172 {
1173 if ((unsigned int)len > (unsigned int)precision)
1174 len = precision;
1175 }
1176 }
1177 if (!(flags & LEFT))
1178 while (len < field_width--)
1179 {
1180 f += ' ';
1181 done++;
1182 }
1183 for (i = 0; i < len; ++i)
1184 {
1185 #define MY_MB_CUR_MAX 1
1186 char mb[MY_MB_CUR_MAX];
1187 int mbcount, j;
1188 mbcount = wctomb(mb, *sw++);
1189 if (mbcount <= 0)
1190 {
1191 break;
1192 }
1193 for (j = 0; j < mbcount; j++)
1194 {
1195 f += mb[j];
1196 done++;
1197 }
1198 }
1199 while (len < field_width--)
1200 {
1201 f += ' ';
1202 done++;
1203 }
1204 return done;
1205 }
1206
1207 static int
1208 wstringa(std::wstring& f, const char* sa, int len, int field_width, int precision, int flags)
1209 {
1210 int i, done = 0;
1211 if (sa == NULL)
1212 {
1213 sa = "<NULL>";
1214 len = 6;
1215 }
1216 else
1217 {
1218 if (len == -1)
1219 {
1220 len = 0;
1221 while ((unsigned int)len < (unsigned int)precision && sa[len])
1222 len++;
1223 }
1224 else
1225 {
1226 if ((unsigned int)len > (unsigned int)precision)
1227 len = precision;
1228 }
1229 }
1230 if (!(flags & LEFT))
1231 while (len < field_width--)
1232 {
1233 f += L' ';
1234 done++;
1235 }
1236 for (i = 0; i < len;)
1237 {
1238 wchar_t w;
1239 int mbcount;
1240 mbcount = mbtowc(&w, sa, len-i);
1241 if (mbcount <= 0)
1242 break;
1243 f += w;
1244 done++;
1245 i += mbcount;
1246 }
1247 while (len < field_width--)
1248 {
1249 f += L' ';
1250 done++;
1251 }
1252 return done;
1253 }
1254
1255 #define _isnanl _isnan
1256 #define _finitel _finite
1257
1258 std::string
1259 ssvprintf ( const char *fmt, va_list args )
1260 {
1261 ULONGLONG num;
1262 int base;
1263 long double _ldouble;
1264 double _double;
1265 const char *s;
1266 const wchar_t* sw;
1267 int result;
1268 std::string f;
1269
1270 int flags; /* flags to number() */
1271
1272 int field_width; /* width of output field */
1273 int precision; /* min. # of digits for integers; max
1274 number of chars for from string */
1275 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
1276
1277 for (; *fmt ; ++fmt)
1278 {
1279 if (*fmt != '%')
1280 {
1281 f += *fmt;
1282 continue;
1283 }
1284
1285 /* process flags */
1286 flags = 0;
1287 repeat:
1288 ++fmt; /* this also skips first '%' */
1289 switch (*fmt) {
1290 case '-': flags |= LEFT; goto repeat;
1291 case '+': flags |= PLUS; goto repeat;
1292 case ' ': flags |= SPACE; goto repeat;
1293 case '#': flags |= SPECIAL; goto repeat;
1294 case '0': flags |= ZEROPAD; goto repeat;
1295 }
1296
1297 /* get field width */
1298 field_width = -1;
1299 if (isdigit(*fmt))
1300 field_width = skip_atoi(&fmt);
1301 else if (*fmt == '*') {
1302 ++fmt;
1303 /* it's the next argument */
1304 field_width = va_arg(args, int);
1305 if (field_width < 0) {
1306 field_width = -field_width;
1307 flags |= LEFT;
1308 }
1309 }
1310
1311 /* get the precision */
1312 precision = -1;
1313 if (*fmt == '.') {
1314 ++fmt;
1315 if (isdigit(*fmt))
1316 precision = skip_atoi(&fmt);
1317 else if (*fmt == '*') {
1318 ++fmt;
1319 /* it's the next argument */
1320 precision = va_arg(args, int);
1321 }
1322 if (precision < 0)
1323 precision = 0;
1324 }
1325
1326 /* get the conversion qualifier */
1327 qualifier = 0;
1328 // %Z can be just stand alone or as size_t qualifier
1329 if ( *fmt == 'Z' ) {
1330 qualifier = *fmt;
1331 switch ( *(fmt+1)) {
1332 case 'o':
1333 case 'b':
1334 case 'X':
1335 case 'x':
1336 case 'd':
1337 case 'i':
1338 case 'u':
1339 ++fmt;
1340 break;
1341 default:
1342 break;
1343 }
1344 } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') {
1345 qualifier = *fmt;
1346 ++fmt;
1347 } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') {
1348 qualifier = *fmt;
1349 fmt += 3;
1350 }
1351
1352 // go fine with ll instead of L
1353 if ( *fmt == 'l' ) {
1354 ++fmt;
1355 qualifier = 'L';
1356 }
1357
1358 /* default base */
1359 base = 10;
1360
1361 switch (*fmt) {
1362 case 'c':
1363 if (!(flags & LEFT))
1364 while (--field_width > 0)
1365 {
1366 f += ' ';
1367 }
1368 if (qualifier == 'l' || qualifier == 'w')
1369 {
1370 f += (char)(unsigned char)(wchar_t) va_arg(args,int);
1371 }
1372 else
1373 {
1374 f += (char)(unsigned char) va_arg(args,int);
1375 }
1376 while (--field_width > 0)
1377 {
1378 f += ' ';
1379 }
1380 continue;
1381
1382 case 'C':
1383 if (!(flags & LEFT))
1384 while (--field_width > 0)
1385 {
1386 f += ' ';
1387 }
1388 if (qualifier == 'h')
1389 {
1390 f += (char)(unsigned char) va_arg(args,int);
1391 }
1392 else
1393 {
1394 f += (char)(unsigned char)(wchar_t) va_arg(args,int);
1395 }
1396 while (--field_width > 0)
1397 {
1398 f += ' ';
1399 }
1400 continue;
1401
1402 case 's':
1403 if (qualifier == 'l' || qualifier == 'w') {
1404 /* print unicode string */
1405 sw = va_arg(args, wchar_t *);
1406 result = stringw(f, sw, -1, field_width, precision, flags);
1407 } else {
1408 /* print ascii string */
1409 s = va_arg(args, char *);
1410 result = do_string(f, s, -1, field_width, precision, flags);
1411 }
1412 if (result < 0)
1413 {
1414 assert(!"TODO FIXME handle error better");
1415 return f;
1416 }
1417 continue;
1418
1419 case 'S':
1420 if (qualifier == 'h') {
1421 /* print ascii string */
1422 s = va_arg(args, char *);
1423 result = do_string(f, s, -1, field_width, precision, flags);
1424 } else {
1425 /* print unicode string */
1426 sw = va_arg(args, wchar_t *);
1427 result = stringw(f, sw, -1, field_width, precision, flags);
1428 }
1429 if (result < 0)
1430 {
1431 assert(!"TODO FIXME handle error better");
1432 return f;
1433 }
1434 continue;
1435
1436 /*case 'Z':
1437 if (qualifier == 'w') {
1438 // print counted unicode string
1439 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
1440 if ((pus == NULL) || (pus->Buffer == NULL)) {
1441 sw = NULL;
1442 len = -1;
1443 } else {
1444 sw = pus->Buffer;
1445 len = pus->Length / sizeof(WCHAR);
1446 }
1447 result = stringw(f, sw, len, field_width, precision, flags);
1448 } else {
1449 // print counted ascii string
1450 PANSI_STRING pas = va_arg(args, PANSI_STRING);
1451 if ((pas == NULL) || (pas->Buffer == NULL)) {
1452 s = NULL;
1453 len = -1;
1454 } else {
1455 s = pas->Buffer;
1456 len = pas->Length;
1457 }
1458 result = string(f, s, -1, field_width, precision, flags);
1459 }
1460 if (result < 0)
1461 return -1;
1462 continue;*/
1463
1464 case 'e':
1465 case 'E':
1466 case 'f':
1467 case 'g':
1468 case 'G':
1469 if (qualifier == 'l' || qualifier == 'L' ) {
1470 _ldouble = va_arg(args, long double);
1471
1472 if ( _isnanl(_ldouble) )
1473 {
1474 f += "Nan";
1475 }
1476 else if ( !_finitel(_ldouble) )
1477 {
1478 if ( _ldouble < 0 )
1479 f += "-Inf";
1480 else
1481 f += "+Inf";
1482 } else {
1483 if ( precision == -1 )
1484 precision = 6;
1485 result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
1486 if (result < 0)
1487 {
1488 assert(!"TODO FIXME handle error better");
1489 return f;
1490 }
1491 }
1492 } else {
1493 _double = (double)va_arg(args, double);
1494
1495 if ( _isnan(_double) )
1496 {
1497 f += "Nan";
1498 }
1499 else if ( !_finite(_double) )
1500 {
1501 if ( _double < 0 )
1502 f += "-Inf";
1503 else
1504 f += "+Inf";
1505 }
1506 else
1507 {
1508 if ( precision == -1 )
1509 precision = 6;
1510 result = numberf(f,_double,*fmt,field_width,precision,flags);
1511 if (result < 0)
1512 {
1513 assert(!"TODO FIXME handle error better");
1514 return f;
1515 }
1516 }
1517 }
1518 continue;
1519
1520 case 'p':
1521 if (field_width == -1) {
1522 field_width = 2*sizeof(void *);
1523 flags |= ZEROPAD;
1524 }
1525 result = number(f,
1526 (unsigned long) va_arg(args, void *), 16,
1527 field_width, precision, flags);
1528 if (result < 0)
1529 {
1530 assert(!"TODO FIXME handle error better");
1531 return f;
1532 }
1533 continue;
1534
1535 case 'n':
1536 if (qualifier == 'l') {
1537 long * ip = va_arg(args, long *);
1538 *ip = 0;
1539 } else {
1540 int * ip = va_arg(args, int *);
1541 *ip = 0;
1542 }
1543 continue;
1544
1545 /* integer number formats - set up the flags and "break" */
1546 case 'o':
1547 base = 8;
1548 break;
1549
1550 case 'b':
1551 base = 2;
1552 break;
1553
1554 case 'X':
1555 flags |= LARGE;
1556 case 'x':
1557 base = 16;
1558 break;
1559
1560 case 'd':
1561 case 'i':
1562 flags |= SIGN;
1563 case 'u':
1564 break;
1565
1566 default:
1567 if (*fmt != '%')
1568 {
1569 f += '%';
1570 }
1571 if (*fmt)
1572 {
1573 f += *fmt;
1574 }
1575 else
1576 --fmt;
1577 continue;
1578 }
1579
1580 if (qualifier == 'I')
1581 num = va_arg(args, ULONGLONG);
1582 else if (qualifier == 'l') {
1583 if (flags & SIGN)
1584 num = va_arg(args, long);
1585 else
1586 num = va_arg(args, unsigned long);
1587 }
1588 else if (qualifier == 'h') {
1589 if (flags & SIGN)
1590 num = va_arg(args, int);
1591 else
1592 num = va_arg(args, unsigned int);
1593 }
1594 else if (flags & SIGN)
1595 num = va_arg(args, int);
1596 else
1597 num = va_arg(args, unsigned int);
1598 result = number(f, num, base, field_width, precision, flags);
1599 if (result < 0)
1600 {
1601 assert(!"TODO FIXME handle error better");
1602 return f;
1603 }
1604 }
1605 //putc('\0',f);
1606 return f;
1607 }
1608
1609 std::wstring
1610 sswvprintf ( const wchar_t* fmt, va_list args )
1611 {
1612 ULONGLONG num;
1613 int base;
1614 long double _ldouble;
1615 double _double;
1616 const wchar_t* s;
1617 const char* sa;
1618 int result;
1619 std::wstring f;
1620
1621 int flags; /* flags to number() */
1622
1623 int field_width; /* width of output field */
1624 int precision; /* min. # of digits for integers; max
1625 number of chars for from string */
1626 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
1627
1628 for (; *fmt ; ++fmt)
1629 {
1630 if (*fmt != L'%')
1631 {
1632 f += *fmt;
1633 continue;
1634 }
1635
1636 /* process flags */
1637 flags = 0;
1638 repeat:
1639 ++fmt; /* this also skips first '%' */
1640 switch (*fmt) {
1641 case L'-': flags |= LEFT; goto repeat;
1642 case L'+': flags |= PLUS; goto repeat;
1643 case L' ': flags |= SPACE; goto repeat;
1644 case L'#': flags |= SPECIAL; goto repeat;
1645 case L'0': flags |= ZEROPAD; goto repeat;
1646 }
1647
1648 /* get field width */
1649 field_width = -1;
1650 if (isdigit(*fmt))
1651 field_width = skip_wtoi(&fmt);
1652 else if (*fmt == L'*') {
1653 ++fmt;
1654 /* it's the next argument */
1655 field_width = va_arg(args, int);
1656 if (field_width < 0) {
1657 field_width = -field_width;
1658 flags |= LEFT;
1659 }
1660 }
1661
1662 /* get the precision */
1663 precision = -1;
1664 if (*fmt == L'.') {
1665 ++fmt;
1666 if (iswdigit(*fmt))
1667 precision = skip_wtoi(&fmt);
1668 else if (*fmt == L'*') {
1669 ++fmt;
1670 /* it's the next argument */
1671 precision = va_arg(args, int);
1672 }
1673 if (precision < 0)
1674 precision = 0;
1675 }
1676
1677 /* get the conversion qualifier */
1678 qualifier = 0;
1679 // %Z can be just stand alone or as size_t qualifier
1680 if ( *fmt == L'Z' ) {
1681 qualifier = *fmt;
1682 switch ( *(fmt+1)) {
1683 case L'o':
1684 case L'b':
1685 case L'X':
1686 case L'x':
1687 case L'd':
1688 case L'i':
1689 case L'u':
1690 ++fmt;
1691 break;
1692 default:
1693 break;
1694 }
1695 } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') {
1696 qualifier = *fmt;
1697 ++fmt;
1698 } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') {
1699 qualifier = *fmt;
1700 fmt += 3;
1701 }
1702
1703 // go fine with ll instead of L
1704 if ( *fmt == L'l' ) {
1705 ++fmt;
1706 qualifier = L'L';
1707 }
1708
1709 /* default base */
1710 base = 10;
1711
1712 switch (*fmt) {
1713 case L'c':
1714 if (!(flags & LEFT))
1715 while (--field_width > 0)
1716 {
1717 f += L' ';
1718 }
1719 if ( qualifier == L'h' )
1720 {
1721 f += (wchar_t)(char)(unsigned char) va_arg(args,int);
1722 }
1723 else
1724 {
1725 f += (wchar_t) va_arg(args,int);
1726 }
1727 while (--field_width > 0)
1728 {
1729 f += ' ';
1730 }
1731 continue;
1732
1733 case 'C':
1734 if (!(flags & LEFT))
1735 while (--field_width > 0)
1736 {
1737 f += L' ';
1738 }
1739 if (qualifier == L'l' || qualifier == L'w')
1740 {
1741 f += (wchar_t) va_arg(args,int);
1742 }
1743 else
1744 {
1745 f += (wchar_t)(char)(unsigned char) va_arg(args,int);
1746 }
1747 while (--field_width > 0)
1748 {
1749 f += L' ';
1750 }
1751 continue;
1752
1753 case 's':
1754 if (qualifier == L'h') {
1755 /* print ascii string */
1756 sa = va_arg(args, char *);
1757 result = wstringa(f, sa, -1, field_width, precision, flags);
1758 } else {
1759 /* print unicode string */
1760 s = va_arg(args, wchar_t *);
1761 result = do_wstring(f, s, -1, field_width, precision, flags);
1762 }
1763 if (result < 0)
1764 {
1765 assert(!"TODO FIXME handle error better");
1766 return f;
1767 }
1768 continue;
1769
1770 case 'S':
1771 if (qualifier == L'l' || qualifier == L'w') {
1772 /* print unicode string */
1773 s = va_arg(args, wchar_t *);
1774 result = do_wstring(f, s, -1, field_width, precision, flags);
1775 } else {
1776 /* print ascii string */
1777 sa = va_arg(args, char *);
1778 result = wstringa(f, sa, -1, field_width, precision, flags);
1779 }
1780 if (result < 0)
1781 {
1782 assert(!"TODO FIXME handle error better");
1783 return f;
1784 }
1785 continue;
1786
1787 case L'e':
1788 case L'E':
1789 case L'f':
1790 case L'g':
1791 case L'G':
1792 if (qualifier == L'l' || qualifier == L'L' )
1793 {
1794 _ldouble = va_arg(args, long double);
1795
1796 if ( _isnanl(_ldouble) )
1797 {
1798 f += L"Nan";
1799 }
1800 else if ( !_finitel(_ldouble) )
1801 {
1802 if ( _ldouble < 0 )
1803 f += L"-Inf";
1804 else
1805 f += L"+Inf";
1806 } else {
1807 if ( precision == -1 )
1808 precision = 6;
1809 result = wnumberfl(f,_ldouble,*fmt,field_width,precision,flags);
1810 if (result < 0)
1811 {
1812 assert(!"TODO FIXME handle error better");
1813 return f;
1814 }
1815 }
1816 } else {
1817 _double = (double)va_arg(args, double);
1818
1819 if ( _isnan(_double) )
1820 {
1821 f += L"Nan";
1822 }
1823 else if ( !_finite(_double) )
1824 {
1825 if ( _double < 0 )
1826 f += L"-Inf";
1827 else
1828 f += L"+Inf";
1829 }
1830 else
1831 {
1832 if ( precision == -1 )
1833 precision = 6;
1834 result = wnumberf(f,_double,*fmt,field_width,precision,flags);
1835 if (result < 0)
1836 {
1837 assert(!"TODO FIXME handle error better");
1838 return f;
1839 }
1840 }
1841 }
1842 continue;
1843
1844 case L'p':
1845 if (field_width == -1) {
1846 field_width = 2*sizeof(void *);
1847 flags |= ZEROPAD;
1848 }
1849 result = wnumber(f,
1850 (unsigned long) va_arg(args, void *), 16,
1851 field_width, precision, flags);
1852 if (result < 0)
1853 {
1854 assert(!"TODO FIXME handle error better");
1855 return f;
1856 }
1857 continue;
1858
1859 case L'n':
1860 if (qualifier == L'l') {
1861 long * ip = va_arg(args, long *);
1862 *ip = 0;
1863 } else {
1864 int * ip = va_arg(args, int *);
1865 *ip = 0;
1866 }
1867 continue;
1868
1869 /* integer number formats - set up the flags and "break" */
1870 case L'o':
1871 base = 8;
1872 break;
1873
1874 case L'b':
1875 base = 2;
1876 break;
1877
1878 case L'X':
1879 flags |= LARGE;
1880 case L'x':
1881 base = 16;
1882 break;
1883
1884 case L'd':
1885 case L'i':
1886 flags |= SIGN;
1887 case L'u':
1888 break;
1889
1890 default:
1891 if (*fmt != L'%')
1892 {
1893 f += L'%';
1894 }
1895 if (*fmt)
1896 {
1897 f += *fmt;
1898 }
1899 else
1900 --fmt;
1901 continue;
1902 }
1903
1904 if (qualifier == L'I')
1905 num = va_arg(args, ULONGLONG);
1906 else if (qualifier == L'l') {
1907 if (flags & SIGN)
1908 num = va_arg(args, long);
1909 else
1910 num = va_arg(args, unsigned long);
1911 }
1912 else if (qualifier == L'h') {
1913 if (flags & SIGN)
1914 num = va_arg(args, int);
1915 else
1916 num = va_arg(args, unsigned int);
1917 }
1918 else if (flags & SIGN)
1919 num = va_arg(args, int);
1920 else
1921 num = va_arg(args, unsigned int);
1922 result = wnumber(f, num, base, field_width, precision, flags);
1923 if (result < 0)
1924 {
1925 assert(!"TODO FIXME handle error better");
1926 return f;
1927 }
1928 }
1929 //putc('\0',f);
1930 return f;
1931 }