/home/ntakagi/work/STLport-5.1.5/stlport/stl/_monetary.cGo to the documentation of this file.00001 /* 00002 * Copyright (c) 1999 00003 * Silicon Graphics Computer Systems, Inc. 00004 * 00005 * Copyright (c) 1999 00006 * Boris Fomitchev 00007 * 00008 * This material is provided "as is", with absolutely no warranty expressed 00009 * or implied. Any use is at your own risk. 00010 * 00011 * Permission to use or copy this software for any purpose is hereby granted 00012 * without fee, provided the above notices are retained on all copies. 00013 * Permission to modify the code and to distribute modified code is granted, 00014 * provided the above notices are retained, and a notice that the code was 00015 * modified is included with the above copyright notice. 00016 * 00017 */ 00018 #ifndef _STLP_MONETARY_C 00019 #define _STLP_MONETARY_C 00020 00021 # ifndef _STLP_INTERNAL_MONETARY_H 00022 # include <stl/_monetary.h> 00023 # endif 00024 00025 #ifndef _STLP_INTERNAL_IOS_H 00026 # include <stl/_ios.h> 00027 #endif 00028 00029 #ifndef _STLP_INTERNAL_NUM_PUT_H 00030 # include <stl/_num_put.h> 00031 #endif 00032 00033 #ifndef _STLP_INTERNAL_NUM_GET_H 00034 # include <stl/_num_get.h> 00035 #endif 00036 00037 _STLP_BEGIN_NAMESPACE 00038 00039 #if (_STLP_STATIC_TEMPLATE_DATA > 0) 00040 00041 # if !defined (__BORLANDC__) 00042 template <class _CharT, class _InputIterator> 00043 locale::id money_get<_CharT, _InputIterator>::id; 00044 00045 template <class _CharT, class _OutputIterator> 00046 locale::id money_put<_CharT, _OutputIterator>::id; 00047 # endif 00048 00049 # if (defined (__CYGWIN__) || defined (__MINGW32__)) && \ 00050 defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT) 00051 /* 00052 * Under cygwin, when STLport is used as a shared library, the id needs 00053 * to be specified as imported otherwise they will be duplicated in the 00054 * calling executable. 00055 */ 00056 template <> 00057 _STLP_DECLSPEC locale::id money_get<char, istreambuf_iterator<char, char_traits<char> > >::id; 00058 /* 00059 template <> 00060 _STLP_DECLSPEC locale::id money_get<char, const char*>::id; 00061 */ 00062 00063 template <> 00064 _STLP_DECLSPEC locale::id money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id; 00065 template <> 00066 _STLP_DECLSPEC locale::id money_put<char, char*>::id; 00067 00068 # if !defined (_STLP_NO_WCHAR_T) 00069 template <> 00070 _STLP_DECLSPEC locale::id money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; 00071 template <> 00072 _STLP_DECLSPEC locale::id money_get<wchar_t, const wchar_t*>::id; 00073 00074 template <> 00075 _STLP_DECLSPEC locale::id money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id; 00076 template <> 00077 _STLP_DECLSPEC locale::id money_put<wchar_t, wchar_t*>::id; 00078 # endif 00079 00080 # endif 00081 00082 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ 00083 00084 //typedef money_get<char, const char*> money_get_char; 00085 //typedef money_put<char, char*> money_put_char; 00086 typedef money_get<char, istreambuf_iterator<char, char_traits<char> > > money_get_char_2; 00087 typedef money_put<char, ostreambuf_iterator<char, char_traits<char> > > money_put_char_2; 00088 00089 //__DECLARE_INSTANCE(locale::id, money_get_char::id, ); 00090 //__DECLARE_INSTANCE(locale::id, money_put_char::id, ); 00091 __DECLARE_INSTANCE(locale::id, money_get_char_2::id, ); 00092 __DECLARE_INSTANCE(locale::id, money_put_char_2::id, ); 00093 00094 # ifndef _STLP_NO_WCHAR_T 00095 00096 //typedef money_get<wchar_t, const wchar_t*> money_get_wchar_t; 00097 //typedef money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_get_wchar_t_2; 00098 typedef money_put<wchar_t, wchar_t*> money_put_wchar_t; 00099 typedef money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_put_wchar_t_2; 00100 00101 //__DECLARE_INSTANCE(locale::id, money_get_wchar_t::id, ); 00102 //__DECLARE_INSTANCE(locale::id, money_put_wchar_t::id, ); 00103 __DECLARE_INSTANCE(locale::id, money_get_wchar_t_2::id, ); 00104 __DECLARE_INSTANCE(locale::id, money_put_wchar_t_2::id, ); 00105 00106 # endif 00107 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ 00108 00109 // money_get facets 00110 00111 _STLP_MOVE_TO_PRIV_NAMESPACE 00112 00113 // helper functions for do_get 00114 template <class _InIt1, class _InIt2> 00115 pair<_InIt1, bool> __get_string( _InIt1 __first, _InIt1 __last, 00116 _InIt2 __str_first, _InIt2 __str_last) { 00117 while ( __first != __last && __str_first != __str_last && *__first == *__str_first ) { 00118 ++__first; 00119 ++__str_first; 00120 } 00121 return make_pair(__first, __str_first == __str_last); 00122 } 00123 00124 template <class _InIt, class _OuIt, class _CharT> 00125 bool 00126 __get_monetary_value(_InIt& __first, _InIt __last, _OuIt __out_ite, 00127 const ctype<_CharT>& _c_type, 00128 _CharT __point, int __frac_digits, _CharT __sep, 00129 const string& __grouping, bool &__syntax_ok) { 00130 if (__first == __last || !_c_type.is(ctype_base::digit, *__first)) 00131 return false; 00132 00133 char __group_sizes[128]; 00134 char* __group_sizes_end = __grouping.empty()? 0 : __group_sizes; 00135 char __current_group_size = 0; 00136 00137 while (__first != __last) { 00138 if (_c_type.is(ctype_base::digit, *__first)) { 00139 ++__current_group_size; 00140 *__out_ite++ = *__first++; 00141 } 00142 else if (__group_sizes_end) { 00143 if (*__first == __sep) { 00144 *__group_sizes_end++ = __current_group_size; 00145 __current_group_size = 0; 00146 ++__first; 00147 } 00148 else break; 00149 } 00150 else 00151 break; 00152 } 00153 00154 if (__grouping.empty()) 00155 __syntax_ok = true; 00156 else { 00157 if (__group_sizes_end != __group_sizes) 00158 *__group_sizes_end++ = __current_group_size; 00159 00160 __syntax_ok = __valid_grouping(__group_sizes, __group_sizes_end, 00161 __grouping.data(), __grouping.data()+ __grouping.size()); 00162 00163 if (__first == __last || *__first != __point) { 00164 for (int __digits = 0; __digits != __frac_digits; ++__digits) 00165 *__out_ite++ = _CharT('0'); 00166 return true; // OK not to have decimal point 00167 } 00168 } 00169 00170 ++__first; 00171 00172 int __digits = 0; 00173 00174 while (__first != __last && _c_type.is(ctype_base::digit, *__first)) { 00175 *__out_ite++ = *__first++; 00176 ++__digits; 00177 } 00178 00179 __syntax_ok = __syntax_ok && (__digits == __frac_digits); 00180 00181 return true; 00182 } 00183 00184 00185 template <class _CharT, class _InputIter, class _StrType> 00186 _InputIter __money_do_get(_InputIter __s, _InputIter __end, bool __intl, 00187 ios_base& __str, ios_base::iostate& __err, 00188 _StrType& __digits, bool &__is_positive, _CharT* /*__dummy*/) { 00189 if (__s == __end) { 00190 __err |= ios_base::eofbit; 00191 return __s; 00192 } 00193 00194 typedef _CharT char_type; 00195 typedef _StrType string_type; 00196 typedef _InputIter iter_type; 00197 typedef moneypunct<char_type, false> _Punct; 00198 typedef moneypunct<char_type, true> _Punct_intl; 00199 typedef ctype<char_type> _Ctype; 00200 00201 locale __loc = __str.getloc(); 00202 const _Punct& __punct = use_facet<_Punct>(__loc) ; 00203 const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ; 00204 const _Ctype& __c_type = use_facet<_Ctype>(__loc) ; 00205 00206 money_base::pattern __format = __intl ? __punct_intl.neg_format() 00207 : __punct.neg_format(); 00208 string_type __ns = __intl ? __punct_intl.negative_sign() 00209 : __punct.negative_sign(); 00210 string_type __ps = __intl ? __punct_intl.positive_sign() 00211 : __punct.positive_sign(); 00212 int __i; 00213 bool __symbol_required = (__str.flags() & ios_base::showbase) != 0; 00214 string_type __buf; 00215 back_insert_iterator<string_type> __out_ite(__buf); 00216 00217 for (__i = 0; __i < 4; ++__i) { 00218 switch (__format.field[__i]) { 00219 case money_base::none: 00220 if (__i == 3) { 00221 if (__c_type.is(ctype_base::space, *__s)) { 00222 __err = ios_base::failbit; 00223 return __s; 00224 } 00225 break; 00226 } 00227 while (__s != __end && __c_type.is(ctype_base::space, *__s)) 00228 ++__s; 00229 break; 00230 case money_base::space: 00231 if (!__c_type.is(ctype_base::space, *__s)) { 00232 __err = ios_base::failbit; 00233 return __s; 00234 } 00235 ++__s; 00236 while (__s != __end && __c_type.is(ctype_base::space, *__s)) 00237 ++__s; 00238 break; 00239 case money_base::symbol: { 00240 string_type __curs = __intl ? __punct_intl.curr_symbol() 00241 : __punct.curr_symbol(); 00242 pair<iter_type, bool> 00243 __result = __get_string(__s, __end, __curs.begin(), __curs.end()); 00244 if (!__result.second && __symbol_required) 00245 __err = ios_base::failbit; 00246 __s = __result.first; 00247 break; 00248 } 00249 case money_base::sign: { 00250 if (__s == __end) { 00251 if (__ps.empty()) 00252 break; 00253 if (__ns.empty()) { 00254 __is_positive = false; 00255 break; 00256 } 00257 __err = ios_base::failbit; 00258 return __s; 00259 } 00260 else { 00261 if (__ps.empty()) { 00262 if (__ns.empty()) 00263 break; 00264 if (*__s == __ns[0]) { 00265 ++__s; 00266 __is_positive = false; 00267 } 00268 break; 00269 } 00270 else { 00271 if (*__s == __ps[0]) { 00272 ++__s; 00273 break; 00274 } 00275 if (__ns.empty()) 00276 break; 00277 if (*__s == __ns[0]) { 00278 ++__s; 00279 __is_positive = false; 00280 break; 00281 } 00282 __err = ios_base::failbit; 00283 } 00284 } 00285 return __s; 00286 } 00287 case money_base::value: { 00288 char_type __point = __intl ? __punct_intl.decimal_point() 00289 : __punct.decimal_point(); 00290 int __frac_digits = __intl ? __punct_intl.frac_digits() 00291 : __punct.frac_digits(); 00292 string __grouping = __intl ? __punct_intl.grouping() 00293 : __punct.grouping(); 00294 bool __syntax_ok = true; 00295 00296 bool __result; 00297 00298 char_type __sep = __grouping.empty() ? char_type() : 00299 __intl ? __punct_intl.thousands_sep() : __punct.thousands_sep(); 00300 00301 __result = __get_monetary_value(__s, __end, __out_ite, __c_type, 00302 __point, __frac_digits, 00303 __sep, 00304 __grouping, __syntax_ok); 00305 00306 if (!__syntax_ok) 00307 __err |= ios_base::failbit; 00308 if (!__result) { 00309 __err = ios_base::failbit; 00310 return __s; 00311 } 00312 break; 00313 00314 } // Close money_base::value case 00315 } // Close switch statement 00316 } // Close for loop 00317 00318 if (__is_positive) { 00319 if (__ps.size() > 1) { 00320 pair<_InputIter, bool> 00321 __result = __get_string(__s, __end, __ps.begin() + 1, __ps.end()); 00322 __s = __result.first; 00323 if (!__result.second) 00324 __err |= ios::failbit; 00325 } 00326 if (!(__err & ios_base::failbit)) 00327 __digits = __buf; 00328 } 00329 else { 00330 if (__ns.size() > 1) { 00331 pair<_InputIter, bool> 00332 __result = __get_string(__s, __end, __ns.begin() + 1, __ns.end()); 00333 __s = __result.first; 00334 if (!__result.second) 00335 __err |= ios::failbit; 00336 } 00337 if (!(__err & ios::failbit)) { 00338 __digits = __c_type.widen('-'); 00339 __digits += __buf; 00340 } 00341 } 00342 if (__s == __end) 00343 __err |= ios::eofbit; 00344 00345 return __s; 00346 } 00347 00348 _STLP_MOVE_TO_STD_NAMESPACE 00349 00350 //===== methods ====== 00351 template <class _CharT, class _InputIter> 00352 _InputIter 00353 money_get<_CharT, _InputIter>::do_get(_InputIter __s, _InputIter __end, bool __intl, 00354 ios_base& __str, ios_base::iostate& __err, 00355 _STLP_LONGEST_FLOAT_TYPE& __units) const { 00356 string_type __buf; 00357 bool __is_positive = true; 00358 __s = _STLP_PRIV __money_do_get(__s, __end, __intl, __str, __err, __buf, __is_positive, (_CharT*)0); 00359 00360 if (__err == ios_base::goodbit || __err == ios_base::eofbit) { 00361 typename string_type::iterator __b = __buf.begin(), __e = __buf.end(); 00362 00363 if (!__is_positive) ++__b; 00364 // Can't use atold, since it might be wchar_t. Don't get confused by name below : 00365 // it's perfectly capable of reading long double. 00366 _STLP_PRIV __get_decimal_integer(__b, __e, __units, (_CharT*)0); 00367 00368 if (!__is_positive) { 00369 __units = -__units; 00370 } 00371 } 00372 00373 return __s; 00374 } 00375 00376 template <class _CharT, class _InputIter> 00377 _InputIter 00378 money_get<_CharT, _InputIter>::do_get(iter_type __s, iter_type __end, bool __intl, 00379 ios_base& __str, ios_base::iostate& __err, 00380 string_type& __digits) const { 00381 bool __is_positive = true; 00382 return _STLP_PRIV __money_do_get(__s, __end, __intl, __str, __err, __digits, __is_positive, (_CharT*)0); 00383 } 00384 00385 // money_put facets 00386 00387 _STLP_MOVE_TO_PRIV_NAMESPACE 00388 00389 template <class _CharT, class _OutputIter, class _Str_Type, class _Str> 00390 _OutputIter __money_do_put(_OutputIter __s, bool __intl, ios_base& __str, 00391 _CharT __fill, const _Str& __digits, bool __check_digits, 00392 _Str_Type * /*__dummy*/) { 00393 typedef _CharT char_type; 00394 typedef _Str_Type string_type; 00395 typedef ctype<char_type> _Ctype; 00396 typedef moneypunct<char_type, false> _Punct; 00397 typedef moneypunct<char_type, true> _Punct_intl; 00398 00399 locale __loc = __str.getloc(); 00400 const _Ctype& __c_type = use_facet<_Ctype>(__loc) ; 00401 const _Punct& __punct = use_facet<_Punct>(__loc) ; 00402 const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ; 00403 00404 // some special characters 00405 char_type __minus = __c_type.widen('-'); 00406 char_type __plus = __c_type.widen('+'); 00407 char_type __space = __c_type.widen(' '); 00408 char_type __zero = __c_type.widen('0'); 00409 char_type __point = __intl ? __punct_intl.decimal_point() 00410 : __punct.decimal_point(); 00411 00412 char_type __sep = __intl ? __punct_intl.thousands_sep() 00413 : __punct.thousands_sep(); 00414 00415 string __grouping = __intl ? __punct_intl.grouping() 00416 : __punct.grouping(); 00417 00418 int __frac_digits = __intl ? __punct_intl.frac_digits() 00419 : __punct.frac_digits(); 00420 00421 string_type __curr_sym = __intl ? __punct_intl.curr_symbol() 00422 : __punct.curr_symbol(); 00423 00424 // if there are no digits we are going to return __s. If there 00425 // are digits, but not enough to fill the frac_digits, we are 00426 // going to add zeros. I don't know whether this is right or 00427 // not. 00428 if (__digits.empty()) 00429 return __s; 00430 00431 typename string_type::const_iterator __digits_first = __digits.begin(); 00432 typename string_type::const_iterator __digits_last = __digits.end(); 00433 00434 bool __is_negative = *__digits_first == __minus; 00435 if (__is_negative) 00436 ++__digits_first; 00437 00438 #if !defined (__BORLANDC__) 00439 string_type __sign = __intl ? __is_negative ? __punct_intl.negative_sign() 00440 : __punct_intl.positive_sign() 00441 : __is_negative ? __punct.negative_sign() 00442 : __punct.positive_sign(); 00443 #else 00444 string_type __sign; 00445 if (__intl) { 00446 if (__is_negative) 00447 __sign = __punct_intl.negative_sign(); 00448 else 00449 __sign = __punct_intl.positive_sign(); 00450 } 00451 else { 00452 if (__is_negative) 00453 __sign = __punct.negative_sign(); 00454 else 00455 __sign = __punct.positive_sign(); 00456 } 00457 #endif 00458 00459 if (__check_digits) { 00460 typename string_type::const_iterator __cp = __digits_first; 00461 while (__cp != __digits_last && __c_type.is(ctype_base::digit, *__cp)) 00462 ++__cp; 00463 if (__cp == __digits_first) 00464 return __s; 00465 __digits_last = __cp; 00466 } 00467 00468 // If grouping is required, we make a copy of __digits and 00469 // insert the grouping. 00470 _STLP_BASIC_IOSTRING(char_type) __new_digits; 00471 if (!__grouping.empty()) { 00472 __new_digits.assign(__digits_first, __digits_last); 00473 __insert_grouping(__new_digits, 00474 __new_digits.size() - __frac_digits, 00475 __grouping, 00476 __sep, __plus, __minus, 0); 00477 __digits_first = __new_digits.begin(); // <<-- 00478 __digits_last = __new_digits.end(); // <<-- 00479 } 00480 00481 // Determine the amount of padding required, if any. 00482 streamsize __width = __str.width(); 00483 00484 #if defined (_STLP_DEBUG) && (defined(__HP_aCC) && (__HP_aCC <= 1)) 00485 size_t __value_length = operator -(__digits_last, __digits_first); 00486 #else 00487 size_t __value_length = __digits_last - __digits_first; 00488 #endif 00489 00490 size_t __length = __value_length + __sign.size(); 00491 00492 if (__frac_digits != 0) 00493 ++__length; 00494 00495 bool __generate_curr = (__str.flags() & ios_base::showbase) !=0; 00496 if (__generate_curr) 00497 __length += __curr_sym.size(); 00498 money_base::pattern __format = __intl ? (__is_negative ? __punct_intl.neg_format() 00499 : __punct_intl.pos_format()) 00500 : (__is_negative ? __punct.neg_format() 00501 : __punct.pos_format()); 00502 { 00503 //For the moment the following is commented for decoding reason. 00504 //No reason to add a space last if the money symbol do not have to be display 00505 //if (__format.field[3] == (char) money_base::symbol && !__generate_curr) { 00506 // if (__format.field[2] == (char) money_base::space) { 00507 // __format.field[2] = (char) money_base::none; 00508 // } 00509 //} 00510 //space can only be second or third and only once (22.2.6.3-1): 00511 if ((__format.field[1] == (char) money_base::space) || 00512 (__format.field[2] == (char) money_base::space)) 00513 ++__length; 00514 } 00515 00516 const bool __need_fill = (((sizeof(streamsize) > sizeof(size_t)) && (__STATIC_CAST(streamsize, __length) < __width)) || 00517 ((sizeof(streamsize) <= sizeof(size_t)) && (__length < __STATIC_CAST(size_t, __width)))); 00518 streamsize __fill_amt = __need_fill ? __width - __length : 0; 00519 00520 ios_base::fmtflags __fill_pos = __str.flags() & ios_base::adjustfield; 00521 00522 if (__fill_amt != 0 && 00523 !(__fill_pos & (ios_base::left | ios_base::internal))) 00524 __s = __fill_n(__s, __fill_amt, __fill); 00525 00526 for (int __i = 0; __i < 4; ++__i) { 00527 char __ffield = __format.field[__i]; 00528 switch (__ffield) { 00529 case money_base::none: 00530 if (__fill_amt != 0 && __fill_pos == ios_base::internal) 00531 __s = __fill_n(__s, __fill_amt, __fill); 00532 break; 00533 case money_base::space: 00534 *__s++ = __space; 00535 if (__fill_amt != 0 && __fill_pos == ios_base::internal) 00536 __s = __fill_n(__s, __fill_amt, __fill); 00537 break; 00538 case money_base::symbol: 00539 if (__generate_curr) 00540 __s = copy(__curr_sym.begin(), __curr_sym.end(), __s); 00541 break; 00542 case money_base::sign: 00543 if (!__sign.empty()) 00544 *__s++ = __sign[0]; 00545 break; 00546 case money_base::value: 00547 if (__frac_digits == 0) { 00548 __s = copy(__digits_first, __digits_last, __s); 00549 } else { 00550 if ((int)__value_length <= __frac_digits) { 00551 // if we see '9' here, we should out 0.09 00552 *__s++ = __zero; // integer part is zero 00553 *__s++ = __point; // decimal point 00554 __s = __fill_n(__s, __frac_digits - __value_length, __zero); // zeros 00555 __s = copy(__digits_first, __digits_last, __s); // digits 00556 } else { 00557 __s = copy(__digits_first, __digits_last - __frac_digits, __s); 00558 if (__frac_digits != 0) { 00559 *__s++ = __point; 00560 __s = copy(__digits_last - __frac_digits, __digits_last, __s); 00561 } 00562 } 00563 } 00564 break; 00565 } //Close for switch 00566 } // Close for loop 00567 00568 // Ouput rest of sign if necessary. 00569 if (__sign.size() > 1) 00570 __s = copy(__sign.begin() + 1, __sign.end(), __s); 00571 if (__fill_amt != 0 && 00572 !(__fill_pos & (ios_base::right | ios_base::internal))) 00573 __s = __fill_n(__s, __fill_amt, __fill); 00574 00575 return __s; 00576 } 00577 00578 _STLP_MOVE_TO_STD_NAMESPACE 00579 00580 template <class _CharT, class _OutputIter> 00581 _OutputIter 00582 money_put<_CharT, _OutputIter> 00583 ::do_put(_OutputIter __s, bool __intl, ios_base& __str, 00584 char_type __fill, _STLP_LONGEST_FLOAT_TYPE __units) const { 00585 _STLP_BASIC_IOSTRING(char_type) __digits; 00586 _STLP_PRIV __get_money_digits(__digits, __str, __units); 00587 return _STLP_PRIV __money_do_put(__s, __intl, __str, __fill, __digits, false, __STATIC_CAST(string_type*, 0)); 00588 } 00589 00590 template <class _CharT, class _OutputIter> 00591 _OutputIter 00592 money_put<_CharT, _OutputIter> 00593 ::do_put(_OutputIter __s, bool __intl, ios_base& __str, 00594 char_type __fill, const string_type& __digits) const { 00595 return _STLP_PRIV __money_do_put(__s, __intl, __str, __fill, __digits, true, __STATIC_CAST(string_type*, 0)); 00596 } 00597 00598 _STLP_END_NAMESPACE 00599 00600 #endif /* _STLP_MONETARY_C */ 00601 00602 // Local Variables: 00603 // mode:C++ 00604 // End:
Generated on Mon Mar 10 15:32:31 2008 by ![]() |