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