1/* 2 * Copyright (c) 1999 3 * Silicon Graphics Computer Systems, Inc. 4 * 5 * Copyright (c) 1999 6 * Boris Fomitchev 7 * 8 * This material is provided "as is", with absolutely no warranty expressed 9 * or implied. Any use is at your own risk. 10 * 11 * Permission to use or copy this software for any purpose is hereby granted 12 * without fee, provided the above notices are retained on all copies. 13 * Permission to modify the code and to distribute modified code is granted, 14 * provided the above notices are retained, and a notice that the code was 15 * modified is included with the above copyright notice. 16 * 17 */ 18#ifndef _STLP_NUM_GET_C 19#define _STLP_NUM_GET_C 20 21#ifndef _STLP_INTERNAL_NUM_GET_H 22# include <stl/_num_get.h> 23#endif 24 25#ifndef _STLP_INTERNAL_LIMITS 26# include <stl/_limits.h> 27#endif 28 29_STLP_BEGIN_NAMESPACE 30 31_STLP_MOVE_TO_PRIV_NAMESPACE 32 33_STLP_DECLSPEC unsigned char _STLP_CALL __digit_val_table(unsigned); 34_STLP_DECLSPEC const char* _STLP_CALL __narrow_atoms(); 35 36// __do_get_integer, __do_get_float and its helper functions. 37 38inline bool _STLP_CALL __get_fdigit(char __c, const char*) 39{ return __c >= '0' && __c <= '9'; } 40 41inline bool _STLP_CALL __get_fdigit_or_sep(char& __c, char __sep, const char *__digits) { 42 if (__c == __sep) { 43 __c = ',' ; 44 return true ; 45 } 46 else 47 return __get_fdigit(__c, __digits); 48} 49 50inline int _STLP_CALL 51__get_digit_from_table(unsigned __index) 52{ return (__index > 127 ? 0xFF : __digit_val_table(__index)); } 53 54template <class _InputIter, class _CharT> 55int 56__get_base_or_zero(_InputIter& __in_ite, _InputIter& __end, 57 ios_base::fmtflags __flags, const ctype<_CharT>& __c_type) { 58 _CharT __atoms[5]; 59 __c_type.widen(__narrow_atoms(), __narrow_atoms() + 5, __atoms); 60 61 bool __negative = false; 62 _CharT __c = *__in_ite; 63 64 if (__c == __atoms[1] /* __xminus_char */ ) { 65 __negative = true; 66 ++__in_ite; 67 } 68 else if (__c == __atoms[0] /* __xplus_char */ ) 69 ++__in_ite; 70 71 int __base; 72 int __valid_zero = 0; 73 74 ios_base::fmtflags __basefield = __flags & ios_base::basefield; 75 76 switch (__basefield) { 77 case ios_base::oct: 78 __base = 8; 79 break; 80 case ios_base::dec: 81 __base = 10; 82 break; 83 case ios_base::hex: 84 __base = 16; 85 if (__in_ite != __end && *__in_ite == __atoms[2] /* __zero_char */ ) { 86 ++__in_ite; 87 if (__in_ite != __end && 88 (*__in_ite == __atoms[3] /* __x_char */ || *__in_ite == __atoms[4] /* __X_char */ )) 89 ++__in_ite; 90 else 91 __valid_zero = 1; // That zero is valid by itself. 92 } 93 break; 94 default: 95 if (__in_ite != __end && *__in_ite == __atoms[2] /* __zero_char */ ) { 96 ++__in_ite; 97 if (__in_ite != __end && 98 (*__in_ite == __atoms[3] /* __x_char */ || *__in_ite == __atoms[4] /* __X_char */ )) { 99 ++__in_ite; 100 __base = 16; 101 } 102 else 103 { 104 __base = 8; 105 __valid_zero = 1; // That zero is still valid by itself. 106 } 107 } 108 else 109 __base = 10; 110 break; 111 } 112 return (__base << 2) | ((int)__negative << 1) | __valid_zero; 113} 114 115 116template <class _InputIter, class _Integer, class _CharT> 117bool _STLP_CALL 118__get_integer(_InputIter& __first, _InputIter& __last, 119 int __base, _Integer& __val, 120 int __got, bool __is_negative, _CharT __separator, const string& __grouping, const __true_type& /*_IsSigned*/) { 121 bool __ovflow = false; 122 _Integer __result = 0; 123 bool __is_group = !__grouping.empty(); 124 char __group_sizes[64]; 125 char __current_group_size = 0; 126 char* __group_sizes_end = __group_sizes; 127 128 _Integer __over_base = (numeric_limits<_Integer>::min)() / __STATIC_CAST(_Integer, __base); 129 130 for ( ; __first != __last ; ++__first) { 131 132 const _CharT __c = *__first; 133 134 if (__is_group && __c == __separator) { 135 *__group_sizes_end++ = __current_group_size; 136 __current_group_size = 0; 137 continue; 138 } 139 140 int __n = __get_digit_from_table(__c); 141 142 if (__n >= __base) 143 break; 144 145 ++__got; 146 ++__current_group_size; 147 148 if (__result < __over_base) 149 __ovflow = true; // don't need to keep accumulating 150 else { 151 _Integer __next = __STATIC_CAST(_Integer, __base * __result - __n); 152 if (__result != 0) 153 __ovflow = __ovflow || __next >= __result; 154 __result = __next; 155 } 156 } 157 158 if (__is_group && __group_sizes_end != __group_sizes) { 159 *__group_sizes_end++ = __current_group_size; 160 } 161 162 // fbp : added to not modify value if nothing was read 163 if (__got > 0) { 164 __val = __ovflow ? __is_negative ? (numeric_limits<_Integer>::min)() 165 : (numeric_limits<_Integer>::max)() 166 : __is_negative ? __result 167 : __STATIC_CAST(_Integer, -__result); 168 } 169 // overflow is being treated as failure 170 return ((__got > 0) && !__ovflow) && 171 (__is_group == 0 || 172 __valid_grouping(__group_sizes, __group_sizes_end, 173 __grouping.data(), __grouping.data()+ __grouping.size())); 174} 175 176template <class _InputIter, class _Integer, class _CharT> 177bool _STLP_CALL 178__get_integer(_InputIter& __first, _InputIter& __last, 179 int __base, _Integer& __val, 180 int __got, bool __is_negative, _CharT __separator, const string& __grouping, const __false_type& /*_IsSigned*/) { 181 bool __ovflow = false; 182 _Integer __result = 0; 183 bool __is_group = !__grouping.empty(); 184 char __group_sizes[64]; 185 char __current_group_size = 0; 186 char* __group_sizes_end = __group_sizes; 187 188 _Integer __over_base = (numeric_limits<_Integer>::max)() / __STATIC_CAST(_Integer, __base); 189 190 for ( ; __first != __last ; ++__first) { 191 192 const _CharT __c = *__first; 193 194 if (__is_group && __c == __separator) { 195 *__group_sizes_end++ = __current_group_size; 196 __current_group_size = 0; 197 continue; 198 } 199 200 int __n = __get_digit_from_table(__c); 201 202 if (__n >= __base) 203 break; 204 205 ++__got; 206 ++__current_group_size; 207 208 if (__result > __over_base) 209 __ovflow = true; //don't need to keep accumulating 210 else { 211 _Integer __next = __STATIC_CAST(_Integer, __base * __result + __n); 212 if (__result != 0) 213 __ovflow = __ovflow || __next <= __result; 214 __result = __next; 215 } 216 } 217 218 if (__is_group && __group_sizes_end != __group_sizes) { 219 *__group_sizes_end++ = __current_group_size; 220 } 221 222 // fbp : added to not modify value if nothing was read 223 if (__got > 0) { 224 __val = __ovflow ? (numeric_limits<_Integer>::max)() 225 : (__is_negative ? __STATIC_CAST(_Integer, -__result) 226 : __result); 227 } 228 229 // overflow is being treated as failure 230 return ((__got > 0) && !__ovflow) && 231 (__is_group == 0 || 232 __valid_grouping(__group_sizes, __group_sizes_end, 233 __grouping.data(), __grouping.data()+ __grouping.size())); 234} 235 236 237template <class _InputIter, class _Integer, class _CharT> 238bool _STLP_CALL 239__get_decimal_integer(_InputIter& __first, _InputIter& __last, _Integer& __val, _CharT* /*dummy*/) { 240 string __grp; 241 //Here there is no grouping so separator is not important, we just pass the default character. 242 return __get_integer(__first, __last, 10, __val, 0, false, _CharT() /*separator*/, __grp, __false_type()); 243} 244 245template <class _InputIter, class _Integer, class _CharT> 246_InputIter _STLP_CALL 247__do_get_integer(_InputIter& __in_ite, _InputIter& __end, ios_base& __str, 248 ios_base::iostate& __err, _Integer& __val, _CharT* /*__pc*/) { 249 locale __loc = __str.getloc(); 250 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 251 252#if defined (__HP_aCC) && (__HP_aCC == 1) 253 bool _IsSigned = !((_Integer)(-1) > 0); 254#else 255 typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned; 256#endif 257 258 const int __base_or_zero = __get_base_or_zero(__in_ite, __end, __str.flags(), __ctype); 259 int __got = __base_or_zero & 1; 260 261 bool __result; 262 263 if (__in_ite == __end) { // We may have already read a 0. If so, 264 265 if (__got > 0) { // the result is 0 even if we're at eof. 266 __val = 0; 267 __result = true; 268 } 269 else 270 __result = false; 271 } 272 else { 273 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 274 const bool __negative = (__base_or_zero & 2) != 0; 275 const int __base = __base_or_zero >> 2; 276 277#if defined (__HP_aCC) && (__HP_aCC == 1) 278 if (_IsSigned) 279 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __np.thousands_sep(), __np.grouping(), __true_type() ); 280 else 281 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __np.thousands_sep(), __np.grouping(), __false_type() ); 282#else 283 __result = __get_integer(__in_ite, __end, __base, __val, __got, __negative, __np.thousands_sep(), __np.grouping(), _IsSigned()); 284# endif 285 } 286 287 __err = __STATIC_CAST(ios_base::iostate, __result ? ios_base::goodbit : ios_base::failbit); 288 289 if (__in_ite == __end) 290 __err |= ios_base::eofbit; 291 return __in_ite; 292} 293 294// __read_float and its helper functions. 295template <class _InputIter, class _CharT> 296_InputIter _STLP_CALL 297__copy_sign(_InputIter __first, _InputIter __last, __iostring& __v, 298 _CharT __xplus, _CharT __xminus) { 299 if (__first != __last) { 300 _CharT __c = *__first; 301 if (__c == __xplus) 302 ++__first; 303 else if (__c == __xminus) { 304 __v.push_back('-'); 305 ++__first; 306 } 307 } 308 return __first; 309} 310 311 312template <class _InputIter, class _CharT> 313bool _STLP_CALL 314__copy_digits(_InputIter& __first, _InputIter __last, 315 __iostring& __v, const _CharT* __digits) { 316 bool __ok = false; 317 318 for ( ; __first != __last; ++__first) { 319 _CharT __c = *__first; 320 if (__get_fdigit(__c, __digits)) { 321 __v.push_back((char)__c); 322 __ok = true; 323 } 324 else 325 break; 326 } 327 return __ok; 328} 329 330template <class _InputIter, class _CharT> 331bool _STLP_CALL 332__copy_grouped_digits(_InputIter& __first, _InputIter __last, 333 __iostring& __v, const _CharT * __digits, 334 _CharT __sep, const string& __grouping, 335 bool& __grouping_ok) { 336 bool __ok = false; 337 char __group_sizes[64]; 338 char*__group_sizes_end = __group_sizes; 339 char __current_group_size = 0; 340 341 for ( ; __first != __last; ++__first) { 342 _CharT __c = *__first; 343 bool __tmp = __get_fdigit_or_sep(__c, __sep, __digits); 344 if (__tmp) { 345 if (__c == ',') { 346 *__group_sizes_end++ = __current_group_size; 347 __current_group_size = 0; 348 } 349 else { 350 __ok = true; 351 __v.push_back((char)__c); 352 ++__current_group_size; 353 } 354 } 355 else 356 break; 357 } 358 359 if (__group_sizes_end != __group_sizes) 360 *__group_sizes_end++ = __current_group_size; 361 __grouping_ok = __valid_grouping(__group_sizes, __group_sizes_end, __grouping.data(), __grouping.data() + __grouping.size()); 362 return __ok; 363} 364 365 366template <class _InputIter, class _CharT> 367bool _STLP_CALL 368__read_float(__iostring& __buf, _InputIter& __in_ite, _InputIter& __end, 369 const ctype<_CharT> &__ct, const numpunct<_CharT> &__numpunct) { 370 // Create a string, copying characters of the form 371 // [+-]? [0-9]* .? [0-9]* ([eE] [+-]? [0-9]+)? 372 373 string __grouping = __numpunct.grouping(); 374 bool __digits_before_dot /* = false */; 375 bool __digits_after_dot = false; 376 bool __ok; 377 378 bool __grouping_ok = true; 379 380 _CharT __dot = __numpunct.decimal_point(); 381 _CharT __sep = __numpunct.thousands_sep(); 382 383 _CharT __digits[10]; 384 _CharT __xplus; 385 _CharT __xminus; 386 387 _CharT __pow_e; 388 _CharT __pow_E; 389 390 _Initialize_get_float(__ct, __xplus, __xminus, __pow_e, __pow_E, __digits); 391 392 // Get an optional sign 393 __in_ite = __copy_sign(__in_ite, __end, __buf, __xplus, __xminus); 394 395 // Get an optional string of digits. 396 if (!__grouping.empty()) 397 __digits_before_dot = __copy_grouped_digits(__in_ite, __end, __buf, __digits, 398 __sep, __grouping, __grouping_ok); 399 else 400 __digits_before_dot = __copy_digits(__in_ite, __end, __buf, __digits); 401 402 // Get an optional decimal point, and an optional string of digits. 403 if (__in_ite != __end && *__in_ite == __dot) { 404 __buf.push_back('.'); 405 ++__in_ite; 406 __digits_after_dot = __copy_digits(__in_ite, __end, __buf, __digits); 407 } 408 409 // There have to be some digits, somewhere. 410 __ok = __digits_before_dot || __digits_after_dot; 411 412 // Get an optional exponent. 413 if (__ok && __in_ite != __end && (*__in_ite == __pow_e || *__in_ite == __pow_E)) { 414 __buf.push_back('e'); 415 ++__in_ite; 416 __in_ite = __copy_sign(__in_ite, __end, __buf, __xplus, __xminus); 417 __ok = __copy_digits(__in_ite, __end, __buf, __digits); 418 // If we have an exponent then the sign 419 // is optional but the digits aren't. 420 } 421 422 return __ok; 423} 424 425template <class _InputIter, class _Float, class _CharT> 426_InputIter _STLP_CALL 427__do_get_float(_InputIter& __in_ite, _InputIter& __end, ios_base& __str, 428 ios_base::iostate& __err, _Float& __val, _CharT* /*__pc*/) { 429 locale __loc = __str.getloc(); 430 const ctype<_CharT> &__ctype = use_facet<ctype<_CharT> >(__loc); 431 const numpunct<_CharT> &__numpunct = use_facet<numpunct<_CharT> >(__loc); 432 433 __iostring __buf ; 434 bool __ok = __read_float(__buf, __in_ite, __end, __ctype, __numpunct); 435 if (__ok) { 436 __string_to_float(__buf, __val); 437 __err = ios_base::goodbit; 438 } 439 else { 440 __err = ios_base::failbit; 441 } 442 if (__in_ite == __end) 443 __err |= ios_base::eofbit; 444 return __in_ite; 445} 446 447template <class _InputIter, class _CharT> 448_InputIter _STLP_CALL 449__do_get_alphabool(_InputIter& __in_ite, _InputIter& __end, ios_base& __str, 450 ios_base::iostate& __err, bool& __x, _CharT* /*__pc*/) { 451 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__str.getloc()); 452 const basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > __truename = __np.truename(); 453 const basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > __falsename = __np.falsename(); 454 bool __true_ok = true; 455 bool __false_ok = true; 456 457 size_t __n = 0; 458 for ( ; __in_ite != __end; ++__in_ite) { 459 _CharT __c = *__in_ite; 460 __true_ok = __true_ok && (__c == __truename[__n]); 461 __false_ok = __false_ok && (__c == __falsename[__n]); 462 ++__n; 463 464 if ((!__true_ok && !__false_ok) || 465 (__true_ok && __n >= __truename.size()) || 466 (__false_ok && __n >= __falsename.size())) { 467 ++__in_ite; 468 break; 469 } 470 } 471 if (__true_ok && __n < __truename.size()) __true_ok = false; 472 if (__false_ok && __n < __falsename.size()) __false_ok = false; 473 474 if (__true_ok || __false_ok) { 475 __err = ios_base::goodbit; 476 __x = __true_ok; 477 } 478 else 479 __err = ios_base::failbit; 480 481 if (__in_ite == __end) 482 __err |= ios_base::eofbit; 483 484 return __in_ite; 485} 486 487_STLP_MOVE_TO_STD_NAMESPACE 488 489// 490// num_get<>, num_put<> 491// 492 493template <class _CharT, class _InputIterator> 494locale::id num_get<_CharT, _InputIterator>::id; 495 496#if !defined (_STLP_NO_BOOL) 497template <class _CharT, class _InputIter> 498_InputIter 499num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, 500 ios_base& __s, ios_base::iostate& __err, bool& __x) const { 501 if (__s.flags() & ios_base::boolalpha) { 502 return _STLP_PRIV __do_get_alphabool(__in_ite, __end, __s, __err, __x, (_CharT*)0); 503 } 504 else { 505 long __lx; 506 _InputIter __tmp = _STLP_PRIV __do_get_integer(__in_ite, __end, __s, __err, __lx, (_CharT*)0 ); 507 if (!(__err & ios_base::failbit)) { 508 if (__lx == 0) 509 __x = false; 510 else if (__lx == 1) 511 __x = true; 512 else 513 __err |= ios_base::failbit; 514 } 515 return __tmp; 516 } 517} 518#endif 519 520#if defined (_STLP_FIX_LIBRARY_ISSUES) 521template <class _CharT, class _InputIter> 522_InputIter 523num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 524 ios_base::iostate& __err, short& __val) const 525{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 526 527template <class _CharT, class _InputIter> 528_InputIter 529num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 530 ios_base::iostate& __err, int& __val) const 531{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 532 533#endif 534 535template <class _CharT, class _InputIter> 536_InputIter 537num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 538 ios_base::iostate& __err, long& __val) const 539{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 540 541template <class _CharT, class _InputIter> 542_InputIter 543num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 544 ios_base::iostate& __err, 545 unsigned short& __val) const 546{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 547 548template <class _CharT, class _InputIter> 549_InputIter 550num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 551 ios_base::iostate& __err, 552 unsigned int& __val) const 553{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 554 555template <class _CharT, class _InputIter> 556_InputIter 557num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 558 ios_base::iostate& __err, 559 unsigned long& __val) const 560{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 561 562template <class _CharT, class _InputIter> 563_InputIter 564num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 565 ios_base::iostate& __err, 566 float& __val) const 567{ return _STLP_PRIV __do_get_float(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 568 569template <class _CharT, class _InputIter> 570_InputIter 571num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 572 ios_base::iostate& __err, 573 double& __val) const 574{ return _STLP_PRIV __do_get_float(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 575 576#if !defined (_STLP_NO_LONG_DOUBLE) 577template <class _CharT, class _InputIter> 578_InputIter 579num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 580 ios_base::iostate& __err, 581 long double& __val) const 582{ return _STLP_PRIV __do_get_float(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 583#endif 584 585template <class _CharT, class _InputIter> 586_InputIter 587num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 588 ios_base::iostate& __err, 589 void*& __p) const { 590#if defined (_STLP_LONG_LONG) && !defined (__MRC__) //*ty 12/07/2001 - MrCpp can not cast from long long to void* 591 unsigned _STLP_LONG_LONG __val; 592#else 593 unsigned long __val; 594#endif 595 iter_type __tmp = _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); 596 if (!(__err & ios_base::failbit)) 597 __p = __REINTERPRET_CAST(void*, __val); 598 return __tmp; 599} 600 601#if defined (_STLP_LONG_LONG) 602template <class _CharT, class _InputIter> 603_InputIter 604num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 605 ios_base::iostate& __err, 606 _STLP_LONG_LONG& __val) const 607{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 608 609template <class _CharT, class _InputIter> 610_InputIter 611num_get<_CharT, _InputIter>::do_get(_InputIter __in_ite, _InputIter __end, ios_base& __str, 612 ios_base::iostate& __err, 613 unsigned _STLP_LONG_LONG& __val) const 614{ return _STLP_PRIV __do_get_integer(__in_ite, __end, __str, __err, __val, (_CharT*)0 ); } 615#endif 616 617_STLP_END_NAMESPACE 618 619#endif /* _STLP_NUMERIC_FACETS_C */ 620 621// Local Variables: 622// mode:C++ 623// End: 624