2 * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
5 * Silicon Graphics Computer Systems, Inc.
10 * This material is provided "as is", with absolutely no warranty expressed
11 * or implied. Any use is at your own risk.
13 * Permission to use or copy this software for any purpose is hereby granted
14 * without fee, provided the above notices are retained on all copies.
15 * Permission to modify the code and to distribute modified code is granted,
16 * provided the above notices are retained, and a notice that the code was
17 * modified is included with the above copyright notice.
20 #ifndef _STLP_NUM_GET_C
21 #define _STLP_NUM_GET_C
23 #ifndef _STLP_INTERNAL_NUM_GET_H
24 # include <stl/_num_get.h>
27 #ifndef _STLP_INTERNAL_LIMITS
28 # include <stl/_limits.h>
33 _STLP_MOVE_TO_PRIV_NAMESPACE
35 _STLP_DECLSPEC unsigned char _STLP_CALL __digit_val_table(unsigned);
36 _STLP_DECLSPEC const char* _STLP_CALL __narrow_atoms();
38 template < class _InputIter, class _Integer, class _CharT>
40 __do_get_integer(_InputIter&, _InputIter&, ios_base&, ios_base::iostate&, _Integer&, _CharT*);
42 // __do_get_integer and its helper functions.
44 inline bool _STLP_CALL __get_fdigit(char __c, const char*)
45 { return __c >= '0' && __c <= '9'; }
47 inline bool _STLP_CALL __get_fdigit_or_sep(char& __c, char __sep, const char *__digits) {
53 return __get_fdigit(__c, __digits);
57 __get_digit_from_table(unsigned __index)
58 { return (__index > 127 ? 0xFF : __digit_val_table(__index)); }
60 template <class _InputIter, class _CharT>
62 __get_base_or_zero(_InputIter& __in_ite, _InputIter& __end, ios_base& __str, _CharT*) {
64 const ctype<_CharT>& __c_type = *__STATIC_CAST(const ctype<_CharT>*, __str._M_ctype_facet());
66 __c_type.widen(__narrow_atoms(), __narrow_atoms() + 5, __atoms);
68 bool __negative = false;
69 _CharT __c = *__in_ite;
71 if (__c == __atoms[1] /* __xminus_char */ ) {
75 else if (__c == __atoms[0] /* __xplus_char */ )
81 ios_base::fmtflags __basefield = __str.flags() & ios_base::basefield;
83 switch (__basefield) {
92 if (__in_ite != __end && *__in_ite == __atoms[2] /* __zero_char */ ) {
94 if (__in_ite != __end &&
95 (*__in_ite == __atoms[3] /* __x_char */ || *__in_ite == __atoms[4] /* __X_char */ ))
98 __valid_zero = 1; // That zero is valid by itself.
102 if (__in_ite != __end && *__in_ite == __atoms[2] /* __zero_char */ ) {
104 if (__in_ite != __end &&
105 (*__in_ite == __atoms[3] /* __x_char */ || *__in_ite == __atoms[4] /* __X_char */ )) {
112 __valid_zero = 1; // That zero is still valid by itself.
119 return (__base << 2) | ((int)__negative << 1) | __valid_zero;
123 template <class _InputIter, class _Integer, class _CharT>
125 __get_integer(_InputIter& __first, _InputIter& __last,
126 int __base, _Integer& __val,
127 int __got, bool __is_negative, _CharT __separator, const string& __grouping, const __true_type& /*_IsSigned*/) {
128 bool __ovflow = false;
129 _Integer __result = 0;
130 bool __is_group = !__grouping.empty();
131 char __group_sizes[64];
132 char __current_group_size = 0;
133 char* __group_sizes_end = __group_sizes;
135 _Integer __over_base = (numeric_limits<_Integer>::min)() / __STATIC_CAST(_Integer, __base);
137 for ( ; __first != __last ; ++__first) {
139 const _CharT __c = *__first;
141 if (__is_group && __c == __separator) {
142 *__group_sizes_end++ = __current_group_size;
143 __current_group_size = 0;
147 int __n = __get_digit_from_table(__c);
153 ++__current_group_size;
155 if (__result < __over_base)
156 __ovflow = true; // don't need to keep accumulating
158 _Integer __next = __STATIC_CAST(_Integer, __base * __result - __n);
160 __ovflow = __ovflow || __next >= __result;
165 if (__is_group && __group_sizes_end != __group_sizes) {
166 *__group_sizes_end++ = __current_group_size;
169 // fbp : added to not modify value if nothing was read
171 __val = __ovflow ? __is_negative ? (numeric_limits<_Integer>::min)()
172 : (numeric_limits<_Integer>::max)()
173 : __is_negative ? __result
174 : __STATIC_CAST(_Integer, -__result);
176 // overflow is being treated as failure
177 return ((__got > 0) && !__ovflow) &&
179 __valid_grouping(__group_sizes, __group_sizes_end,
180 __grouping.data(), __grouping.data()+ __grouping.size()));
183 template <class _InputIter, class _Integer, class _CharT>
185 __get_integer(_InputIter& __first, _InputIter& __last,
186 int __base, _Integer& __val,
187 int __got, bool __is_negative, _CharT __separator, const string& __grouping, const __false_type& /*_IsSigned*/) {
188 bool __ovflow = false;
189 _Integer __result = 0;
190 bool __is_group = !__grouping.empty();
191 char __group_sizes[64];
192 char __current_group_size = 0;
193 char* __group_sizes_end = __group_sizes;
195 _Integer __over_base = (numeric_limits<_Integer>::max)() / __STATIC_CAST(_Integer, __base);
197 for ( ; __first != __last ; ++__first) {
199 const _CharT __c = *__first;
201 if (__is_group && __c == __separator) {
202 *__group_sizes_end++ = __current_group_size;
203 __current_group_size = 0;
207 int __n = __get_digit_from_table(__c);
213 ++__current_group_size;
215 if (__result > __over_base)
216 __ovflow = true; //don't need to keep accumulating
218 _Integer __next = __STATIC_CAST(_Integer, __base * __result + __n);
220 __ovflow = __ovflow || __next <= __result;
225 if (__is_group && __group_sizes_end != __group_sizes) {
226 *__group_sizes_end++ = __current_group_size;
229 // fbp : added to not modify value if nothing was read
231 __val = __ovflow ? (numeric_limits<_Integer>::max)()
232 : (__is_negative ? __STATIC_CAST(_Integer, -__result)
236 // overflow is being treated as failure
237 return ((__got > 0) && !__ovflow) &&
239 __valid_grouping(__group_sizes, __group_sizes_end,
240 __grouping.data(), __grouping.data()+ __grouping.size()));
244 template <class _InputIter, class _Integer, class _CharT>
246 __get_decimal_integer(_InputIter& __first, _InputIter& __last, _Integer& __val, _CharT* /*dummy*/) {
248 //Here there is no grouping so separator is not important, we just pass the default charater.
249 return __get_integer(__first, __last, 10, __val, 0, false, _CharT() /*separator*/, __grp, __false_type());
252 template <class _InputIter, class _Integer, class _CharT>
253 _InputIter _STLP_CALL
254 __do_get_integer(_InputIter& __in_ite, _InputIter& __end, ios_base& __str,
255 ios_base::iostate& __err, _Integer& __val, _CharT* __pc) {
256 #if defined (__HP_aCC) && (__HP_aCC == 1)
257 bool _IsSigned = !((_Integer)(-1) > 0);
259 typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned;
262 const numpunct<_CharT>& __numpunct = *__STATIC_CAST(const numpunct<_CharT>*, __str._M_numpunct_facet());
263 const string& __grouping = __str._M_grouping(); // cached copy
265 const int __base_or_zero = __get_base_or_zero(__in_ite, __end, __str, __pc);
266 int __got = __base_or_zero & 1;
270 if (__in_ite == __end) { // We may have already read a 0. If so,
272 if (__got > 0) { // the result is 0 even if we're at eof.
280 const bool __negative = (__base_or_zero & 2) != 0;
281 const int __base = __base_or_zero >> 2;
283 #if defined (__HP_aCC) && (__HP_aCC == 1)
285 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __numpunct.thousands_sep(), __grouping, __true_type() );
287 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __numpunct.thousands_sep(), __grouping, __false_type() );
289 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __numpunct.thousands_sep(), __grouping, _IsSigned());
293 __err = __STATIC_CAST(ios_base::iostate, __result ? ios_base::goodbit : ios_base::failbit);
295 if (__in_ite == __end)
296 __err |= ios_base::eofbit;
300 // __read_float and its helper functions.
301 template <class _InputIter, class _CharT>
302 _InputIter _STLP_CALL
303 __copy_sign(_InputIter __first, _InputIter __last, __iostring& __v,
304 _CharT __xplus, _CharT __xminus) {
305 if (__first != __last) {
306 _CharT __c = *__first;
309 else if (__c == __xminus) {
318 template <class _InputIter, class _CharT>
320 __copy_digits(_InputIter& __first, _InputIter __last,
321 __iostring& __v, const _CharT* __digits) {
324 for ( ; __first != __last; ++__first) {
325 _CharT __c = *__first;
326 if (__get_fdigit(__c, __digits)) {
327 __v.push_back((char)__c);
336 template <class _InputIter, class _CharT>
338 __copy_grouped_digits(_InputIter& __first, _InputIter __last,
339 __iostring& __v, const _CharT * __digits,
340 _CharT __sep, const string& __grouping,
341 bool& __grouping_ok) {
343 char __group_sizes[64];
344 char*__group_sizes_end = __group_sizes;
345 char __current_group_size = 0;
347 for ( ; __first != __last; ++__first) {
348 _CharT __c = *__first;
349 bool __tmp = __get_fdigit_or_sep(__c, __sep, __digits);
352 *__group_sizes_end++ = __current_group_size;
353 __current_group_size = 0;
357 __v.push_back((char)__c);
358 ++__current_group_size;
365 if (__group_sizes_end != __group_sizes)
366 *__group_sizes_end++ = __current_group_size;
367 __grouping_ok = __valid_grouping(__group_sizes, __group_sizes_end, __grouping.data(), __grouping.data() + __grouping.size());
372 template <class _InputIter, class _CharT>
374 __read_float(__iostring& __buf, _InputIter& __in_ite, _InputIter& __end, ios_base& __s, _CharT*) {
375 // Create a string, copying characters of the form
376 // [+-]? [0-9]* .? [0-9]* ([eE] [+-]? [0-9]+)?
378 bool __digits_before_dot /* = false */;
379 bool __digits_after_dot = false;
382 bool __grouping_ok = true;
384 const ctype<_CharT>& __ct = *__STATIC_CAST(const ctype<_CharT>*, __s._M_ctype_facet());
385 const numpunct<_CharT>& __numpunct = *__STATIC_CAST(const numpunct<_CharT>*, __s._M_numpunct_facet());
386 const string& __grouping = __s._M_grouping(); // cached copy
388 _CharT __dot = __numpunct.decimal_point();
389 _CharT __sep = __numpunct.thousands_sep();
398 _Initialize_get_float(__ct, __xplus, __xminus, __pow_e, __pow_E, __digits);
400 // Get an optional sign
401 __in_ite = __copy_sign(__in_ite, __end, __buf, __xplus, __xminus);
403 // Get an optional string of digits.
404 if (!__grouping.empty())
405 __digits_before_dot = __copy_grouped_digits(__in_ite, __end, __buf, __digits,
406 __sep, __grouping, __grouping_ok);
408 __digits_before_dot = __copy_digits(__in_ite, __end, __buf, __digits);
410 // Get an optional decimal point, and an optional string of digits.
411 if (__in_ite != __end && *__in_ite == __dot) {
412 __buf.push_back('.');
414 __digits_after_dot = __copy_digits(__in_ite, __end, __buf, __digits);
417 // There have to be some digits, somewhere.
418 __ok = __digits_before_dot || __digits_after_dot;
420 // Get an optional exponent.
421 if (__ok && __in_ite != __end && (*__in_ite == __pow_e || *__in_ite == __pow_E)) {
422 __buf.push_back('e');
424 __in_ite = __copy_sign(__in_ite, __end, __buf, __xplus, __xminus);
425 __ok = __copy_digits(__in_ite, __end, __buf, __digits);
426 // If we have an exponent then the sign
427 // is optional but the digits aren't.
433 _STLP_MOVE_TO_STD_NAMESPACE
436 // num_get<>, num_put<>
439 #if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
440 # if !defined(__SYMBIAN32__WSD__)
441 # if !defined (__BORLANDC__) && (defined (__SYMBIAN32__) && defined(_STLP_DESIGNATED_DLL))
442 template <class _CharT, class _InputIterator>
443 locale::id num_get<_CharT, _InputIterator>::id;
446 # if ((defined (__CYGWIN__) || defined (__MINGW32__)) && \
447 defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)) || (defined (__SYMBIAN32__) && defined(_STLP_DESIGNATED_DLL))
449 * Under cygwin, when STLport is used as a shared library, the id needs
450 * to be specified as imported otherwise they will be duplicated in the
451 * calling executable.
453 # if defined(__SYMBIAN32__)
455 locale::id num_get<char, istreambuf_iterator<char, char_traits<char> > >::id; //data should not exported in symbian
458 _STLP_DECLSPEC locale::id num_get<char, const char*>::id;
461 # if !defined (STLP_NO_WCHAR_T)
463 locale::id num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
466 _STLP_DECLSPEC locale::id num_get<wchar_t, const wchar_t*>::id;
468 # endif//STLP_NO_WCHAR_T
471 _STLP_DECLSPEC locale::id num_get<char, istreambuf_iterator<char, char_traits<char> > >::id;
474 _STLP_DECLSPEC locale::id num_get<char, const char*>::id;
477 # if !defined (STLP_NO_WCHAR_T)
479 _STLP_DECLSPEC locale::id num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
482 _STLP_DECLSPEC locale::id num_get<wchar_t, const wchar_t*>::id;
485 # endif//__SYMBIAN32__
487 # endif /* __CYGWIN__ && _STLP_USE_DYNAMIC_LIB */
488 #endif //__SYMBIAN32__WSD__
490 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
492 //typedef num_get<char, const char*> num_get_char;
493 typedef num_get<char, istreambuf_iterator<char, char_traits<char> > > num_get_char_2;
495 //__DECLARE_INSTANCE(locale::id, num_get_char::id, );
496 __DECLARE_INSTANCE(locale::id, num_get_char_2::id, );
498 # if !defined (_STLP_NO_WCHAR_T)
500 //typedef num_get<wchar_t, const wchar_t*> num_get_wchar_t;
501 typedef num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > > num_get_wchar_t_2;
503 //__DECLARE_INSTANCE(locale::id, num_get_wchar_t::id, );
504 __DECLARE_INSTANCE(locale::id, num_get_wchar_t_2::id, );
508 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
510 #if !defined (_STLP_NO_BOOL)
511 template <class _CharT, class _InputIter>
513 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end,
515 ios_base::iostate& __err, bool& __x) const {
516 if (__s.flags() & ios_base::boolalpha) {
517 locale __loc = __s.getloc();
518 const _Numpunct& __np = *__STATIC_CAST(const _Numpunct*, __s._M_numpunct_facet());
519 // const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc) ;
520 // const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc) ;
522 const basic_string<_CharT> __truename = __np.truename();
523 const basic_string<_CharT> __falsename = __np.falsename();
524 bool __true_ok = true;
525 bool __false_ok = true;
528 for ( ; __in_ite != __end; ++__in_ite) {
529 _CharT __c = *__in_ite;
530 __true_ok = __true_ok && (__c == __truename[__n]);
531 __false_ok = __false_ok && (__c == __falsename[__n]);
534 if ((!__true_ok && !__false_ok) ||
535 (__true_ok && __n >= __truename.size()) ||
536 (__false_ok && __n >= __falsename.size())) {
541 if (__true_ok && __n < __truename.size()) __true_ok = false;
542 if (__false_ok && __n < __falsename.size()) __false_ok = false;
544 if (__true_ok || __false_ok) {
545 __err = ios_base::goodbit;
549 __err = ios_base::failbit;
551 if (__in_ite == __end)
552 __err |= ios_base::eofbit;
559 _InputIter __tmp = this->do_get(__in_ite, __end, __s, __err, __lx);
560 if (!(__err & ios_base::failbit)) {
566 __err |= ios_base::failbit;
572 #endif /* _STLP_NO_BOOL */
574 #if defined (_STLP_FIX_LIBRARY_ISSUES)
575 template <class _CharT, class _InputIter>
577 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
578 ios_base::iostate& __err, short& __val) const
579 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
581 template <class _CharT, class _InputIter>
583 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
584 ios_base::iostate& __err, int& __val) const
585 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
589 template <class _CharT, class _InputIter>
591 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
592 ios_base::iostate& __err, long& __val) const
593 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
595 template <class _CharT, class _InputIter>
597 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
598 ios_base::iostate& __err,
599 unsigned short& __val) const
600 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
602 template <class _CharT, class _InputIter>
604 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
605 ios_base::iostate& __err,
606 unsigned int& __val) const
607 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
609 template <class _CharT, class _InputIter>
611 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
612 ios_base::iostate& __err,
613 unsigned long& __val) const
614 { return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); }
617 template <class _CharT, class _InputIter>
619 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
620 ios_base::iostate& __err,
621 float& __val) const {
622 _STLP_PRIV __iostring __buf ;
623 bool __ok = _STLP_PRIV __read_float(__buf, __in_ite, __end, __str, (_CharT*)0 );
624 _STLP_PRIV __string_to_float(__buf, __val);
625 __err = __STATIC_CAST(ios_base::iostate, __ok ? ios_base::goodbit : ios_base::failbit);
626 if (__in_ite == __end)
627 __err |= ios_base::eofbit;
631 template <class _CharT, class _InputIter>
633 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
634 ios_base::iostate& __err,
635 double& __val) const {
636 _STLP_PRIV __iostring __buf ;
637 bool __ok = _STLP_PRIV __read_float(__buf, __in_ite, __end, __str, (_CharT*)0 );
638 #ifdef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT
642 _STLP_PRIV __string_to_float(__buf, __val);
643 #ifdef SYMBIAN_OE_ENHANCED_LOCALE_SUPPORT
646 __err = __STATIC_CAST(ios_base::iostate, __ok ? ios_base::goodbit : ios_base::failbit);
647 if (__in_ite == __end)
648 __err |= ios_base::eofbit;
652 #if !defined (_STLP_NO_LONG_DOUBLE)
653 template <class _CharT, class _InputIter>
655 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
656 ios_base::iostate& __err,
657 long double& __val) const {
658 _STLP_PRIV __iostring __buf ;
659 bool __ok = _STLP_PRIV __read_float(__buf, __in_ite, __end, __str, (_CharT*)0 );
660 _STLP_PRIV __string_to_float(__buf, __val);
661 __err = __STATIC_CAST(ios_base::iostate, __ok ? ios_base::goodbit : ios_base::failbit);
662 if (__in_ite == __end)
663 __err |= ios_base::eofbit;
666 #endif /* _STLP_NO_LONG_DOUBLE */
668 template <class _CharT, class _InputIter>
670 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
671 ios_base::iostate& __err,
673 #if defined (_STLP_LONG_LONG) && !defined (__MRC__) //*ty 12/07/2001 - MrCpp can not cast from long long to void*
674 unsigned _STLP_LONG_LONG __val;
678 iter_type __tmp = _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 );
679 if (!(__err & ios_base::failbit))
680 __p = __REINTERPRET_CAST(void*,__val);
684 #if defined (_STLP_LONG_LONG)
685 template <class _CharT, class _InputIter>
687 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
688 ios_base::iostate& __err,
689 _STLP_LONG_LONG& __val) const {
690 return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 );
693 template <class _CharT, class _InputIter>
695 num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str,
696 ios_base::iostate& __err,
697 unsigned _STLP_LONG_LONG& __val) const {
698 return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 );
700 #endif /* _STLP_LONG_LONG */
704 #endif /* _STLP_NUMERIC_FACETS_C */