Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
_money_get.cc
Go to the documentation of this file.
1
29#include <streambuf>
30#include <loc/_ctype.h>
31#include <loc/_moneypunct.h>
32#include <rw/_defs.h>
33
34
36
38__rw_get_num (void*, const char*, int, int,
39 const char*, _RWSTD_SIZE_T, const char*, _RWSTD_SIZE_T);
40
42__rw_check_grouping (const char*, _RWSTD_SIZE_T,
43 const char*, _RWSTD_SIZE_T);
44
45} // namespace __rw
46
47
49
50
51template <class _CharT, class _InputIter>
52_RW::__rw_facet_id money_get<_CharT, _InputIter>::id;
53
54
55template <class _CharT, class _InputIter>
56typename money_get<_CharT, _InputIter>::iter_type
57money_get<_CharT, _InputIter>::
58_C_get (iter_type __it, iter_type __end, bool __intl, ios_base &__flags,
59 _RWSTD_IOSTATE &__err, void *__pval, string_type *__pstr) const
60{
61 typedef moneypunct<_CharT, false> _Punct0;
62 typedef moneypunct<_CharT, true> _Punct1;
63
64 const _Punct0 &__pun = __intl ?
65 _RWSTD_REINTERPRET_CAST (const _Punct0&,
66 _RWSTD_USE_FACET (_Punct1,
67 __flags.getloc ()))
68 : _RWSTD_USE_FACET (_Punct0, __flags.getloc ());
69
70 // retrieve positive and negative sign, currency symbol,
71 // the grouping string and the pattern format
72 const string_type __ps = __pun.positive_sign ();
73 const string_type __ns = __pun.negative_sign ();
74 const string_type __cs = __pun.curr_symbol ();
75 const string __gr = __pun.grouping ();
76 const money_base::pattern __pat = __pun.neg_format ();
77
78 _RWSTD_IOSTATE __ebits = _RW::__rw_goodbit;
79
80 bool __needws = false; // whitespace required?
81 bool __seendp = false; // seen decimal point in input
82
83 const ctype<_CharT> &__ctp =
84 _RWSTD_USE_FACET (ctype<_CharT>, __flags.getloc ());
85
86 char __buf [304];
87 char *__pcur = __buf;
88
89 typedef typename string_type::traits_type _Traits;
90
91 char __grpbuf [sizeof __buf]; // holds sizes of discovered groups
92 char *__pgrp = __grpbuf; // current group
93 const char *__grpstart = 0; // the start of the last group
94 const char *__grpend = 0; // the end of the last group
95
96
97 int __sign = 0; // the sign of the result if detected (-1, 0, or +1)
98
99 // buffer must always start with a sign (__rw_get_num requirement)
100 // use a '+' and overwrite it with a '-' if necessary
101 *__pcur++ = '+';
102
103 const int __fl = __flags.flags ();
104
105 typedef _RWSTD_SIZE_T _SizeT;
106
107 for (_SizeT __i = 0; !__ebits && __i != sizeof __pat.field; ++__i) {
108
109 switch (__pat.field [__i]) {
110
111 case /* '\1' */ money_base::space:
112 __needws = true;
113 // fall through...
114
115 case /* '\0' */ money_base::none: {
116
117 // optional or even required whitespace is consumed only if
118 // other characters may be required to complete the format
119 if ( sizeof __pat.field == __i + 1
120 || 2 == __i && money_base::symbol == __pat.field [3]
121 && (!(__fl & _RW::__rw_showbase) || 0 == __cs.size ())
122 && !( __sign < 0 && __ns.size () > 1
123 || __sign > 0 && __ps.size () > 1)
124 || 1 == __i && money_base::value == __pat.field [0]
125 && 0 == __ns.size () && 0 == __ps.size ()
126 && (0 == __cs.size () || !(__fl & _RW::__rw_showbase)))
127 break;
128
129 _SizeT __nc = 0;
130
131 while (__it != __end && __ctp.is (ctype_base::space, *__it)) {
132 ++__it;
133 ++__nc;
134 }
135
136 if (__needws && !__nc)
137 __ebits |= _RW::__rw_failbit;
138 break;
139 }
140
141 case /* '\2' */ money_base::symbol: {
142
143 // if optional, currency symbol is not extracted unless
144 // it is consumed only if it is followed by characters
145 // required to complete the pattern (see example in
146 // 22.2.6.1.2, p3)
147 if ( __fl & _RW::__rw_showbase
148 || __i < 2
149 || 2 == __i && (money_base::none != __pat.field [3])
150 || __sign < 0 && __ns.size () > 1
151 || __sign > 0 && __ps.size () > 1) {
152
153 for (_SizeT __nc = 0; __nc != __cs.size ();
154 ++__nc, ++__it) {
155 if (__it == __end || !_Traits::eq (*__it, __cs [__nc])) {
156
157 // 22.2.6.1.2, p2: unless showbase is set,
158 // curr_symbol is optional
159 if (__nc || __fl & _RW::__rw_showbase)
160 __ebits |= _RW::__rw_failbit;
161 break;
162 }
163 }
164 }
165 break;
166 }
167
168 case /* '\3' */ money_base::sign: {
169
170 if (__it == __end) {
171 if (__ps.size () && __ns.size ())
172 __ebits |= _RW::__rw_failbit;
173 else
174 __sign = __ps.empty () - 1;
175 break;
176 }
177
178 const char_type __c = *__it;
179
180 // 22.2.6.1.2, p3: if the first character of positive
181 // and negative sign is the same, the result is positive
182
183 if (__ps.size () && _Traits::eq (__c, __ps [0])) {
184 __sign = 1;
185 ++__it;
186 }
187 else if (__ns.size () && _Traits::eq (__c, __ns [0])) {
188 __sign = -1;
189 ++__it;
190 }
191
192 break;
193 }
194
195 case /* '\4' */ money_base::value: {
196
197 const char_type __ts =
198 __gr.size () && __gr [0] && __gr [0] != _RWSTD_CHAR_MAX ?
199 __pun.thousands_sep () : __ctp.widen ('0');
200
201 int __fd = __pun.frac_digits ();
202
203 for (; __it != __end; ++__it) {
204
205 // read and narrow a character (note that narrow() may
206 // yield the same narrow char for more than one wide
207 // character; e.g., there may be two sets of digits)
208 const char_type __c = *__it;
209 const char __ch = __ctp.narrow (__c, '\0');
210
211 if (__ch >= '0' && __ch <= '9') {
212 if (!__seendp || __fd-- > 0)
213 *__pcur++ = __ch;
214 }
215 else if ( !__seendp && __fd > 0
216 && _Traits::eq (__c, __pun.decimal_point ())) {
217 __grpend = __pcur;
218 __seendp = true;
219 }
220 else if (!__seendp && _Traits::eq (__c, __ts)) {
221 // add the length of the current group to the array groups
222 // store UCHAR_MAX if group length exceeds the size of char
223 _RWSTD_PTRDIFF_T __len;
224
225 if (__grpstart)
226 __len = __pcur - __grpstart;
227 else {
228 __grpstart = __pcur;
229 __len = __pcur - __buf - 1;
230 }
231
232 typedef unsigned char _UChar;
233
234 *__pgrp++ = char (__len < _UChar (-1) ? __len : -1);
235 __grpstart = __pcur;
236 }
237 else
238 break;
239 }
240
241 if (__pcur - __buf > 1) {
242 // append zeros to a non-empty string of digits
243 // up to the number of frac_digits
244 while (__fd-- > 0)
245 *__pcur++ = '0';
246 }
247
248 *__pcur = '\0';
249 break;
250 }
251
252 default:
253 __ebits = _RW::__rw_failbit;
254 break;
255
256 }
257 }
258
259 if (!(__ebits & _RW::__rw_failbit)) {
260
261 if (__buf [1]) {
262
263 // process the remainder of a multicharacter sign
264 const _SizeT __sizes [] = {
265 __ps.size () ? __ps.size () -1 : 0,
266 __ns.size () ? __ns.size () -1 : 0
267 };
268
269 const char_type* const __names [] = {
270 __ps.data () + !!__sizes [0],
271 __ns.data () + !!__sizes [1]
272 };
273
274 if (__sign && (__sizes [0] || __sizes [1])) {
275
276 // if the first character of a multi-character sign
277 // has been seen, try to extract the rest of the sign
278
279 _SizeT __inx = 0;
280
281 int __errtmp = 1; // no duplicates allowed
282
283 __it = _RW::__rw_match_name (__it, __end, __names, __sizes,
284 sizeof __names / sizeof *__names,
285 __inx, __errtmp, 0);
286
287 if (1 < __inx && __sizes [__sign < 0]) {
288
289 // failed to match the remainder of the sign to
290 // the input and the first character of the sign
291 // does not form the complete (positive or negative)
292 // sign
293 __ebits = _RW::__rw_failbit;
294 __buf [1] = '\0';
295 }
296 else if (!_Traits::eq (*__ps.data (), *__ns.data ())) {
297
298 // if the first extracted character of the sign string
299 // forms the complete sign whose first character doesn't
300 // form an initial substring of the other sign string
301 // the resulting sign is determined by the one-character
302 // sign string
303 if (1 < __inx)
304 __inx = 0 < __sizes [__sign < 0];
305
306 // if both signs begin with the same character,
307 // the result is positive (22.2.6.1.2, p3)
308 *__buf = __inx ? '-' : '+';
309 __sign = -int (__inx);
310 }
311 }
312 else if (__sign < 0) {
313 *__buf = '-';
314 }
315
316 if (__pstr && !(__ebits & _RW::__rw_failbit)) {
317 // skip over the leading sign and any redundant zeros after it
318 const char *__start = __buf + 1;
319 for (; '0' == *__start && '0' == __start [1]; ++__start);
320
321 // invert the sign if negative
322 __sign = __sign < 0;
323
324 // widen narrow digits optionally preceded by the minus sign
325 // into the basic_string object as required by 22.2.6.1.2, p1
326 __pstr->resize ((__pcur - __start) + _SizeT (__sign));
327
328 if (__sign)
329 _Traits::assign ((*__pstr)[0], __ctp.widen ('-'));
330
331 __ctp.widen (__start, __pcur, &(*__pstr)[_SizeT (__sign)]);
332 }
333
334 const char *__grs = "";
335 _SizeT __grn = 0;
336
337 // 22.2.6.1.2, p1: thousands separators are optional
338
339 // add the length of the last group to the array of groups
340 // store UCHAR_MAX if group length exceeds the size of char
341 if (__grpstart) {
342 const _RWSTD_PTRDIFF_T __len =
343 (__grpend ? __grpend : __pcur) - __grpstart;
344
345 typedef unsigned char _UChar;
346
347 *__pgrp++ = char (__len < _UChar (-1) ? __len : -1);
348 *__pgrp = '\0';
349 __grs = __gr.data ();
350 __grn = __gr.size ();
351 }
352
353 if (__pval) {
354 // produce a number from the extracted string of digits
355 // and (optionally) check grouping
356
357 const int __errtmp =
358 _RW::__rw_get_num (__pval, __buf, _C_ldouble, 0,
359 __grpbuf, __pgrp - __grpbuf,
360 __grs, __grn);
361
362 __ebits |= _RWSTD_IOSTATE (__errtmp);
363 }
364 else if (0 > _RW::__rw_check_grouping (__grpbuf, __pgrp - __grpbuf,
365 __grs, __grn))
366 __ebits |= _RW::__rw_failbit;
367 }
368 else
369 __ebits |= _RW::__rw_failbit;
370 }
371
372 if (__it == __end)
373 __ebits |= _RW::__rw_eofbit;
374
375 __err |= __ebits;
376
377 return __it;
378}
379
380
381} // namespace std
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_USE_FACET(type, arg)
Definition _defs.h:949
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_IOSTATE
Definition _iosfwd.h:91
Definition json.h:5363