home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / stlport / stl / _monetary.c < prev    next >
C/C++ Source or Header  |  2002-02-02  |  16KB  |  528 lines

  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_MONETARY_C
  19. #define _STLP_MONETARY_C
  20.  
  21. # ifndef _STLP_INTERNAL_MONETARY_H
  22. #  include <stl/_monetary.h>
  23. # endif
  24.  
  25. # if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION)
  26.  
  27. #ifndef _STLP_INTERNAL_IOS_H
  28. # include <stl/_ios.h>
  29. #endif
  30.  
  31. #ifndef _STLP_INTERNAL_NUM_PUT_H
  32. # include <stl/_num_put.h>
  33. #endif
  34.  
  35. #ifndef _STLP_INTERNAL_NUM_GET_H
  36. # include <stl/_num_get.h>
  37. #endif
  38.  
  39. _STLP_BEGIN_NAMESPACE
  40.  
  41. # if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
  42.  
  43. template <class _CharT, class _InputIterator>
  44. locale::id money_get<_CharT, _InputIterator>::id;
  45.  
  46. template <class _CharT, class _OutputIterator>
  47. locale::id money_put<_CharT, _OutputIterator>::id;
  48.  
  49. # else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
  50.  
  51. typedef money_get<char, const char*> money_get_char;
  52. typedef money_put<char, char*> money_put_char;
  53. typedef money_get<char, istreambuf_iterator<char, char_traits<char> > > money_get_char_2;
  54. typedef money_put<char, ostreambuf_iterator<char, char_traits<char> > > money_put_char_2;
  55.  
  56. __DECLARE_INSTANCE(locale::id, money_get_char::id, );
  57. __DECLARE_INSTANCE(locale::id, money_put_char::id, );
  58. __DECLARE_INSTANCE(locale::id, money_get_char_2::id, );
  59. __DECLARE_INSTANCE(locale::id, money_put_char_2::id, );
  60.  
  61. # ifndef _STLP_NO_WCHAR_T
  62.  
  63. typedef money_get<wchar_t, const wchar_t*> money_get_wchar_t;
  64. typedef money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_get_wchar_t_2;
  65. typedef money_put<wchar_t, wchar_t*> money_put_wchar_t;
  66. typedef money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_put_wchar_t_2;
  67.  
  68. __DECLARE_INSTANCE(locale::id, money_get_wchar_t::id, );
  69. __DECLARE_INSTANCE(locale::id, money_put_wchar_t::id, );
  70. __DECLARE_INSTANCE(locale::id, money_get_wchar_t_2::id, );
  71. __DECLARE_INSTANCE(locale::id, money_put_wchar_t_2::id, );
  72.  
  73. # endif
  74. # endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
  75.  
  76. // money_get facets
  77.  
  78.  
  79. // helper functions for do_get
  80. template <class _InIt1, class _InIt2>
  81. pair<_InIt1, bool> __get_string(_InIt1 __first,     _InIt1 __last,
  82.                                _InIt2 __str_first, _InIt2 __str_last) {
  83.   pair<_InIt1, _InIt2> __pr = mismatch(__first, __last, __str_first);
  84.   return make_pair(__pr.first, __pr.second == __str_last);
  85. }
  86.  
  87. template <class _InIt, class _OuIt, class _CharT>
  88. bool
  89. __get_monetary_value(_InIt& __first, _InIt __last, _OuIt __out,
  90.                      const ctype<_CharT>& _c_type,
  91.                      _CharT   __point,
  92.                      int      __frac_digits,
  93.                      _CharT __sep,
  94.                      const string& __grouping,
  95.                      bool&         __syntax_ok)
  96. {
  97.   if (__first == __last || !_c_type.is(ctype_base::digit, *__first))
  98.     return false;
  99.  
  100.   char __group_sizes[128];
  101.   char* __group_sizes_end = __grouping.size() == 0 ? 0 : __group_sizes;
  102.   char   __current_group_size = 0;
  103.  
  104.   while (__first != __last) {
  105.     if (_c_type.is(ctype_base::digit, *__first)) {
  106.       ++__current_group_size;
  107.       *__out++ = *__first++;
  108.     }
  109.     else if (__group_sizes_end) {
  110.       if (*__first == __sep) {
  111.     *__group_sizes_end++ = __current_group_size;
  112.     __current_group_size = 0;
  113.     ++__first;
  114.       }
  115.       else break;
  116.     }
  117.     else
  118.       break;
  119.   }
  120.  
  121.   if (__grouping.size() == 0)
  122.     __syntax_ok = true;
  123.   else {
  124.     if (__group_sizes_end != __group_sizes)
  125.       *__group_sizes_end++ = __current_group_size;
  126.     
  127.     __syntax_ok = __valid_grouping(__group_sizes, __group_sizes_end,
  128.                                    __grouping.data(), __grouping.data()+ __grouping.size());  
  129.     
  130.     if (__first == __last || *__first != __point) {
  131.       for (int __digits = 0; __digits != __frac_digits; ++__digits)
  132.         *__out++ = _CharT('0');
  133.       return true; // OK not to have decimal point
  134.     }
  135.   }
  136.  
  137.   ++__first;
  138.  
  139.   size_t __digits = 0;
  140.  
  141.   while (__first != __last && _c_type.is(ctype_base::digit, *__first)) {
  142.       *__out++ = *__first++;
  143.      ++__digits;
  144.   }
  145.  
  146.   __syntax_ok = __syntax_ok && (__digits == __frac_digits);
  147.  
  148.   return true;
  149. }
  150.  
  151. # ifndef _STLP_NO_LONG_DOUBLE
  152.  
  153. //===== methods ======
  154. template <class _CharT, class _InputIter>
  155. _InputIter 
  156. money_get<_CharT, _InputIter>::do_get(_InputIter __s, _InputIter  __end, bool  __intl,
  157.                       ios_base&  __str, ios_base::iostate& __err,
  158.                       long double& __units) const {
  159.   string_type __buf;
  160.   __s = do_get(__s, __end, __intl, __str, __err, __buf);
  161.  
  162.   if (__err == ios_base::goodbit || __err == ios_base::eofbit) {
  163.     __buf.push_back(0);
  164.     typename string_type::iterator __b = __buf.begin(), __e = __buf.end();
  165.     // Can't use atold, since it might be wchar_t. Don't get confused by name below :
  166.     // it's perfectly capable of reading long double.
  167.     __get_decimal_integer(__b, __e, __units);
  168.   }
  169.   if (__s == __end)
  170.     __err |= ios_base::eofbit;
  171.   return __s;
  172. }
  173. # endif
  174.  
  175. template <class _CharT, class _InputIter>
  176. _InputIter 
  177. money_get<_CharT, _InputIter>::do_get(iter_type __s, 
  178.                       iter_type  __end, bool  __intl,
  179.                       ios_base&  __str, ios_base::iostate&  __err,
  180.                       string_type& __digits) const {
  181.   if (__s == __end) {
  182.     __err |= ios_base::eofbit;
  183.     return __s;
  184.   }
  185.  
  186.   typedef moneypunct<_CharT, false> _Punct;
  187.   typedef moneypunct<_CharT, true>  _Punct_intl;
  188.   typedef ctype<_CharT>             _Ctype;
  189.  
  190.   locale __loc = __str.getloc();
  191.   const _Punct&      __punct      = use_facet<_Punct>(__loc) ;
  192.   const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ;
  193.   const _Ctype&      __c_type      = use_facet<_Ctype>(__loc) ;
  194.                    
  195.   money_base::pattern __format = __intl ? __punct_intl.neg_format()
  196.                                         : __punct.neg_format();
  197.   string_type __ns = __intl ? __punct_intl.negative_sign()
  198.                             : __punct.negative_sign();
  199.   string_type __ps = __intl ? __punct_intl.positive_sign()
  200.                             : __punct.positive_sign();
  201.   int __i;
  202.   bool __is_positive = true;
  203.   bool __symbol_required = (__str.flags() & ios_base::showbase) !=0;
  204.   string_type __buf;
  205.   back_insert_iterator<string_type> __out(__buf);
  206. //  pair<iter_type, bool> __result;
  207.  
  208.   for (__i = 0; __i < 4; ++__i) {
  209.     switch (__format.field[__i]) {
  210.     case (char) money_base::none:
  211.       if (__i == 3) {
  212.         if (__c_type.is(ctype_base::space, *__s)) {
  213.           __err = ios_base::failbit;
  214.           return __s;
  215.         }
  216.         break;
  217.       }
  218.       while (__s != __end && __c_type.is(ctype_base::space, *__s))
  219.         ++__s;
  220.       break;
  221.     case (char) money_base::space:
  222.       if (!__c_type.is(ctype_base::space, *__s)) {
  223.         __err = ios_base::failbit;
  224.         return __s;
  225.       }
  226.       ++__s;
  227.       while (__s != __end && __c_type.is(ctype_base::space, *__s))
  228.         ++__s;
  229.       break;
  230.     case money_base::symbol: {
  231.       string_type __cs = __intl ? __punct_intl.curr_symbol()
  232.                                 : __punct.curr_symbol();
  233.       pair<iter_type, bool>
  234.       __result  = __get_string(__s, __end, __cs.begin(), __cs.end());
  235.       if (!__result.second && __symbol_required)
  236.         __err = ios_base::failbit;
  237.       __s = __result.first;
  238.       break;
  239.     }
  240.     case money_base::sign: {
  241.       if (__s == __end) {
  242.         if (__ps.size() == 0)
  243.           break;
  244.         if (__ns.size() == 0) {
  245.           __is_positive = false;
  246.           break;
  247.         }
  248.         __err = ios_base::failbit;
  249.         return __s;
  250.       }
  251.       else {
  252.         if (__ps.size() == 0) {
  253.           if (__ns.size() == 0)
  254.             break;
  255.           if (*__s == ++__ns[0]) {
  256.             ++__s;
  257.             __is_positive = false;
  258.             break;
  259.           }
  260.           __err = ios_base::failbit;
  261.       //          return __s;
  262.         } 
  263.         else {
  264.           if (*__s == __ps[0]) {
  265.             ++__s;
  266.             break;
  267.           }
  268.           if (__ns.size() == 0)
  269.             break;
  270.           if (*__s == __ns[0]) {
  271.             ++__s;
  272.             __is_positive = false;
  273.             break;
  274.           }
  275.           __err = ios_base::failbit;
  276.       //          return __s;
  277.         }
  278.       }
  279.       return __s;
  280.       //      break;
  281.     }
  282.     case money_base::value: {
  283.       _CharT __point = __intl ? __punct_intl.decimal_point()
  284.                               : __punct.decimal_point();
  285.       int __frac_digits = __intl ? __punct_intl.frac_digits()
  286.                                  : __punct.frac_digits();
  287.       string __grouping = __intl ? __punct_intl.grouping()
  288.                                  : __punct.grouping();
  289.       bool __syntax_ok = true;
  290.  
  291.       bool __result;
  292.  
  293.       _CharT __sep = __grouping.size() == 0 ? _CharT() : 
  294.     __intl ? __punct_intl.thousands_sep() : __punct.thousands_sep();
  295.  
  296.       __result = __get_monetary_value(__s, __end, __out, __c_type,
  297.                                       __point, __frac_digits,
  298.                                       __sep,
  299.                                       __grouping, __syntax_ok);      
  300.  
  301.       if (!__syntax_ok)
  302.         __err |= ios_base::failbit;
  303.       if (!__result) {
  304.         __err = ios_base::failbit;
  305.         return __s;
  306.       }
  307.       break;
  308.       
  309.     }                           // Close money_base::value case
  310.  
  311.  
  312.     }                           // Close switch statement
  313.   }                             // Close for loop
  314.  
  315.   if (__is_positive) {
  316.     if (__ps.size() > 1) {
  317.       pair<_InputIter, bool>
  318.         __result = __get_string(__s, __end, __ps.begin() + 1, __ps.end());
  319.       __s = __result.first;
  320.       if (!__result.second)
  321.     __err |= ios::failbit;
  322.     }
  323.     if (!(__err & ios_base::failbit))
  324.       __digits = __buf;
  325.   }
  326.   else {
  327.     if (__ns.size() > 1) {
  328.       pair<_InputIter, bool>
  329.         __result = __get_string(__s, __end, __ns.begin() + 1, __ns.end());
  330.       __s = __result.first;
  331.       if (!__result.second)
  332.     __err |= ios::failbit;
  333.     }
  334.     if (!(__err & ios::failbit)) {
  335.       __buf.insert(__buf.begin(),__c_type.widen('-'));
  336.       __digits = __buf;
  337.     }
  338.   }
  339.   if (__s == __end)
  340.     __err |= ios::eofbit;
  341.  
  342.   return __s;
  343. }
  344.  
  345. // money_put facets
  346.  
  347. template <class _CharT, class _OutputIter>
  348. _OutputIter
  349. money_put<_CharT, _OutputIter>
  350.  ::do_put(_OutputIter __s, bool __intl, ios_base& __str,
  351.           char_type __fill,
  352.           const string_type& __digits) const { 
  353.   typedef ctype<_CharT>             _Ctype;
  354.   typedef moneypunct<_CharT, false> _Punct;
  355.   typedef moneypunct<_CharT, true>  _Punct_intl;
  356.  
  357.   locale __loc = __str.getloc();
  358.   const _Ctype&      __c_type      = use_facet<_Ctype>(__loc) ;
  359.   const _Punct&      __punct      = use_facet<_Punct>(__loc) ;
  360.   const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ;
  361.  
  362.   // some special characters
  363.  
  364.   char_type __minus = __c_type.widen('-');
  365.   char_type __plus  = __c_type.widen('+');
  366.   char_type __space = __c_type.widen(' ');
  367.   char_type __zero  = __c_type.widen('0');
  368.   char_type __point = __intl ? __c_type.widen(__punct_intl.decimal_point())
  369.                  : __c_type.widen(__punct.decimal_point());
  370.  
  371.   char_type __sep = __intl ? __punct_intl.thousands_sep()
  372.                : __punct     .thousands_sep();
  373.  
  374.   string __grouping = __intl ? __punct_intl.grouping()
  375.                      : __punct     .grouping();
  376.                 
  377.   int __frac_digits      = __intl ? __punct_intl.frac_digits() 
  378.                                   : __punct.frac_digits();
  379.  
  380.   string_type __curr_sym = __intl ? __punct_intl.curr_symbol() 
  381.                                   : __punct.curr_symbol();
  382.  
  383.     // if there are no digits we are going to return __s.  If there
  384.     // are digits, but not enough to fill the frac_digits, we are
  385.     // going to add zeros.  I don't know whether this is right or
  386.     // not.
  387.  
  388.   if (__digits.size() == 0) 
  389.     return __s;
  390.  
  391.   typename string_type::const_iterator __digits_first = __digits.begin();
  392.   typename string_type::const_iterator __digits_last  = __digits.end();
  393.  
  394.   bool __is_negative = *__digits_first == __minus;
  395.   if (__is_negative)
  396.     ++__digits_first;
  397.  
  398.   string_type __sign = __intl ?
  399.              __is_negative ? __punct_intl.negative_sign()
  400.                        : __punct_intl.positive_sign()
  401.                   :
  402.              __is_negative ? __punct.negative_sign()
  403.                        : __punct.positive_sign();
  404.   typename string_type::const_iterator __cp = __digits_first;
  405.   while (__cp != __digits_last && __c_type.is(ctype_base::digit, *__cp))
  406.     ++__cp;
  407.   if (__cp == __digits_first)
  408.     return __s;
  409.   __digits_last = __cp;
  410.  
  411.   // If grouping is required, we make a copy of __digits and
  412.   // insert the grouping.
  413.  
  414.   // To handle the fractional digits, we augment the first group
  415.   // by frac_digits.  If there is only one group, we need first
  416.   // to duplicate it.
  417.  
  418.   string_type __new_digits(__digits_first, __digits_last);
  419.  
  420.   if (__grouping.size() != 0) {
  421.     if (__grouping.size() == 1)
  422.       __grouping.push_back(__grouping[0]);
  423.     __grouping[0] += __frac_digits;
  424.     _CharT* __data_ptr = __CONST_CAST(_CharT*,__new_digits.data());
  425.     _CharT* __data_end = __data_ptr + __new_digits.size();
  426.     
  427.     ptrdiff_t __value_length = __insert_grouping(__data_ptr,
  428.                                __data_end,
  429.                              __grouping,
  430.                              __sep,
  431.                              __plus, __minus, 0);
  432.     __digits_first = __new_digits.begin();
  433.     __digits_last  = __digits_first + __value_length;
  434.   }
  435.  
  436.   // Determine the amount of padding required, if any.  
  437.     
  438.   size_t __width        = __str.width();
  439.  
  440. #if defined(_STLP_DEBUG) && (defined(__HP_aCC) || (__HP_aCC <= 1))
  441.   size_t __value_length = operator -(__digits_last, __digits_first);
  442. #else
  443.   size_t __value_length = __digits_last - __digits_first;
  444. #endif
  445.  
  446.   size_t __length       = __value_length;
  447.       
  448.   __length += __sign.size();
  449.   if (__frac_digits != 0)
  450.     ++__length;
  451.  
  452.   bool __generate_curr = (__str.flags() & ios_base::showbase) !=0;
  453.   if (__generate_curr)
  454.     __length += __curr_sym.size();
  455.   money_base::pattern __format =
  456.     __intl ? (__is_negative ? __punct_intl.neg_format() 
  457.                             : __punct_intl.pos_format())
  458.            : (__is_negative ? __punct.neg_format() 
  459.                             : __punct.pos_format());
  460.   {
  461.     for (int __i = 0; __i < 4; ++__i)
  462.       if (__format.field[__i] == (char) money_base::space)
  463.         ++__length;
  464.   }
  465.  
  466.   size_t __fill_amt = __length < __width ? __width - __length : 0;
  467.  
  468.   ios_base::fmtflags __fill_pos = __str.flags() & ios_base::adjustfield;
  469.  
  470.   if (__fill_amt != 0 &&
  471.       !(__fill_pos & (ios_base::left | ios_base::internal)))
  472.     __s = fill_n(__s, __fill_amt, __fill);
  473.     
  474.   for (int __i = 0; __i < 4; ++__i) {
  475.     char __ffield = __format.field[__i];
  476.     if (__ffield == money_base::none) {
  477.       if (__fill_amt != 0 && __fill_pos == ios_base::internal)
  478.         __s = fill_n(__s, __fill_amt, __fill);
  479.     }
  480.     else if (__ffield == money_base::space) {
  481.       *__s++ = __space;
  482.       if (__fill_amt != 0 && __fill_pos == ios_base::internal)
  483.         __s = fill_n(__s, __fill_amt, __fill);
  484.     }
  485.     else if (__ffield == money_base::symbol) {
  486.       if (__generate_curr)
  487.         __s = copy(__curr_sym.begin(), __curr_sym.end(), __s);
  488.     }
  489.     else if (__ffield == money_base::sign) {
  490.       if (__sign.size() != 0)
  491.         *__s++ = __sign[0];
  492.     }
  493.     else if (__ffield == money_base::value) {
  494.       if (__frac_digits == 0)
  495.         __s = copy(__digits_first, __digits_last, __s);
  496.       else {
  497.         if ((int)__value_length <= __frac_digits) {
  498.           *__s++ = __point;
  499.           __s = copy(__digits_first, __digits_last, __s);
  500.           __s =  fill_n(__s, __frac_digits - __value_length, __zero);
  501.         }
  502.         else {
  503.           __s = copy(__digits_first, __digits_last - __frac_digits, __s);
  504.           if (__frac_digits != 0) {
  505.             *__s++ = __point;
  506.             __s = copy(__digits_last - __frac_digits, __digits_last, __s);
  507.           }
  508.         }
  509.       }
  510.     }
  511.   } // Close for loop
  512.  
  513.   // Ouput rest of sign if necessary.
  514.  
  515.   if (__sign.size() > 1)
  516.     __s = copy(__sign.begin() + 1, __sign.end(), __s);
  517.   if (!(__fill_pos & (ios_base::right | ios_base::internal)))
  518.     __s = fill_n(__s, __fill_amt, __fill);
  519.   
  520.   return __s;
  521. }
  522.  
  523. _STLP_END_NAMESPACE
  524.  
  525. # endif /* EXPOSE */
  526.  
  527. #endif /* _STLP_MONETARY_C */
  528.