Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
num_put.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30#include <rw/_defs.h>
31
32#include <limits> // for numeric_limits
33
34#include <stdio.h> // for snprintf()
35#include <string.h> // for memmove(), memset()
36
37#include <loc/_num_put.h>
38
39#include "fpclass.h" // for __rw_isfinite(), ...
40#include "strtol.h" // for __rw_digit_map
41#include "punct.h" // for __rw_get_stdio_fmat
42
43
44#ifndef _RWSTD_NO_SNPRINTF
45 // cast away constness of the format argument to prevent errors
46 // on platforms such as HP-UX 11.00 that incorrectly declare it
47 // without the const qualifier
48# define _SNPRINTF(buf, size, fmt, arg) \
49 snprintf (buf, size, _RWSTD_CONST_CAST (char*, fmt), arg)
50#else // _RWSTD_NO_SNPRINTF
51# ifndef _RWSTD_NO_SNPRINTF_IN_LIBC
52
53# undef snprintf
54# define snprintf _RWSTD_LIBC_SYM (snprintf)
55# define _SNPRINTF(buf, size, fmt, arg) snprintf (buf, size, fmt, arg)
56
57extern "C" {
58
60snprintf (char*, _RWSTD_SIZE_T, const char*, ...) _LIBC_THROWS ();
61
62} // extern "C"
63
64# else // if defined (_RWSTD_NO_SNPRINTF_IN_LIBC)
65# define _SNPRINTF(buf, ignore, fmt, arg) sprintf (buf, fmt, arg)
66# endif // _RWSTD_NO_SNPRINTF_IN_LIBC
67#endif // _RWSTD_NO_SNPRINTF
68
69
71
72static const char __rw_digits[] =
73 "0123456789abcdefghijklmnopqrstuvwxyz"
74 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
75
76
77static int
78__rw_fmat_infinite (char *buf, size_t bufsize, double val, unsigned flags)
79{
81 _RWSTD_ASSERT (5 <= bufsize);
82
83 _RWSTD_UNUSED (bufsize);
84
85 char* end = buf;
86 const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
87
88 if (__rw_isinf (val)) {
89 if (__rw_signbit (val)) {
90 *end++ = '-';
91 }
92 else if (flags & _RWSTD_IOS_SHOWPOS) {
93 *end++ = '+';
94 }
95
96 const char str [] = "iInNfF";
97 *end++ = str [cap + 0];
98 *end++ = str [cap + 2];
99 *end++ = str [cap + 4];
100 }
101 else {
103
104 if (__rw_signbit (val)) {
105 *end++ = '-';
106 }
107 else if (flags & _RWSTD_IOS_SHOWPOS) {
108 *end++ = '+';
109 }
110
111 const char str [] = "nNaAqQsS";
112
113 if (__rw_isqnan (val))
114 *end++ = str [cap + 4];
115 else if (__rw_issnan (val))
116 *end++ = str [cap + 6];
117
118 *end++ = str [cap + 0];
119 *end++ = str [cap + 2];
120 *end++ = str [cap + 0];
121 }
122
123 return int (end - buf);
124}
125
126
127#ifdef _RWSTD_LONG_LONG
128
129
130typedef _RWSTD_LONG_LONG _LLong;
131typedef unsigned _RWSTD_LONG_LONG _ULLong;
132
133
134static _RWSTD_SIZE_T
135__rw_btoa (char *buf, _ULLong i, unsigned base)
136{
137 _RWSTD_ASSERT (base && base <= 36);
138
139 const _RWSTD_SIZE_T dig = _STD::numeric_limits<_ULLong>::digits + 0U;
140
141 char* end = buf + dig;
142 const char* const begin = end;
143
144 _ULLong tmp;
145 do {
146 tmp = i / base;
147
148 // PA RISC has no integer divide, optimize the modulo operator
149 // this is also faster than computing the modulo on i86, and
150 // faster than calling ldiv()
151 *--end = __rw_digits [i - tmp * base];
152 } while ((i = tmp));
153
154 const _RWSTD_SIZE_T len = begin - end;
155
156 memmove (buf, end, len);
157
158 return len;
159}
160
161
162static _RWSTD_SIZE_T
163__rw_dtoa (char *buf, _ULLong i, unsigned flags)
164{
165 // get the maximum number of decimal digits for an unsigned long
166 // with the largest magnitude, plus 1 for the (optional) sign
167 const _RWSTD_SIZE_T dig10 = _STD::numeric_limits<_ULLong>::digits10 + 2U;
168
169 char* end = buf + dig10;
170 const char* const begin = end;
171
172 _ULLong tmp;
173 do {
174 tmp = i / 10;
175
176 // PA RISC has no integer divide, optimize the modulo operator
177 // this is also faster than computing the modulo on i86, and
178 // faster than calling ldiv()
179 *--end = __rw_digits [i - tmp * 10];
180 } while ((i = tmp));
181
182
184 *--end = '+';
185
186 const _RWSTD_SIZE_T len = begin - end;
187
188 memmove (buf, end, len);
189
190 return len;
191}
192
193
194static inline _RWSTD_SIZE_T
195__rw_dtoa (char *buf, _LLong i, unsigned flags)
196{
197 if (i < 0) {
198 flags &= ~_RWSTD_IOS_SHOWPOS;
199 *buf++ = '-';
200 return 1 + __rw_dtoa (buf, _RWSTD_STATIC_CAST (_ULLong, -i), flags);
201 }
202
203 return __rw_dtoa (buf, _RWSTD_STATIC_CAST (_ULLong, i), flags);
204}
205
206
207static _RWSTD_SIZE_T
208__rw_itoa (char *buf, _ULLong i, unsigned flags)
209{
210 const char* const pdigs = flags & _RWSTD_IOS_UPPERCASE ?
211 __rw_digits + 36 : __rw_digits;
212
213 const _LLong base = (flags >> _RWSTD_IOS_BASEOFF) - _LLong (1);
214
215 int bits;
216
217 char *end = buf;
218
219 switch (base) {
220
221 case 1: bits = 1; break;
222 case 3: bits = 2; break;
223 case 7:
224 bits = 3;
225 if (i && flags & _RWSTD_IOS_SHOWBASE)
226 *end++ = '0';
227 break;
228
229 case 9:
230 return __rw_dtoa (end, i, flags);
231
232 case 15:
233 bits = 4;
234 if (i && flags & _RWSTD_IOS_SHOWBASE) {
235 *end++ = '0';
236 *end++ = pdigs [33]; // 'X' or 'x'
237 }
238 break;
239
240 case 31: bits = 5; break;
241
242 default:
243 _RWSTD_ASSERT (base >= 0 && base <= _RWSTD_UINT_MAX);
244
245 return __rw_btoa (buf, i, unsigned (base));
246 }
247
248 // maximum number of base-digits
249 const int digits =
250 (_STD::numeric_limits<_ULLong>::digits + bits - 1) / bits;
251
252 int j;
253
254 // skip leading zeros
255 if (i) {
256 for (j = digits - 1; j && !(i & (base << j * bits)); --j);
257 }
258 else
259 j = 0;
260
261 // format the remaining digits
262 do {
263 const int dig = int ((i & (base << j * bits)) >> j * bits);
264
265 _RWSTD_ASSERT (dig >= 0 && dig < 36);
266
267 *end++ = pdigs [dig];
268 } while (j--);
269
270 return end - buf;
271}
272
273
274static inline _RWSTD_SIZE_T
275__rw_itoa (char *buf, _LLong i, unsigned flags)
276{
277 if (10 == flags >> _RWSTD_IOS_BASEOFF)
278 return __rw_dtoa (buf, i, flags);
279
280 return __rw_itoa (buf, _RWSTD_STATIC_CAST (_ULLong, i), flags);
281}
282
283
284#endif // _RWSTD_LONG_LONG
285
286
287static _RWSTD_SIZE_T
288__rw_btoa (char *buf, unsigned long i, unsigned base)
289{
290 _RWSTD_ASSERT (base && base <= 36);
291
292 const _RWSTD_SIZE_T dig = _STD::numeric_limits<unsigned long>::digits + 0U;
293
294 char* end = buf + dig;
295 const char* const begin = end;
296
297 unsigned long tmp;
298 do {
299 tmp = i / base;
300
301 // PA RISC has no integer divide, optimize the modulo operator
302 // this is also faster than computing the modulo on i86, and
303 // faster than calling ldiv()
304 *--end = __rw_digits [i - tmp * base];
305 } while ((i = tmp));
306
307 const _RWSTD_SIZE_T len = begin - end;
308
309 memmove (buf, end, len);
310
311 return len;
312}
313
314
315static inline _RWSTD_SIZE_T
316__rw_dtoa (char *buf, unsigned long i, unsigned flags)
317{
318 // get the maximum number of decimal digits for an unsigned long
319 // with the largest magnitude, plus 1 for the (optional) sign
320 const _RWSTD_SIZE_T dig10 =
321 _STD::numeric_limits<unsigned long>::digits10 + 2U;
322
323 char* end = buf + dig10;
324 const char* const begin = end;
325
326 unsigned long tmp;
327 do {
328 tmp = i / 10;
329
330 // PA RISC has no integer divide, optimize the modulo operator
331 // this is also faster than computing the modulo on i86, and
332 // faster than calling ldiv()
333 *--end = __rw_digits [i - tmp * 10];
334 } while ((i = tmp));
335
336
337 // prepend a sign if necessary
339 *--end = '+';
340
341 // move the contents of the buffer to the beginning
342 const _RWSTD_SIZE_T len = begin - end;
343
344 memmove (buf, end, len);
345
346 return len;
347}
348
349
350static inline _RWSTD_SIZE_T
351__rw_dtoa (char *buf, long i, unsigned flags)
352{
353 if (i < 0) {
354 flags &= ~_RWSTD_IOS_SHOWPOS;
355 *buf++ = '-';
356 return 1 + __rw_dtoa (buf, _RWSTD_STATIC_CAST (unsigned long, -i),
357 flags);
358 }
359
360 return __rw_dtoa (buf, _RWSTD_STATIC_CAST (unsigned long, i), flags);
361}
362
363
364// convert unsigned long to a roman number
365static _RWSTD_SIZE_T
366__rw_utor (char *buf, unsigned long i, unsigned flags)
367{
368 // 01234560123456
369 static const char lit [] = "ivxlcdmIVXLCDM";
370
371 if (0 == i || i > 4999)
372 return __rw_dtoa (buf, i, flags);
373
374 const char* const pdigs = flags & _RWSTD_IOS_UPPERCASE ? lit + 7 : lit;
375
376 const char *begin = buf;
377
378 for (; i >= 1000; i -= 1000)
379 *buf++ = pdigs [6]; // 'M'
380
381 for (unsigned long j = 0, ord = 100; j != 6; j += 2, ord /= 10) {
382
383 unsigned long fact;
384
385 if (i >= (fact = 9 * ord)) {
386 *buf++ = pdigs [4 - j]; // {C,X,I}
387 *buf++ = pdigs [6 - j]; // {M,C,X}
388 i -= fact;
389 }
390 else if (i >= (fact = 5 * ord)) {
391 *buf++ = pdigs [5 - j]; // {D,L,V}
392 for (i -= fact; i >= ord; i -= ord)
393 *buf++ = pdigs [4 - j]; // {C,X,I}
394 }
395 else if (i >= (fact = 4 * ord)) {
396 *buf++ = pdigs [4 - j]; // {C,X,I}
397 *buf++ = pdigs [5 - j]; // {D,L,V}
398 i -= fact;
399 }
400 else {
401 for (; i >= ord; i -= ord)
402 *buf++ = pdigs [4 - j]; // {C,X,I}
403 }
404 }
405
406 return buf - begin;
407}
408
409
410static _RWSTD_SIZE_T
411__rw_itoa (char *buf, unsigned long i, unsigned flags)
412{
413 const char* const pdigs = flags & _RWSTD_IOS_UPPERCASE ?
414 __rw_digits + 36 : __rw_digits;
415
416 const unsigned basemask = (flags >> _RWSTD_IOS_BASEOFF) - 1;
417
418 int bits;
419
420 char *end = buf;
421
422 switch (basemask) {
423 case unsigned (-1): case 9:
424 return __rw_dtoa (end, i, flags);
425
426 case 0:
427 return __rw_utor (end, i, flags);
428
429 case 1: bits = 1; break;
430 case 3: bits = 2; break;
431 case 7:
432 bits = 3;
433 if (i && flags & _RWSTD_IOS_SHOWBASE)
434 *end++ = '0';
435 break;
436
437 case 15:
438 bits = 4;
439 if (i && flags & _RWSTD_IOS_SHOWBASE) {
440 *end++ = '0';
441 *end++ = pdigs [33]; // 'X' or 'x'
442 }
443 break;
444
445 case 31:
446 bits = 5; break;
447
448 default:
449 return __rw_btoa (buf, i, basemask + 1);
450 }
451
452 int j;
453
454 // skip leading zeros
455 if (i) {
456 // maximum number of digits in the given base (basemask + 1)
457 const int digits =
458 (_STD::numeric_limits<unsigned long>::digits + bits - 1) / bits;
459
460 for (j = digits - 1; !(i & (long (basemask) << j * bits)); --j);
461 }
462 else
463 j = 0;
464
465 do {
466 const unsigned dig = unsigned ((i >> (j * bits)) & basemask);
467
468 _RWSTD_ASSERT (dig <= basemask);
469
470 *end++ = pdigs [dig];
471 } while (j--);
472
473 return end - buf;
474}
475
476
477static inline _RWSTD_SIZE_T
478__rw_itoa (char *buf, long i, unsigned flags)
479{
480 if (10 == flags >> _RWSTD_IOS_BASEOFF)
481 return __rw_dtoa (buf, i, flags);
482
483 return __rw_itoa (buf, _RWSTD_STATIC_CAST (unsigned long, i), flags);
484}
485
486
487_RWSTD_EXPORT _RWSTD_SIZE_T
488__rw_put_groups (char **pbuf, _RWSTD_SIZE_T len, _RWSTD_SIZE_T bufsize,
489 const char *end, const char *grouping)
490{
491 _RWSTD_ASSERT (0 != *pbuf);
492 _RWSTD_ASSERT (0 != grouping);
493
494 _RWSTD_UNUSED (bufsize);
495
496 if (end) {
497 // for floats, find the decimal point or one of { 'e', 'E' }
498 end = strchr (*pbuf, '.');
499 if (!end) {
500 // try the comma in case sprintf() was used after
501 // a call setlocale() that changed '.' to ','
502 end = strchr (*pbuf, ',');
503 if (!end)
504 end = strpbrk (*pbuf, "Ee");
505 }
506 }
507
508 if (!end) {
509 // no decimal point for all other types
510 end = *pbuf + len;
511 }
512
513 typedef unsigned char UChar;
514
515 char *pd = *pbuf; // pointer to the integral part (past any prefix)
516
517 if (43 /* '-' or '+' */ == __rw_digit_map [UChar (*pd)])
518 ++pd;
519 else if ('0' == *pd) {
520 ++pd;
521
522 if (33 /* 'X' or 'x' */ == __rw_digit_map [UChar (*pd)])
523 ++pd;
524 }
525
526 _RWSTD_SIZE_T ngrps = 0; // number of complete groups
527 _RWSTD_SIZE_T grplen = 0; // length of complete groups
528
529 // compute the amount of buffer space needed for group separators
530 const char *pg = grouping;
531 for ( ; ; ++ngrps) {
532
533 UChar grp = UChar (*pg);
534
535 if (0 == grp) {
536 // '\0' causes the last grouping to be repeated
537 grp = UChar (pg [-1]);
538 }
539 else if (_RWSTD_CHAR_MAX == grp) {
540 // _RWSTD_CHAR_MAX terminates the grouping algorithm
541 break;
542 }
543 else
544 ++pg;
545
546 if (grplen + grp >= _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, end - pd))
547 break;
548
549 grplen += grp;
550 }
551
552 pg = grouping; // reset to point to the first grouping
553 end += ngrps; // adjust the new position of the decimal point
554 len += ngrps; // adjust the length of buffer
555
556 grplen = *pg++; // length of the first grouping
557
558 const bool no_groups = '\0' == **pbuf;
559
560 // copy buffer onto itself starting with the rightmost digit,
561 // inserting thousands_sep placeholders (';') according to
562 // `grouping' in the integral portion of the number
563 // using ';' rather than ',' to prevent potential collisions
564 // with a comma inserted by sprintf() in some locales
565 for (pd = *pbuf + (len - 1); pd != *pbuf && ngrps; --pd) {
566 if (pd >= end) {
567 // copy the fractional part (if any) of the number
568 *pd = pd [-_RWSTD_STATIC_CAST (_RWSTD_PTRDIFF_T, ngrps)];
569 }
570 else {
571 if ((_RWSTD_SIZE_T)(end - pd) == grplen + 1) {
572 // insert throusands separator and compute
573 // the offset of the next separator
574 *pd = ';';
575 --ngrps;
576
577 if (_RWSTD_CHAR_MAX == *pg)
578 break;
579
580 // '\0' forces the repetition of the last grouping
581 grplen += (*pg ? *pg++ : pg [-1]) + 1;
582 }
583 else {
584 // copy the integral part
585 *pd = pd [-_RWSTD_STATIC_CAST (_RWSTD_PTRDIFF_T, ngrps)];
586 }
587 }
588 }
589
590 if (no_groups) {
591
592 pd = *pbuf;
593
594 // replace each group including the thousands_sep placeholder
595 // in the buffer with its size
596 for (char *ps = *pbuf, *last = *pbuf; ; ++pd) {
597
598 if (pd == *pbuf + len) {
599 // append the size of the last group, set `len', and break
600 *ps++ = char (pd - last);
601 len = ps - *pbuf;
602 break;
603 }
604
605 if (';' == *pd) {
606 // replace group with it size
607 *ps++ = char (pd - last);
608 last = pd + 1;
609 }
610 }
611 }
612
613 return len;
614}
615
616
617static inline void
618__rw_fix_flt (char *&end, _RWSTD_SIZE_T &len,
619 unsigned flags, _RWSTD_STREAMSIZE prec)
620{
621#ifdef _WIN32
622
623 char* beg = end - len;
624
625 // workaround for the STDCXX-2 issue
628 && 2 < len
629 && '0' == beg [0]
630 && ('.' == beg [1] || ',' == beg [1])) {
631
632 // for the 0.0 value the MSVC libc inserts redundant '0' character
633 // when %g format is used in sprintf()
634 const char* ptr;
635 for (ptr = beg + 2; ptr != end && '0' == *ptr; ++ptr) ;
636
637 if (ptr == end) {
638 const _RWSTD_SIZE_T exp_len =
639 0 > prec ? 7 : (1 < prec ? prec + 1 : 2);
640 if (exp_len < len) {
641 end = beg + exp_len;
642 len = exp_len;
643 }
644 }
645 }
646
647 if (len > 5) {
648 // make Win32 output conform to C99 printf() requirements
649 // on the exponent: The exponent always contains at least
650 // two digits, and only as many more digits as necessary
651 // to represent the exponent.
652 if (('e' == end [-5] || 'E' == end [-5]) && '0' == end [-3]) {
653 end [-3] = end [-2];
654 end [-2] = end [-1];
655 --len;
656 --end;
657 }
658 else if ('#' == end [-4]) {
659 // may be #INF or #IND
660 const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
661
662 if ('F' == end [-1]) {
663 // assuming #INF
664 // normalize the format of infinity to conform to C99
665
666 const char str[] = "iInNfF";
667
668 end [-6] = str [cap + 0];
669 end [-5] = str [cap + 2];
670 end [-4] = str [cap + 4];
671 }
672 else {
673 // assuming #IND
674 // normalize the format of NaN to conform to C99
675
676 const char str[] = "nNaA";
677
678 end [-6] = str [cap + 0];
679 end [-5] = str [cap + 2];
680 end [-4] = str [cap + 0];
681 }
682
683 end -= 3;
684 len -= 3;
685 }
686 else if ('#' == end [-5]) {
687 // normalize the format of NaN to conform to C99
688
689 const char str[] = "nNaA";
690
691 const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
692
693 end [-7] = str [cap + 0];
694 end [-6] = str [cap + 2];
695 end [-5] = str [cap + 0];
696 end -= 4;
697 len -= 4;
698 }
699 }
700
701#else
702
703 _RWSTD_UNUSED (prec);
704
705 // normalize the format of infinity and NaN to one of
706 // { INF, inf, NAN, nan, NANQ, nanq, NANS, nans }
707 // for portability
708 char* beg = end - len;
709
710 typedef unsigned char UChar;
711
712 // is there a sign?
713 bool sgn = false;
714
715 if (43 /* '+' or '-' */ == __rw_digit_map [UChar (*beg)]) {
716 sgn = true;
717 ++beg;
718 }
719
720 const char* pstr;
721
722 switch (__rw_digit_map [UChar (*beg)]) {
723
724 case 18 /* 'I' or 'i' */ :
725 pstr = "iInNfF\0\0";
726 len = 3;
727 break;
728
729 case 23 /* 'N' or 'n' */ : {
730
731 // distinguish between quiet and signaling NaN
732
733 // FIXME: do this portably, regardless of printf output
734 // (some libc, such as Solaris, output the same string
735 // for both quiet and signaling NaN; others, such as
736 // AIX, output NaNQ and NaNS, respectively)
737
738 const UChar last = __rw_digit_map [UChar (*(end - 1))];
739 if (26 /* 'Q' or 'q' */ == last) {
740 pstr = "nNaAnNqQ";
741 len = 4;
742 }
743 else if (28 /* 'S' or 's' */ == last) {
744 pstr = "nNaAnNsS";
745 len = 4;
746 }
747 else {
748 pstr = "nNaAnN\0\0";
749 len = 3;
750 }
751 break;
752 }
753
754 default:
755 return;
756 }
757
758 const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
759
760 beg [0] = pstr [cap + 0];
761 beg [1] = pstr [cap + 2];
762 beg [2] = pstr [cap + 4];
763 beg [3] = pstr [cap + 6];
764
765 end = beg + 3 + ('\0' != beg [3]);
766
767 // increase the length by one for the sign
768 if (sgn)
769 ++len;
770
771#endif // _WIN32
772
773}
774
775
776
777_RWSTD_EXPORT _RWSTD_SIZE_T
778__rw_put_num (char **pbuf, _RWSTD_SIZE_T bufsize,
779 unsigned flags, int type, _RWSTD_STREAMSIZE prec,
780 const void *pval, const char *grouping)
781{
782 char fmtbuf [32]; // buffer for stdio format specifier
783 const char *fmt = 0; // stdio format specifier
784 char* const buf = *pbuf; // saved value of *pbuf
785 char *end = 0; // decimal point
786 _RWSTD_SIZE_T len; // length of formatted number
787 _RWSTD_STREAMSIZE fpr; // special case floating point precision
788
789 typedef _RWSTD_SIZE_T SizeT;
790
791 switch (type) {
792
793 case __rw_facet::_C_bool:
795 // no output
796 len = 0;
797 *buf = '\0';
798 break;
799 }
800 // else fall through...
801
802 case __rw_facet::_C_short:
803 case __rw_facet::_C_int:
804 case __rw_facet::_C_long:
805#if defined (__INTEL_COMPILER) && defined (_WIN64)
806# pragma warning (disable: 810)
807#endif
808 len = __rw_itoa (buf, _RWSTD_REINTERPRET_CAST (long, pval), flags);
809#if defined (__INTEL_COMPILER) && defined (_WIN64)
810# pragma warning (default: 810)
811#endif
812 break;
813
814 case __rw_facet::_C_ushort:
815 case __rw_facet::_C_uint:
816 case __rw_facet::_C_ulong:
817 // unsigned output behaves analogously printf() with %u
818 // note that the plus in "%+u" is meaningless (i.e., the
819 // sign is only used in signed conversions; 7.19 6.1, p6
820 // of C99: The result of a signed conversion always begins
821 // with a plus or minus sign.)
822#if defined (__INTEL_COMPILER) && defined (_WIN64)
823# pragma warning (disable: 810)
824#endif
825 len = __rw_itoa (buf, _RWSTD_REINTERPRET_CAST (unsigned long, pval),
827#if defined (__INTEL_COMPILER) && defined (_WIN64)
828# pragma warning (default: 810)
829#endif
830 break;
831
832#ifdef _RWSTD_LONG_LONG
833
834 case __rw_facet::_C_llong:
835 len = __rw_itoa (buf, *(const _LLong*)pval, flags);
836 break;
837
838 case __rw_facet::_C_ullong:
839 len = __rw_itoa (buf, *(const _ULLong*)pval,
841 break;
842
843#endif // _RWSTD_LONG_LONG
844
845 case __rw_facet::_C_float | __rw_facet::_C_ptr: {
846 const float fval = *(const float*)pval;
847 if (!__rw_isfinite (fval)) {
848 len = __rw_fmat_infinite (*pbuf, bufsize, fval, flags);
849 end = *pbuf + len;
850 }
851 else {
852 fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
853 fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
854 flags, fpr);
855 for (; ;) {
856 len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, fval));
857
858 if (len >= bufsize) {
859 if (*pbuf != buf)
860 delete[] *pbuf;
861
862 bufsize = len + 1 ? len + 1 : bufsize * 2;
863 *pbuf = new char [bufsize];
864 }
865 else {
866 _RWSTD_ASSERT (len > 0);
867
868 break;
869 }
870 }
871
872 end = *pbuf + len;
873
874 // fix up output to conform to C99
875 __rw_fix_flt (end, len, flags, fpr);
876 }
877 }
878 break;
879
880 case __rw_facet::_C_double | __rw_facet::_C_ptr: {
881 const double dval = *(const double*)pval;
882 if (!__rw_isfinite (dval)) {
883 len = __rw_fmat_infinite (*pbuf, bufsize, dval, flags);
884 end = *pbuf + len;
885 }
886 else {
887 fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
888 fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
889 flags, fpr);
890
891 for ( ; ; ) {
892 len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, dval));
893
894 if (len >= bufsize) {
895 if (*pbuf != buf)
896 delete[] *pbuf;
897
898 bufsize = len + 1 ? len + 1 : bufsize * 2;
899 *pbuf = new char [bufsize];
900 }
901 else {
902 _RWSTD_ASSERT (len > 0);
903
904 break;
905 }
906 }
907
908 end = *pbuf + len;
909
910 // fix up output to conform to C99
911 __rw_fix_flt (end, len, flags, fpr);
912 }
913 }
914 break;
915
916#ifndef _RWSTD_NO_LONG_DOUBLE
917
918 case __rw_facet::_C_ldouble | __rw_facet::_C_ptr: {
919 const long double ldval = *(const long double*)pval;
920 if (!__rw_isfinite (ldval)) {
921 len = __rw_fmat_infinite (*pbuf, bufsize, ldval, flags);
922 end = *pbuf + len;
923 }
924 else {
925 fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
926 fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
927 flags, fpr);
928
929 for ( ; ; ) {
930 len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, ldval));
931 if (len >= bufsize) {
932 if (*pbuf != buf)
933 delete[] *pbuf;
934
935 bufsize = len + 1 ? len + 1 : bufsize * 2;
936 *pbuf = new char [bufsize];
937 }
938 else {
939 _RWSTD_ASSERT (len > 0);
940
941 break;
942 }
943 }
944
945 end = *pbuf + len;
946
947 // fix up output to conform to C99
948 __rw_fix_flt (end, len, flags, fpr);
949 }
950 }
951 break;
952
953#endif // _RWSTD_NO_LONG_DOUBLE
954
955 case __rw_facet::_C_pvoid:
956 if (pval) {
957 fmt = __rw_get_stdio_fmat (fmtbuf, type, flags, prec);
958 len = SizeT (_SNPRINTF (buf, bufsize, fmt, pval));
959 }
960 else {
961 // prevent GNU libc from formatting null pointers as "(nil)"
962 *buf = '0';
963 len = 1;
964 }
965
966 // prevent grouping
967 grouping = "";
968 break;
969
970 default:
971 _RWSTD_ASSERT (!"logic error: bad type");
972 len = 0; // silence used before initialized warnings
973 }
974
975 if (prec < 0 && flags & _RWSTD_IOS_FIXED) {
976
977 // extension: when ios::fixed is set, negative precision inserts
978 // a decimal_point placeholder `prec' positions before the least
979 // significant digit
980
981 const bool sign = '-' == **pbuf || '+' == **pbuf;
982
983 char* const beg = *pbuf + sign;
984
985 char *src; // first of the digits to move
986 char *dst; // where to move the first digit
987 char *dp; // where to insert the decimal point
988
989 const _RWSTD_PTRDIFF_T ndigs = len - sign;
990
991 _RWSTD_SIZE_T nfill; // the number of 0's to insert
992 _RWSTD_SIZE_T nmove; // the number of digits to move
993
994 if (-prec >= ndigs) {
995
996 // insert 0's in addition to the decimal point
997 // e.g., "1234" with prec == -6 yields "0.01234"
998
999 nmove = ndigs;
1000 nfill = -prec - ndigs + 2;
1001
1002 dst = beg + nfill;
1003 src = beg;
1004 dp = beg + 1;
1005
1006 // adjust the length of the block
1007 len += nfill;
1008 }
1009 else {
1010
1011 // insert decimal point into the string of digits
1012 // e.g., "1234" with prec == -3 yields "1.234"
1013
1014 nfill = 0;
1015 nmove = SizeT (-prec);
1016
1017 src = beg + (ndigs + prec);
1018 dst = src + 1;
1019 dp = src;
1020
1021 ++len; // grow the length
1022 }
1023
1024 // move a block of digits to make room for 0's, if any,
1025 // and the decimal point placeholder
1026 memmove (dst, src, nmove);
1027 memset (beg, '0', nfill);
1028
1029 *dp = '.';
1030 end = *pbuf + len;
1031 }
1032
1033 // insert commas as thousands separators if grouping is required
1034 // integral and floating point types only (i.e., not for pointers)
1035 if (len > 1 && *grouping && _RWSTD_CHAR_MAX != *grouping)
1036 len = __rw_put_groups (pbuf, len, bufsize, end, grouping);
1037
1038 // verify that the buffer hasn't overrun
1039 _RWSTD_ASSERT (len <= bufsize);
1040
1041 return len;
1042}
1043
1044
1045} // namespace __rw
#define i
Definition 17.names.cpp:126
#define ptr
Definition 17.names.cpp:525
#define last
Definition 17.names.cpp:487
#define buf
Definition 17.names.cpp:452
#define j
Definition 17.names.cpp:127
#define tmp
Definition 17.names.cpp:553
#define len
Definition 17.names.cpp:488
#define val
Definition 17.names.cpp:570
#define U
Definition 17.names.cpp:164
#define flags
const int end
volatile double * pd
#define _RWSTD_LONG_LONG
#define _RWSTD_DLLIMPORT
Definition _config.h:391
#define _RWSTD_IOS_FIXED
Definition _defs.h:768
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_IOS_BOOLALPHA
Definition _defs.h:766
#define _RWSTD_IOS_FLOATFIELD
Definition _defs.h:790
#define _RWSTD_IOS_UPPERCASE
Definition _defs.h:780
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _LIBC_THROWS()
Definition _defs.h:1152
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_STREAMSIZE
Definition _defs.h:762
#define _RWSTD_IOS_SHOWBASE
Definition _defs.h:775
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _RWSTD_IOS_BASEOFF
Definition _defs.h:805
#define _RWSTD_IOS_SCIENTIFIC
Definition _defs.h:774
#define _RWSTD_IOS_SHOWPOS
Definition _defs.h:777
const char * str
Definition exec.cpp:170
bool __rw_isfinite(double)
Definition fpclass.h:207
bool __rw_isinf(double)
Definition fpclass.h:211
bool __rw_signbit(double)
Definition fpclass.h:209
bool __rw_isqnan(double)
Definition fpclass.h:215
bool __rw_issnan(double)
Definition fpclass.h:217
bool __rw_isnan(double)
Definition fpclass.h:213
unsigned char UChar
Definition collate.cpp:122
#define _SNPRINTF(buf, size, fmt, arg)
Definition num_put.cpp:48