Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
_money_put.cc
Go to the documentation of this file.
1
29#include <streambuf>
30#include <loc/_moneypunct.h>
31#include <loc/_ctype.h>
32
33
35
36_RWSTD_EXPORT _RWSTD_SIZE_T
37__rw_put_num (char**, _RWSTD_SIZE_T, unsigned, int, _RWSTD_STREAMSIZE,
38 const void*, const char*);
39
40_RWSTD_EXPORT _RWSTD_SIZE_T
41__rw_put_groups (char **, _RWSTD_SIZE_T, _RWSTD_SIZE_T,
42 const char*, const char*);
43
44} // namespace __rw
45
46
48
49
50template <class _CharT, class _OutputIter>
51_RW::__rw_facet_id money_put<_CharT, _OutputIter>::id;
52
53
54// outlined to avoid generating a vtable in each translation unit
55// that uses the class
56template <class _CharT, class _OutputIter>
57/* virtual */ money_put<_CharT, _OutputIter>::
58~money_put () /* nothrow */
59{
60 // no-op
61}
62
63
64template <class _CharT, class _OutputIter>
65/* private */ typename money_put<_CharT, _OutputIter>::iter_type
66money_put<_CharT, _OutputIter>::
67_C_put (iter_type __it, int __opts, ios_base &__flags, char_type __fill,
68 const char_type *__s, _RWSTD_SIZE_T __n, int __fd,
69 const char *__groups, _RWSTD_SIZE_T __ngroups) const
70{
71 // static const arrays of pointers to moneypunct<charT, Intl> members
72 // to avoid "if (intl)" conditionals when retrieving punct values
73
74 const bool __intl = 0 != (__opts & _C_intl);
75 const bool __num = 0 != (__opts & _C_ldbl);
76
77 typedef moneypunct<_CharT, false> _Punct0;
78 typedef moneypunct<_CharT, true> _Punct1;
79
80 const _Punct0* __pun0;
81 const _Punct1* __pun1;
82
83#ifdef __GNUG__
84 // silence bogus gcc -Wuninitialized warning:
85 // object may be used uninitialized in this function
86 // while avoiding bogus HP aCC/cadvise warning 20200:
87 // potential null pointer dereference
88 __pun0 = 0;
89 __pun1 = 0;
90#endif // gcc
91
92 if (__intl) {
93 __pun1 = &_RWSTD_USE_FACET (_Punct1, __flags.getloc ());
94 }
95 else {
96 __pun0 = &_RWSTD_USE_FACET (_Punct0, __flags.getloc ());
97 }
98
99 const ctype<_CharT> &__ctp =
100 _RWSTD_USE_FACET (ctype<_CharT>,__flags.getloc ());
101
102 const char __signchar = __ctp.narrow (*__s, '\0');
103
104 money_base::pattern __fmat; // negative or positive format
105 string_type __sign; // negative or positive sign
106
107 if ('-' == __signchar) {
108 if (__intl) {
109 __fmat = __pun1->neg_format ();
110 __sign = __pun1->negative_sign ();
111 }
112 else {
113 __fmat = __pun0->neg_format ();
114 __sign = __pun0->negative_sign ();
115 }
116 ++__s;
117 --__n;
118 }
119 else {
120 if (__intl) {
121 __fmat = __pun1->pos_format ();
122 __sign = __pun1->positive_sign ();
123 }
124 else {
125 __fmat = __pun0->pos_format ();
126 __sign = __pun0->positive_sign ();
127 }
128 if ('+' == __signchar) {
129 ++__s;
130 --__n;
131 }
132 }
133
134 // optional currency sumbol
135 const string_type __curr = (__flags.flags () & _RWSTD_IOS_SHOWBASE) ?
136 __intl ? __pun1->curr_symbol () : __pun0->curr_symbol ()
137 : string_type ();
138
139 // size of fractional and integral parts, respectively, to output
140 long __dint = long (__n - __fd);
141
142 // must have at least one group (even if there are no thousands_sep)
143 _RWSTD_ASSERT (__ngroups > 0);
144
145 // adjust padding by the sizes of each component, including the
146 // number of thousands separators to be inserted
147 long __pad = long (
148 __flags.width () - __curr.size () - __sign.size ()
149 - !__dint - !!__fd - (__dint > 0 ? __dint : -__dint) - __fd
150 - ( money_base::space == __fmat.field [1]
151 || money_base::space == __fmat.field [2])
152 - (__ngroups - 1));
153
154 const int __adj = __flags.flags () & _RWSTD_IOS_ADJUSTFIELD;
155
156 if (__adj != _RWSTD_IOS_INTERNAL && __adj != _RWSTD_IOS_LEFT) {
157
158 for (; __pad > 0; --__pad, ++__it)
159 *__it = __fill;
160 }
161
162 for (_RWSTD_SIZE_T __i = 0, __j; __i != sizeof __fmat; ++__i) {
163
164 switch (__fmat.field [__i]) {
165
166 case money_base::symbol: // exactly one occurrence required
167 for (__j = 0; __j != __curr.size (); ++__j, ++__it)
168 *__it = __curr [__j];
169 break;
170
171 case money_base::sign: // exactly one occurrence required
172 if (__sign.size ()) {
173 // first character of sign only
174 *__it = __sign [0];
175 ++__it;
176 }
177 break;
178
179 case money_base::space: // optional (required if none not present)
180 // 22.2.6.3, p1: the value space, if present,
181 // is neither first nor last.
182
183 _RWSTD_REQUIRES (0 != __i && sizeof __fmat != __i - 1,
185 _RWSTD_FUNC ("std::num_put<>::do_put()")));
186
187 // an ordinary space, not `fill', is required here
188 // will precede any required padding
189 *__it = __ctp.widen (' ');
190 ++__it;
191
192 case money_base::none: // optional (required if space not present)
193 // 22.2.6.3, p1: the value none, if present, is not first
194
195 _RWSTD_REQUIRES (0 != __i,
197 _RWSTD_FUNC ("std::num_put<>::do_put()")));
198
200 && sizeof __fmat != __i - 1)
201 for (; __pad > 0; --__pad, ++__it)
202 *__it = __fill;
203
204 break;
205
206 case money_base::value: { // exactly one occurrence required
207
208 if (__dint < 0 || 0 == __dint && __fd > 0) {
209 const char_type __zero = __ctp.widen ('0');
210
211 // insert leading zero and decimal point
212 *__it = __zero;
213 ++__it;
214
215 *__it = __intl ?
216 __pun1->decimal_point () : __pun0->decimal_point ();
217 ++__it;
218
219 // insert leading fractional zeros
220 for (; __dint++; ++__it)
221 *__it = __zero;
222
223 // prevent insertion of the decimal point below
224 __dint = -1;
225 }
226
227 _RWSTD_SIZE_T __grplen = 0;
228
229 for (const char_type *__e = __s + __n; __s != __e; ++__it, ++__s) {
230
231 if (!__num && !__ctp.is (ctype_base::digit, *__s))
232 break;
233
234 typedef unsigned char _UChar;
235
236 if (0 < __dint) {
237
238 _RWSTD_ASSERT (0 != __groups);
239
240 if (*__groups && __grplen == _UChar (*__groups)) {
241 *__it = __intl ? __pun1->thousands_sep ()
242 : __pun0->thousands_sep ();
243 __grplen = 0;
244 ++__groups;
245 ++__it;
246 }
247 }
248 else if (0 == __dint) {
249 *__it = __intl ? __pun1->decimal_point ()
250 : __pun0->decimal_point ();
251 ++__it;
252 }
253
254 --__dint;
255 ++__grplen;
256
257 switch (*__s) {
258 // replace either the period or the comma with the
259 // decimal point in case a setlocale() call made by
260 // the program changed the default '.' to ','
261 case '.':
262 case ',':
263 *__it = __intl ? __pun1->decimal_point ()
264 : __pun0->decimal_point ();
265 break;
266
267 case ';':
268 *__it = __intl ? __pun1->thousands_sep ()
269 : __pun0->thousands_sep ();
270 break;
271
272 default: *__it = *__s;
273 }
274 }
275
276 break;
277 }
278 }
279 }
280
281 // output the remaining characters of sign (if any)
282 for (_RWSTD_SIZE_T __k = 1; __k < __sign.size (); ++__k, ++__it)
283 *__it = __sign [__k];
284
285 // left ajustment
286 for (; __pad > 0; --__pad, ++__it)
287 *__it = __fill;
288
289 // 22.2.6.2.2, p1: reset width()
290 __flags.width (0);
291
292 return __it;
293}
294
295
296template <class _CharT, class _OutputIter>
297/* virtual */ typename money_put<_CharT, _OutputIter>::iter_type
298money_put<_CharT, _OutputIter>::
299do_put (iter_type __i, bool __intl, ios_base &__flags, char_type __fill,
300 long double __val) const
301{
302 int __fd;
303 string __grouping;
304
305 if (__intl) {
306 typedef moneypunct<_CharT, true> _Punct;
307 const _Punct &__pun = _RWSTD_USE_FACET (_Punct, __flags.getloc ());
308
309 __fd = __pun.frac_digits ();
310 __grouping = __pun.grouping ();
311 }
312 else {
313 typedef moneypunct<_CharT, false> _Punct;
314 const _Punct &__pun = _RWSTD_USE_FACET (_Punct, __flags.getloc ());
315
316 __fd = __pun.frac_digits ();
317 __grouping = __pun.grouping ();
318 }
319
320 char __buf [304];
321 char_type __wbuf [sizeof __buf];
322
323 char *__pbuf = __buf;
324
325 // format a floating point number in fixed precision into narrow buffer
326 // will insert thousands_sep placeholders (';') accroding to grouping
327 const _RWSTD_SIZE_T __n =
328 _RW::__rw_put_num (&__pbuf, sizeof __buf, _RWSTD_IOS_FIXED,
329 _C_ldouble | _C_ptr,
331 &__val, __grouping.c_str ());
332
333 // widen narrow buffer (necessary even if char_type == char)
334 const ctype<_CharT> &__ctp =
335 _RWSTD_USE_FACET (ctype<_CharT>, __flags.getloc ());
336
337 __ctp.widen (__buf, __buf + __n, __wbuf);
338
339 // write the widened buffer out, replacing any commas
340 // with the actual thousands_sep punct character
341 return _C_put (__i, (__intl ? _C_intl : 0) | _C_ldbl,
342 __flags, __fill, __wbuf, __n, 0, "", 1);
343}
344
345
346template <class _CharT, class _OutputIter>
347/* virtual */ typename money_put<_CharT, _OutputIter>::iter_type
348money_put<_CharT, _OutputIter>::
349do_put (iter_type __i, bool __intl, ios_base &__flags, char_type __fill,
350 const string_type &__str) const
351{
352 // fractional part does not undergo grouping and will be removed
353 int __fd;
354
355 string __grouping;
356
357 if (__intl) {
358 typedef moneypunct<_CharT, true> _Punct;
359
360 const _Punct &__pun = _RWSTD_USE_FACET (_Punct, __flags.getloc ());
361
362 __fd = __pun.frac_digits ();
363 __grouping = __pun.grouping ();
364 }
365 else {
366 typedef moneypunct<_CharT, false> _Punct;
367
368 const _Punct &__pun = _RWSTD_USE_FACET (_Punct, __flags.getloc ());
369
370 __fd = __pun.frac_digits ();
371 __grouping = __pun.grouping ();
372 }
373
374 _RWSTD_SIZE_T __ngroups = 1; // always at least one group
375 _RWSTD_SIZE_T __strdigs = 0; // number of digits in `str'
376
377 typedef string::traits_type _Traits;
378 typedef typename string_type::const_iterator _StringIter;
379
380 char __buf [304]; // buffer for groups
381 static char __nul = '\0'; // `groups' must be non-0
382 char *__groups = __grouping.size () ? __buf : &__nul;
383
384 const ctype<_CharT> &__ctp =
385 _RWSTD_USE_FACET (ctype<_CharT>, __flags.getloc ());
386
387 // narrow digits into a temporary buffer to determine grouping
388 for (_StringIter __it = __str.begin (); __it != __str.end (); ++__it) {
389 if (__ctp.is (ctype_base::digit, *__it)) {
390 if (__groups != &__nul)
391 _Traits::assign (*__groups++, __ctp.narrow (*__it, '\0'));
392 }
393 else if (__str.begin () != __it || '-' != __ctp.narrow (*__it, '\0'))
394 break;
395 ++__strdigs;
396 }
397
398 if (__groups != &__nul && __fd >= 0 && __fd < __groups - __buf) {
399 __groups -= __fd;
400
401 // compute the size of each group relative to the formatted number
402 // e.g., with `str' of "9876543210" and `grouping' of "\1\2\3",
403 // `groups' will point at "\1\3\3\2\1" since `str' will be
404 // formatted as "9,876,543,21,0" with thousands_sep's inserted
405
406 char *__pbuf = __buf;
407
408 *__pbuf = '\0';
409
410 __ngroups =
411 _RW::__rw_put_groups (&__pbuf, __groups - __pbuf, sizeof __buf,
412 0, __grouping.c_str ());
413 __pbuf [__ngroups] = '\0';
414 __groups = __pbuf;
415 }
416
417 return _C_put (__i, __intl ? _C_intl : 0,
418 __flags, __fill, __str.c_str (), __strdigs,
419 __fd, __groups, __ngroups);
420}
421
422
423} // namespace std
#define _RWSTD_IOS_ADJUSTFIELD
Definition _defs.h:792
#define _RWSTD_REQUIRES(pred, args)
Definition _defs.h:1132
#define _RWSTD_IOS_FIXED
Definition _defs.h:768
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_USE_FACET(type, arg)
Definition _defs.h:949
#define _RWSTD_IOS_LEFT
Definition _defs.h:771
#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_FUNC(ignore)
Definition _defs.h:1120
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _RWSTD_IOS_INTERNAL
Definition _defs.h:770
#define _RWSTD_ERROR_RUNTIME_ERROR
Definition _error.h:94
Definition json.h:5363