Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
punct.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30#include <rw/_defs.h>
31
32#include <locale.h> // for lconv, localeconv(), setlocale()
33#include <stdio.h> // for sprintf()
34#include <stdlib.h> // for mbstowcs()
35#include <string.h> // for memcpy()
36
37#include <ios> // for ios_base, needed by <rw/_punct.h>
38#include <memory> // for operator new() and delete()
39
40#include "access.h"
41
42#include <loc/_localedef.h>
43#include <loc/_moneypunct.h>
44#include <loc/_numpunct.h>
45
46#include <rw/_error.h>
47
48#include "setlocale.h"
49#include "punct.h"
50
51
52#if defined (_RWSTD_MSVC) && defined (_WIN64)
53 // shut up MSVC/Win64 complaints about possible loss of data
54# pragma warning (disable: 4244)
55#endif // MSVC/Win64
56
57
59
60
61static inline void
62__rw_copy (void *dst, const void *src, size_t n)
63{
64 memcpy (dst, src, n);
65}
66
67static inline void
68__rw_widen (void *dst, const void *src, size_t n)
69{
70 mbstowcs (_RWSTD_STATIC_CAST (wchar_t*, dst),
71 _RWSTD_STATIC_CAST (const char*, src), n);
72}
73
74
75static const void*
76__rw_get_numpunct (const __rw_facet *pfacet, int flags)
77{
78 const int member = flags & ~(__rw_mon | __rw_wide | __rw_intl);
79 const bool winx = !!(flags & __rw_wide); // wide or narrow index
80 const void *pdata = pfacet->_C_data (); // mapped locale database
81
82 if (pdata) {
83
84 const __rw_punct_t* const pun =
85 _RWSTD_STATIC_CAST (const __rw_punct_t*, pdata);
86
87 const __rw_num_t *num;
88
89 switch (member) {
90
91 case __rw_dp: return pun->decimal_point (winx);
92 case __rw_ts: return pun->thousands_sep (winx);
93 case __rw_gr: return pun->grouping ();
94
95 case __rw_tn:
96 num = _RWSTD_STATIC_CAST (const __rw_num_t*, pun->get_ext ());
98 return num->truename (winx);
99
100 case __rw_fn:
101 num = _RWSTD_STATIC_CAST (const __rw_num_t*, pun->get_ext ());
103 return num->falsename (winx);
104
105 default: _RWSTD_ASSERT (!"bad discriminant");
106 }
107
108 return 0;
109 }
110 else if (0 == __rw_access::_C_get_name (*pfacet)) { // "C" locale
111
112 static const void* const cdata[] = {
113 ".", L".", ",", L",", "", L"", "true", L"true", "false", L"false"
114 };
115
116 switch (member) {
117
118 case __rw_dp: return cdata [0 + winx]; // 22.2.3.1.2, p1
119 case __rw_ts: return cdata [2 + winx]; // 22.2.3.1.2, p2
120 case __rw_gr: return cdata [4 + winx]; // 22.2.3.1.2, p3
121 case __rw_tn: return cdata [6 + winx]; // 22.2.3.1.2, p4
122 case __rw_fn: return cdata [8 + winx];
123
124 default: _RWSTD_ASSERT (!"bad discriminant");
125 }
126
127 return 0;
128 }
129
130 const char* const locname = __rw_access::_C_get_name (*pfacet) ?
131 __rw_access::_C_get_name (*pfacet) : "C";
132
133 // set all categories -- need LC_NUMERIC and LC_CTYPE
134 const __rw_setlocale clocale (locname, _RWSTD_LC_ALL);
135
136 if (pfacet->_C_data ()) {
137 // check to see if another thread may have set _C_data()
138 // while we were waiting for the lock in __rw_setlocale
139 // ctor above and, if so, call self recursively on the
140 // already initialized `impdata'
141 return __rw_get_numpunct (pfacet, flags);
142 }
143
144 // get the lconv data
145 const lconv* const pconv = localeconv ();
146 if (!pconv)
147 __rw_throw (_RWSTD_ERROR_LOCALE_BAD_NAME, locname);
148
149 // be prepared to handle (non-conforming) null pointers
150 // (e.g., AIX -- see bug #558)
151 const char* const grp = pconv->grouping ? pconv->grouping : "";
152 const char* const dp = pconv->decimal_point ? pconv->decimal_point : "";
153 const char* const ts = pconv->thousands_sep ? pconv->thousands_sep : "";
154
155 // the size of the narrow grouping string in bytes
156 const size_t grsz = strlen (grp) + 1;
157
158 // compute the sizes of all members in bytes
159 size_t dpsz = strlen (dp) + 1;
160 size_t tssz = strlen (ts) + 1;
161 size_t tnsz = sizeof "true";
162 size_t fnsz = sizeof "false";
163
164 if (winx) {
165 // adjust for wide characters
166 dpsz *= sizeof (wchar_t);
167 tssz *= sizeof (wchar_t);
168 tnsz *= sizeof (wchar_t);
169 fnsz *= sizeof (wchar_t);
170 }
171
172 // compute the actual size of the variable size structure
173 const size_t size =
174 sizeof (__rw_punct_t)
175 + sizeof (__rw_num_t)
176 + sizeof (size_t) // maximum padding for alignment
177 + grsz + dpsz + tssz + tnsz + fnsz;
178
179 // allocate variable size structure(s)
180 __rw_punct_t* const pun =
181 _RWSTD_STATIC_CAST (__rw_punct_t*, ::operator new (size));
182
183 // compute offsets into the varaiable size structure
184 pun->decimal_point_off [winx] = 0;
185 pun->thousands_sep_off [winx] = pun->decimal_point_off [winx] + int (dpsz);
186
187 // point widen to a wrapper for mbstowcs() for wchar_t or memcpy otherwise
188 void (*widen)(void*, const void*, size_t) =
189 winx ? __rw_widen : __rw_copy;
190
191 // copy strings from lconv data members to the varaiable size structure
192 char* s = _RWSTD_REINTERPRET_CAST (char*, pun + 1);
193
194 widen (s + pun->decimal_point_off [winx], dp, dpsz);
195 widen (s + pun->thousands_sep_off [winx], ts, tssz);
196
197 // set the offset of the extended punctuation data
198 pun->punct_ext_off = pun->thousands_sep_off [winx] + int (tssz);
199
200 // adjust alignment
201 const size_t misalign = pun->punct_ext_off % sizeof (size_t);
202 if (misalign)
203 pun->punct_ext_off += int (sizeof (size_t) - misalign);
204
205 s = _RWSTD_REINTERPRET_CAST (char*, pun + 1) + pun->punct_ext_off;
206
207 __rw_num_t* const num = _RWSTD_REINTERPRET_CAST (__rw_num_t*, s);
208
209 s += sizeof *num;
210
211 // invalidate members (offsets) by setting them to 0xff
212 memset (num, ~0, sizeof *num);
213
214 num->truename_off [winx] = 0;
215 num->falsename_off [winx] = num->truename_off [winx] + int (tnsz);
216
217 widen (s + num->truename_off [winx], "true", tnsz);
218 widen (s + num->falsename_off [winx], "false", fnsz);
219
220 // place narrow grouping string last to avoid alignment issues
221 pun->grouping_off =
222 _RWSTD_STATIC_CAST (_RWSTD_UINT32_T,
223 pun->punct_ext_off + sizeof *num + num->falsename_off [winx] + fnsz);
224
225 memcpy (s + num->falsename_off [winx] + fnsz, grp, grsz);
226
227 // set `impdata' and `impsize' (facet base dtor will delete)
228 __rw_access::_C_get_impdata (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
229 pun;
230
231 __rw_access::_C_get_impsize (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
232 (size_t)(-1);
233
234 // call self recursively on already initialized `impdata'
235 return __rw_get_numpunct (pfacet, flags);
236}
237
238
241static const void*
242__rw_get_moneypunct (const __rw_facet *pfacet, int flags)
243{
244 const int member = flags & ~(__rw_mon | __rw_wide | __rw_intl);
245 const bool winx = !!(flags & __rw_wide); // wide or narrow index
246 const bool intl = !!(flags & __rw_intl); // international or domestic
247 const void *pdata = pfacet->_C_data (); // mapped locale database
248
249 if (pdata) {
250
251 const __rw_punct_t* const pun =
252 _RWSTD_STATIC_CAST (const __rw_punct_t*, pdata);
253
254 const __rw_mon_t *mon;
255
256 switch (member) {
257 case __rw_dp: return pun->decimal_point (winx);
258 case __rw_ts: return pun->thousands_sep (winx);
259 case __rw_gr: return pun->grouping ();
260
261 }
262
263 // get extended data
264 mon = _RWSTD_STATIC_CAST (const __rw_mon_t*, pun->get_ext ());
265 _RWSTD_ASSERT (mon);
266
267 typedef unsigned char UChar;
268
269 switch (member) {
270
271 case __rw_cs: return mon->curr_symbol (intl, winx);
272 case __rw_ps: return mon->positive_sign (winx);
273 case __rw_ns: return mon->negative_sign (winx);
274
275 case __rw_pf: return mon->pos_format [intl];
276 case __rw_nf: return mon->neg_format [intl];
277
278 case __rw_fd:
279 return _RWSTD_REINTERPRET_CAST (void*, (size_t)
280 UChar (mon->frac_digits [intl]));
281
282 default: _RWSTD_ASSERT (!"bad discriminant");
283 }
284
285 return 0;
286 }
287 else if (0 == __rw_access::_C_get_name (*pfacet)) { // "C" locale
288
289 static const void* const cdata[] = {
290 ".", L".", ",", L",", "", L"", "", L"", "", L"",
291 "", L"", "", L"", "\2\3\0\4", "\2\3\0\4",
292 };
293
294 switch (member) {
295
296 case __rw_dp: return cdata [0 + winx];
297 case __rw_ts: return cdata [2 + winx];
298 case __rw_gr: return cdata [4 + winx];
299 case __rw_cs: return cdata [6 + winx + 2 * intl];
300 case __rw_ps: return cdata [10 + winx];
301 case __rw_ns: return cdata [12 + winx];
302 case __rw_pf: return cdata [14];
303 case __rw_nf: return cdata [15];
304
305 // the number of fractional digits in the "C" locale is not specified
306 case __rw_fd: return 0; // no fractional digits
307
308 default: _RWSTD_ASSERT (!"bad discriminant");
309 }
310
311 return 0;
312 }
313
314 const char* const locname = __rw_access::_C_get_name (*pfacet) ?
315 __rw_access::_C_get_name (*pfacet) : "C";
316
317 // set all categories -- need LC_NUMERIC and LC_CTYPE
318 const __rw_setlocale clocale (locname, _RWSTD_LC_ALL);
319
320 if (pfacet->_C_data ()) {
321 // check to see if another thread may have set _C_data()
322 // while we were waiting for the lock in __rw_setlocale
323 // ctor above and, if so, call self recursively on the
324 // already initialized `impdata'
325 return __rw_get_moneypunct (pfacet, flags);
326 }
327
328 // get the lconv data
329 const lconv* const pconv = localeconv ();
330 if (!pconv)
331 __rw_throw (_RWSTD_ERROR_LOCALE_BAD_NAME, locname);
332
333 _RWSTD_ASSERT (pconv->mon_grouping);
334 _RWSTD_ASSERT (pconv->mon_decimal_point);
335 _RWSTD_ASSERT (pconv->mon_thousands_sep);
336
337 // the size of the narrow grouping string in bytes
338 const size_t grsz = strlen (pconv->mon_grouping) + 1;
339
340 // compute the sizes of all members in bytes
341 size_t dpsz = strlen (pconv->mon_decimal_point) + 1;
342 size_t tssz = strlen (pconv->mon_thousands_sep) + 1;
343 size_t pssz = strlen (pconv->positive_sign) + 1;
344 size_t nssz = strlen (pconv->negative_sign) + 1;
345
346 const char* const cs = intl ? pconv->int_curr_symbol
347 : pconv->currency_symbol;
348
349 size_t cssz = strlen (cs) + 1;
350
351 if (winx) {
352 // adjust for wide characters
353 dpsz *= sizeof (wchar_t);
354 tssz *= sizeof (wchar_t);
355 pssz *= sizeof (wchar_t);
356 nssz *= sizeof (wchar_t);
357 cssz *= sizeof (wchar_t);
358 }
359
360 // compute the actual size of the variable size structure
361 const size_t size =
362 sizeof (__rw_punct_t)
363 + sizeof (__rw_mon_t)
364 + sizeof (size_t) // maximum padding for alignment
365 + grsz + dpsz + tssz + pssz + nssz + cssz;
366
367 // allocate variable size structure(s)
368 __rw_punct_t* const pun =
369 _RWSTD_STATIC_CAST (__rw_punct_t*, ::operator new (size));
370
371 // compute offsets into the varaiable size structure
372 pun->decimal_point_off [winx] = 0;
373 pun->thousands_sep_off [winx] = pun->decimal_point_off [winx] + int (dpsz);
374
375 // point widen to a wrapper for mbstowcs() for wchar_t or memcpy otherwise
376 void (*widen)(void*, const void*, size_t) =
377 winx ? __rw_widen : __rw_copy;
378
379 // copy strings from lconv data members to the varaiable size structure
380 char* s = _RWSTD_REINTERPRET_CAST (char*, pun + 1);
381
382 widen (s + pun->decimal_point_off [winx], pconv->mon_decimal_point, dpsz);
383 widen (s + pun->thousands_sep_off [winx], pconv->mon_thousands_sep, tssz);
384
385 // set the offset of the extended punctuation data
386 pun->punct_ext_off = pun->thousands_sep_off [winx] + int (tssz);
387
388 // adjust alignment
389 const size_t misalign = pun->punct_ext_off % sizeof (size_t);
390 if (misalign)
391 pun->punct_ext_off += int (sizeof (size_t) - misalign);
392
393 s = _RWSTD_REINTERPRET_CAST (char*, pun + 1) + pun->punct_ext_off;
394
395 __rw_mon_t* const mon = _RWSTD_REINTERPRET_CAST (__rw_mon_t*, s);
396
397 s += sizeof *mon;
398
399 // invalidate members (offsets) by setting them to 0xff
400 memset (mon, ~0, sizeof *mon);
401
402 mon->positive_sign_off [winx] = 0;
403 mon->negative_sign_off [winx] = mon->positive_sign_off [winx] + int (pssz);
404
405 widen (s + mon->positive_sign_off [winx], pconv->positive_sign, pssz);
406 widen (s + mon->negative_sign_off [winx], pconv->negative_sign, nssz);
407
408 mon->curr_symbol_off [intl][winx] =
409 mon->negative_sign_off [winx] + int (nssz);
410
411 widen (s + mon->curr_symbol_off [intl][winx], cs, cssz);
412
413 pun->grouping_off =
414 _RWSTD_STATIC_CAST (_RWSTD_UINT32_T,
415 pun->punct_ext_off + sizeof *mon
416 + mon->curr_symbol_off [intl][winx] + cssz);
417
418 // place narrow grouping string last to avoid alignment issues
419 memcpy (s + mon->curr_symbol_off [intl][winx] + cssz,
420 pconv->mon_grouping, grsz);
421
422 mon->frac_digits [0] = pconv->frac_digits;
423 mon->frac_digits [1] = pconv->int_frac_digits;
424
425 // initialize domestic C90 formats
426 mon->p_cs_precedes [0] = pconv->p_cs_precedes;
427 mon->n_cs_precedes [0] = pconv->n_cs_precedes;
428 mon->p_sep_by_space [0] = pconv->p_sep_by_space;
429 mon->n_sep_by_space [0] = pconv->n_sep_by_space;
430 mon->p_sign_posn [0] = pconv->p_sign_posn;
431 mon->n_sign_posn [0] = pconv->n_sign_posn;
432
433#ifndef _RWSTD_NO_LCONV_INT_FMAT
434
435 // copy international formats from C99 members
436 mon->p_cs_precedes [1] = pconv->int_p_cs_precedes;
437 mon->n_cs_precedes [1] = pconv->int_n_cs_precedes;
438 mon->p_sep_by_space [1] = pconv->int_p_sep_by_space;
439 mon->n_sep_by_space [1] = pconv->int_n_sep_by_space;
440 mon->p_sign_posn [1] = pconv->int_p_sign_posn;
441 mon->n_sign_posn [1] = pconv->int_n_sign_posn;
442
443#else // if defined (_RWSTD_NO_LCONV_INT_FMAT)
444
445 // copy international formats from local members
446 mon->p_cs_precedes [1] = mon->p_cs_precedes [0];
447 mon->n_cs_precedes [1] = mon->n_cs_precedes [0];
448 mon->p_sep_by_space [1] = mon->p_sep_by_space [0];
449 mon->n_sep_by_space [1] = mon->n_sep_by_space [0];
450 mon->p_sign_posn [1] = mon->p_sign_posn [0];
451 mon->n_sign_posn [1] = mon->n_sign_posn [0];
452
453#endif // _RWSTD_NO_LCONV_INT_FMAT
454
455 enum {
456 // for syntactic convenience
457 none = _STD::money_base::none,
458 space = _STD::money_base::space,
459 symbol = _STD::money_base::symbol,
460 sign = _STD::money_base::sign,
461 value = _STD::money_base::value
462 };
463
464 static const _STD::money_base::pattern pat[] = {
465
466 // cs_precedes [0..1]:
467 //
468 // An integer set to 1 if the currency_symbol precedes the value
469 // for a monetary value, and set to 0 if the symbol succeeds
470 // the value.
471
472 // sep_by_space [0..2]:
473 //
474 // 0 No space separates the currency_symbol from the value for
475 // a monetary value.
476 // 1 If the currency symbol and sign string are adjacent, a space
477 // separates them from the value; otherwise, a space separates
478 // the currency symbol from the value.
479 // 2 If the currency symbol and sign string are adjacent, a space
480 // separates them; otherwise, a space separates the sign string
481 // from the value.
482
483 // sign_posn [0..4]:
484 //
485 // An integer set to a value indicating the positioning of the
486 // positive_sign for a monetary value. The following integer
487 // values shall be recognized:
488 //
489 // 0 Parentheses enclose the value and the currency_symbol.
490 // 1 The sign string precedes the value and the currency_symbol.
491 // 2 The sign string succeeds the value and the currency_symbol.
492 // 3 The sign string immediately precedes the currency_symbol.
493 // 4 The sign string immediately succeeds the currency_symbol.
494
495 // +-------- cs_precedes
496 // |+----- sep_by_space
497 // ||+-- sign_posn
498 // |||
499 // VVV .... - 1 $ . // pattern
500 /* 000: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
501 /* 001: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
502 /* 002: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
503 /* 003: 1-$. */ { { value, sign, symbol, none } }, // "\4\3\2\0"
504 /* 004: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
505
506 /* 010: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
507 /* 011: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
508 /* 012: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
509 /* 013: 1 -$ */ { { value, space, sign, symbol } }, // "\4\3\3\2"
510 /* 014: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
511
512 /* 020: - 1$ */ { { sign, space, value, symbol } }, // "\3\1\4\2"
513 /* 021: - 1$ */ { { sign, space, value, symbol } }, // "\3\1\4\2"
514 /* 022: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
515 /* 023: 1- $ */ { { value, sign, space, symbol } }, // "\4\3\1\2"
516 /* 024: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
517
518 /* 100: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
519 /* 101: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
520 /* 102: $1-. */ { { symbol, value, sign, none } }, // "\2\4\3\0"
521 /* 103: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
522 /* 104: $-1. */ { { symbol, sign, value, none } }, // "\2\3\4\0"
523
524 /* 110: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
525 /* 111: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
526 /* 112: $ 1- */ { { symbol, space, value, sign } }, // "\2\1\4\3"
527 /* 113: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
528 /* 114: $- 1 */ { { symbol, sign, space, value } }, // "\2\3\1\4"
529
530 /* 120: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
531 /* 121: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
532 /* 122: $1 - */ { { symbol, value, space, sign } }, // "\2\4\1\3"
533 /* 123: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
534 /* 124: $ -1 */ { { symbol, space, sign, value } } // "\2\1\3\4"
535 };
536
537 size_t inx = size_t (mon->p_cs_precedes [intl]) * (3U * 5U)
538 + size_t (mon->p_sep_by_space [intl]) * 5U
539 + size_t (mon->p_sign_posn [intl]);
540
541 if (inx < sizeof pat / sizeof *pat)
542 memcpy (mon->pos_format [intl], pat + inx, sizeof *pat);
543 else
544 memset (mon->pos_format [intl], none, sizeof *pat);
545
546 inx = size_t (mon->n_cs_precedes [intl]) * (3U * 5U)
547 + size_t (mon->n_sep_by_space [intl]) * 5U
548 + size_t (mon->n_sign_posn [intl]);
549
550 if (inx < sizeof pat / sizeof *pat)
551 memcpy (mon->neg_format [intl], pat + inx, sizeof *pat);
552 else
553 memset (mon->neg_format [intl], none, sizeof *pat);
554
555 // set `impdata' and `impsize' (facet base dtor will delete)
556 __rw_access::_C_get_impdata (*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
557 pun;
558
559 __rw_access::_C_get_impsize(*_RWSTD_CONST_CAST (__rw_facet*, pfacet)) =
560 (size_t)(-1);
561
562 // call self recursively on already initialized `impdata'
563 return __rw_get_moneypunct (pfacet, flags);
564}
565
566
569/* _RWSTD_SPECIALIZED_FUNCTION */ _RWSTD_EXPORT
570const char*
571__rw_get_punct(const __rw_facet *pfacet, int flags, char)
572{
573 typedef const char *CPChar;
574
575 if (flags & __rw_mon)
576 return CPChar (__rw_get_moneypunct (pfacet, flags & ~__rw_mon));
577
578 return CPChar (__rw_get_numpunct (pfacet, flags));
579}
580
581
582#ifndef _RWSTD_NO_WCHAR_T
583
584/* _RWSTD_SPECIALIZED_FUNCTION */ _RWSTD_EXPORT
585const wchar_t*
586__rw_get_punct(const __rw_facet *pfacet, int flags, wchar_t)
587{
588 flags |= __rw_wide;
589
590 typedef const wchar_t *CPWChar;
591
592 if (flags & __rw_mon)
593 return CPWChar (__rw_get_moneypunct (pfacet, flags & ~__rw_mon));
594
595 return CPWChar (__rw_get_numpunct (pfacet, flags));
596}
597
598#endif // _RWSTD_NO_WCHAR_T
599
600
601const char*
602__rw_get_stdio_fmat (char buf [32], int type, unsigned fmtflags,
604{
605 char *pbuf = buf;
606
607 // format of the specifier:
608 // "%[+][#](.[0-9]*)(h|l|L|LL)(o|x|X|i|d|e|E|f|F|g|G|p)"
609
610 *pbuf++ = '%';
611
612 if (fmtflags & _RWSTD_IOS_SHOWPOS)
613 *pbuf++ = '+';
614
615 if (type & __rw_facet::_C_floating) {
616 if (fmtflags & _RWSTD_IOS_SHOWPOINT)
617 *pbuf++ = '#';
618
619 // follows resolution of lwg issue 231
620 if (0 <= prec) {
621
622 // 7.19.6.1, p5 of C99 specifies that, when given using the
623 // asterisk, negative precision is treated the same as if
624 // it were omitted; treat negative precision the same here
625 pbuf += sprintf (pbuf, ".%ld", long (prec));
626 }
627 }
628 else if (fmtflags & _RWSTD_IOS_SHOWBASE)
629 *pbuf++ = '#';
630
631 enum {
632 // for convenience
633 Short = __rw_facet::_C_ushort & __rw_facet::_C_typemask,
634 Long = __rw_facet::_C_ulong & __rw_facet::_C_typemask,
635 LLong = __rw_facet::_C_ullong & __rw_facet::_C_typemask,
636 Double = __rw_facet::_C_double & __rw_facet::_C_typemask,
637 LDouble = __rw_facet::_C_ldouble & __rw_facet::_C_typemask
638 };
639
640 const int basetype = type & __rw_facet::_C_typemask;
641
642 switch (basetype) {
643
644 case Short: *pbuf++ = 'h'; break;
645 case Long:
646 case Double:
647 *pbuf++ = 'l';
648 break;
649
650 case LDouble: *pbuf++ = 'L'; break;
651
652 case LLong:
653
654#ifdef _RWSTD_LLONG_PRINTF_PREFIX
655
656 memcpy (pbuf, _RWSTD_LLONG_PRINTF_PREFIX,
657 sizeof _RWSTD_LLONG_PRINTF_PREFIX - 1);
658 pbuf += sizeof _RWSTD_LLONG_PRINTF_PREFIX - 1;
659
660#else
661
662 _RWSTD_ASSERT (!"long long printf prefix not configured");
663
664#endif // _RWSTD_LLONG_PRINTF_PREFIX
665
666 break;
667 }
668
669 if (type & __rw_facet::_C_floating) {
670
671 switch (fmtflags & _RWSTD_IOS_FLOATFIELD) {
672 case _RWSTD_IOS_FIXED:
673 *pbuf++ = 'f';
674 break;
675
677 *pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'E' : 'e';
678 break;
679
680 default:
681 *pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'G' : 'g';
682 }
683 }
684 else if (type == __rw_facet::_C_pvoid)
685 *pbuf++ = 'p';
686 else if (type == __rw_facet::_C_bool && fmtflags & _RWSTD_IOS_BOOLALPHA)
687 --pbuf; // empty format indicates bool
688 else {
689 switch (fmtflags & _RWSTD_IOS_BASEFIELD) {
690 case _RWSTD_IOS_OCT: *pbuf++ = 'o'; break;
691 case _RWSTD_IOS_DEC: *pbuf++ = 'd'; break;
692 case _RWSTD_IOS_HEX:
693 *pbuf++ = fmtflags & _RWSTD_IOS_UPPERCASE ? 'X' : 'x';
694 break;
695 default:
696 *pbuf++ = 'i';
697
698 }
699 }
700
701 *pbuf++ = '\0';
702
703 _RWSTD_ASSERT (pbuf - buf < 32);
704
705 return buf;
706}
707
708
709} // namespace __rw
#define buf
Definition 17.names.cpp:452
#define s
#define n
Definition 17.names.cpp:130
#define inx
Definition 17.names.cpp:484
#define num
Definition 17.names.cpp:505
const char * widen(char *dst, const char *src)
#define flags
T value(const T &val)
@ Long
#define LLong
unsigned short wchar_t
#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_BASEFIELD
Definition _defs.h:796
#define _RWSTD_IOS_DEC
Definition _defs.h:767
#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_STATIC_CAST(T, x)
Definition _defs.h:534
#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_SCIENTIFIC
Definition _defs.h:774
#define _RWSTD_IOS_OCT
Definition _defs.h:772
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
#define _RWSTD_IOS_HEX
Definition _defs.h:769
#define _RWSTD_IOS_SHOWPOS
Definition _defs.h:777
#define _RWSTD_IOS_SHOWPOINT
Definition _defs.h:776
#define _RWSTD_ERROR_LOCALE_BAD_NAME
Definition _error.h:105
unsigned char UChar
Definition collate.cpp:122