/home/ntakagi/work/STLport-5.1.5/stlport/stl/_monetary.c

Go 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  doxygen 1.5.1