home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / include / xlocmon < prev    next >
Text File  |  1998-06-16  |  16KB  |  506 lines

  1. // xlocmon internal header (from <locale>)
  2.  
  3. #if     _MSC_VER > 1000
  4. #pragma once
  5. #endif
  6.  
  7. #ifndef _XLOCMON_
  8. #define _XLOCMON_
  9. #include <xiosbase>
  10.  
  11. #ifdef  _MSC_VER
  12. #pragma pack(push,8)
  13. #endif  /* _MSC_VER */
  14. _STD_BEGIN
  15.         // STRUCT money_base
  16. struct _CRTIMP money_base : public locale::facet {
  17.     enum _Part {symbol = '$', sign = '+', space = ' ',
  18.         value = 'v', none = 'x'};
  19.     _BITMASK(_Part, part);
  20.     struct pattern {
  21.         char field[4];
  22.         };
  23.     money_base(size_t _R = 0)
  24.         : locale::facet(_R) {}
  25.     };
  26. _BITMASK_OPS(money_base::_Part);
  27.         // TEMPLATE CLASS _Mpunct
  28. template<class _E>
  29.     class _Mpunct : public money_base {
  30. public:
  31.     typedef _E char_type;
  32.     typedef basic_string<_E, char_traits<_E>, allocator<_E> >
  33.         string_type;
  34.     _E decimal_point() const
  35.         {return (do_decimal_point()); }
  36.     _E thousands_sep() const
  37.         {return (do_thousands_sep()); }
  38.     string grouping() const
  39.         {return (do_grouping()); }
  40.     string_type curr_symbol() const
  41.         {return (do_curr_symbol()); }
  42.     string_type positive_sign() const
  43.         {return (do_positive_sign()); }
  44.     string_type negative_sign() const
  45.         {return (do_negative_sign()); }
  46.     int frac_digits() const
  47.         {return (do_frac_digits()); }
  48.     pattern pos_format() const
  49.         {return (do_pos_format()); }
  50.     pattern neg_format() const
  51.         {return (do_neg_format()); }
  52.     explicit _Mpunct(size_t _R, bool _Intl)
  53.         : money_base(_R), _Ifl(_Intl) {_Init(_Locinfo()); }
  54.     _Mpunct(const _Locinfo& _Lobj, size_t _R, bool _Intl)
  55.         : money_base(_R), _Ifl(_Intl) {_Init(_Lobj); }
  56.     static size_t __cdecl _Getcat()
  57.         {return (_LC_NUMERIC); }
  58. _PROTECTED:
  59.     virtual ~_Mpunct()
  60.         {delete[] _Mgr;
  61.         delete[] _Mcs;
  62.         delete[] _Mps;
  63.         delete[] _Mns; }
  64. protected:
  65.     void _Init(const _Locinfo& _Lobj)
  66.         {const lconv *_P = _Lobj._Getlconv();
  67.         _Mdp = _WIDEN(_E, _P->mon_decimal_point[0]);
  68.         _Mks = _WIDEN(_E, _P->mon_thousands_sep[0]);
  69.         _Mgr = _MAKLOCSTR(char, _P->mon_grouping);
  70.         _Mcs = _MAKLOCSTR(_E, _Ifl ? _P->int_curr_symbol
  71.             : _P->currency_symbol);
  72.         _Mps = _MAKLOCSTR(_E, _P->p_sign_posn < 0
  73.             || 4 < _P->p_sign_posn
  74.                 ? "" : _P->positive_sign);
  75.         _Mns = _MAKLOCSTR(_E, _P->n_sign_posn < 0
  76.             || 4 < _P->n_sign_posn
  77.                 ? "-" : _P->negative_sign);
  78.         _Mfd = _Ifl ? _P->int_frac_digits
  79.             : _P->frac_digits;
  80.         if (_Mfd < 0 || CHAR_MAX <= _Mfd)
  81.             _Mfd = 0;
  82.         _Makpat(_Mpf, _P->p_sep_by_space,
  83.             _P->p_cs_precedes, _P->p_sign_posn);
  84.         _Makpat(_Mnf, _P->n_sep_by_space,
  85.             _P->n_cs_precedes, _P->n_sign_posn); }
  86.     virtual _E do_decimal_point() const
  87.         {return (_Mdp); }
  88.     virtual _E do_thousands_sep() const
  89.         {return (_Mks); }
  90.     virtual string do_grouping() const
  91.         {return (string(_Mgr)); }
  92.     virtual string_type do_curr_symbol() const
  93.         {return (string_type(_Mcs)); }
  94.     virtual string_type do_positive_sign() const
  95.         {return (string_type(_Mps)); }
  96.     virtual string_type do_negative_sign() const
  97.         {return (string_type(_Mns)); }
  98.     virtual int do_frac_digits() const
  99.         {return (_Mfd); }
  100.     virtual pattern do_pos_format() const
  101.         {return (_Mpf); }
  102.     virtual pattern do_neg_format() const
  103.         {return (_Mnf); }
  104. private:
  105.     void _Makpat(pattern& _Pat, char _Sep, char _Pre, char _Pos)
  106.         {char *_S = _Ifl || (_Sep & ~1) != 0 || (_Pre & ~1) != 0
  107.             || _Pos < 0 || 4 < _Pos ? "$+vx"
  108.             : "+v$x" "+v$x" "v$+x" "v+$x" "v$+x"
  109.                 "+$vx" "+$vx" "$v+x" "+$vx" "$+vx"
  110.                 "+v $" "+v $" "v $+" "v+ $" "v $+"
  111.                 "+$ v" "+$ v" "$ v+" "+$ v" "$ +v" + (_Pos
  112.                 + (_Pre == 1 ? 20 : 0) + (_Sep == 1 ? 40 : 0));
  113.         memcpy(_Pat.field, _S, 4); }
  114.     char *_Mgr;
  115.     _E _Mdp, _Mks, *_Mcs, *_Mps, *_Mns;
  116.     int _Mfd;
  117.     pattern _Mpf, _Mnf;
  118.     bool _Ifl;
  119.     };
  120.         // TEMPLATE CLASS moneypunct
  121. template<class _E, bool _Intl = false>
  122.     class moneypunct : public _Mpunct<_E> {
  123. public:
  124.     static const bool intl;
  125.     static locale::id id;
  126.     explicit moneypunct(size_t _R = 0)
  127.         : _Mpunct<_E>(_R, _Intl) {}
  128.     moneypunct(const _Locinfo& _Lobj, size_t _R = 0)
  129.         : _Mpunct<_E>(_Lobj, _R, _Intl) {}
  130.     static size_t __cdecl _Getcat()
  131.         {return (_LC_NUMERIC); }
  132.     };
  133. template<class _E, bool _Intl>
  134.     const bool moneypunct<_E, _Intl>::intl = _Intl;
  135. template<class _E, bool _Intl>
  136.     locale::id moneypunct<_E, _Intl>::id;
  137.         // TEMPLATE CLASS moneypunct_byname
  138. template<class _E, bool _Intl = false>
  139.     class moneypunct_byname : public moneypunct<_E, _Intl> {
  140. public:
  141.     explicit moneypunct_byname(const char *_S, size_t _R = 0)
  142.         : moneypunct<_E, _Intl>(_Locinfo(_S), _R) {}
  143. _PROTECTED:
  144.     virtual ~moneypunct_byname()
  145.         {}
  146.     };
  147.         // TEMPLATE CLASS money_get
  148. template<class _E,
  149.     class _II = istreambuf_iterator<_E, char_traits<_E> > >
  150.     class money_get : public locale::facet {
  151.     typedef moneypunct<_E, false> _Mypunct0;
  152.     typedef moneypunct<_E, true> _Mypunct1;
  153. public:
  154.     typedef _E char_type;
  155.     typedef _II iter_type;
  156.     typedef basic_string<_E, char_traits<_E>, allocator<_E> >
  157.         string_type;
  158.     _II get(_II _F, _II _L, bool _Intl, ios_base& _X,
  159.         ios_base::iostate& _St, long double& _V) const
  160.         {return (do_get(_F, _L, _Intl, _X, _St, _V)); }
  161.     _II get(_II _F, _II _L, bool _Intl, ios_base& _X,
  162.         ios_base::iostate& _St, string_type& _D) const
  163.         {return (do_get(_F, _L, _Intl, _X, _St, _D)); }
  164.     static locale::id id;
  165.     explicit money_get(size_t _R = 0)
  166.         : locale::facet(_R) {_Init(_Locinfo()); }
  167.     money_get(const _Locinfo& _Lobj, size_t _R = 0)
  168.         : locale::facet(_R) {_Init(_Lobj); }
  169.     static size_t __cdecl _Getcat()
  170.         {return (_LC_MONETARY); }
  171. _PROTECTED:
  172.     virtual ~money_get()
  173.         {}
  174. protected:
  175.     void _Init(const _Locinfo& _Lobj)
  176.         {}
  177.     virtual _II do_get(_II _F, _II _L, bool _Intl, ios_base& _X,
  178.         ios_base::iostate& _St, long double& _V) const
  179.         {string_type _Str = _Getmfld(_F, _L, _Intl, _X);
  180.         if (_F == _L)
  181.             _St |= ios_base::eofbit;
  182.         if (_Str.size() == 0)
  183.             _St |= ios_base::failbit;
  184.         else
  185.             {string _Str2;
  186.             _Str2.reserve(_Str.size());
  187.             for (size_t _I = 0; _I < _Str.size(); ++_I)
  188.                 _Str2 += (char)_NARROW(_E, _Str[_I]);
  189.             const char *_Eb = _Str2.c_str();
  190.             char *_Ep;
  191.             errno = 0;
  192.             const long double _Ans = _Stold(_Eb, &_Ep, 0);
  193.             if (_Ep == _Eb || errno != 0)
  194.                 _St |= ios_base::failbit;
  195.             else
  196.                 _V = _Ans; }
  197.         return (_F); }
  198.     virtual _II do_get(_II _F, _II _L, bool _Intl, ios_base& _X,
  199.         ios_base::iostate& _St, string_type& _D) const
  200.         {string_type _Str = _Getmfld(_F, _L, _Intl, _X);
  201.         if (_F == _L)
  202.             _St |= ios_base::eofbit;
  203.         if (_Str.size() == 0)
  204.             _St |= ios_base::failbit;
  205.         else
  206.             _D = _Str;
  207.         return (_F); }
  208. private:
  209.     string_type _Getmfld(_II& _F, _II& _L, bool _Intl,
  210.         ios_base& _X) const
  211.         {const _Mpunct<_E> *_Pfac;
  212.         if (_Intl)
  213.             _Pfac = &_USE(_X.getloc(), _Mypunct1);
  214.         else
  215.             _Pfac = &_USE(_X.getloc(), _Mypunct0);
  216.         const ctype<_E>& _Fac2 = _USE(_X.getloc(), ctype<_E>);
  217.         bool _Bad = false, _Neg = false;
  218.         string_type _Sg, _Str;
  219.         const money_base::pattern _Pat = _Pfac->neg_format();
  220.         for (size_t _N = 0; !_Bad && _N < 4; ++_N)
  221.             switch (_Pat.field[_N])
  222.         {case money_base::symbol:
  223.             {string_type _Cs = _Pfac->curr_symbol();
  224.             const _E *_S;
  225.             if (_X.flags() & ios_base::showbase)
  226.                 ;
  227.             else if (_N == 3 && _Sg.size() == 0
  228.                 || _F == _L || *_F != *_Cs.c_str())
  229.                 _Cs.erase();
  230.             for (_S = _Cs.begin(); _F != _L && _S != _Cs.end()
  231.                 && *_F == *_S; ++_S, ++_F)
  232.                 ;
  233.             if (_S != _Cs.end())
  234.                 _Bad = true; }
  235.             break;
  236.         case money_base::sign:
  237.             {if (_F == _L)
  238.                 ;
  239.             else if (0 < (_Pfac->positive_sign()).size()
  240.                 && _Pfac->positive_sign()[0] == *_F)
  241.                 ++_F, _Sg = _Pfac->positive_sign();
  242.             else if (0 < (_Pfac->negative_sign()).size()
  243.                 && _Pfac->negative_sign()[0] == *_F)
  244.                 ++_F, _Sg = _Pfac->negative_sign(), _Neg = true;
  245.             if (_Sg.size() == 1)
  246.                 _Sg.erase(); }
  247.             break;
  248.         case money_base::value:
  249.             {int _Nfd = 0;
  250.             int _Fd = _Pfac->frac_digits();
  251.             const string _Gr = _Pfac->grouping();
  252.             if (*_Gr.c_str() <= '\0')
  253.                 while (_F != _L
  254.                     && _Fac2.is(ctype_base::digit, *_F))
  255.                     _Str += *_F++;
  256.             else
  257.                 {const _E _Ks = _Pfac->thousands_sep();
  258.                 string _Grin(1, '\0');
  259.                 size_t _I = 0;
  260.                 for (; _F != _L; ++_F)
  261.                     if (_Fac2.is(ctype_base::digit, *_F))
  262.                         {_Str += *_F;
  263.                         if (_Grin[_I] != CHAR_MAX)
  264.                             ++_Grin[_I]; }
  265.                     else if (_Grin[_I] == '\0' || *_F != _Ks)
  266.                         break;
  267.                     else
  268.                         _Grin.append(1, '\0'), ++_I;
  269.                 if (_I == 0)
  270.                     ;
  271.                 else if ('\0' < _Grin[_I])
  272.                     ++_I;
  273.                 else
  274.                     _Bad = true;
  275.                 for (const char *_Pg = _Gr.c_str();
  276.                     !_Bad && 0 < _I; --_I)
  277.                     if (*_Pg == CHAR_MAX)
  278.                         break;
  279.                     else if (0 < --_I && *_Pg != _Grin[_I]
  280.                         || 0 == _I && *_Pg < _Grin[_I])
  281.                         _Bad = true;
  282.                     else if ('\0' < _Pg[1])
  283.                         ++_Pg;
  284.                 if (_Bad)
  285.                     break; }
  286.             if (_F != _L && *_F == _Pfac->decimal_point())
  287.                 {while (++_F != _L
  288.                     && _Fac2.is(ctype_base::digit, *_F))
  289.                     if (_Nfd < _Fd)
  290.                         _Str += *_F, ++_Nfd; }
  291.             if (_Str.size() == 0)
  292.                 _Bad = true;
  293.             else
  294.                 for (; _Nfd < _Fd; ++_Nfd)
  295.                     _Str += _WIDEN(_E, '0'); }
  296.             break;
  297.         default:
  298.             {if (_N == 3)
  299.                 break;
  300.             while (_F != _L && _Fac2.is(ctype_base::space, *_F))
  301.                 ++_F; }}
  302.         if (!_Bad && 0 < _Sg.size())
  303.             {const _E *_S;
  304.             for (_S = _Sg.begin(); _F != _L
  305.                 && ++_S != _Sg.end() && *_F == *_S; ++_F)
  306.                 ;
  307.             if (_S != _Sg.end())
  308.                 _Bad = true; }
  309.         if (_Bad)
  310.             _Str.erase();
  311.         else if (_Neg)
  312.             _Str.insert((size_t)0, (size_t)1, _WIDEN(_E, '-'));
  313.         return (_Str); }
  314.     };
  315. template<class _E, class _II>
  316.     locale::id money_get<_E, _II>::id;
  317.         // TEMPLATE CLASS money_put
  318. template<class _E,
  319.     class _OI = ostreambuf_iterator<_E, char_traits<_E> > >
  320.     class money_put : public locale::facet {
  321.     typedef moneypunct<_E, false> _Mypunct0;
  322.     typedef moneypunct<_E, true> _Mypunct1;
  323. public:
  324.     typedef _E char_type;
  325.     typedef _OI iter_type;
  326.     typedef basic_string<_E, char_traits<_E>, allocator<_E> >
  327.         string_type;
  328.     _OI put(_OI _F, bool _Intl, ios_base& _X, _E _Fill,
  329.         long double _V) const
  330.         {return (do_put(_F, _Intl, _X, _Fill, _V)); }
  331.     _OI put(_OI _F, bool _Intl, ios_base& _X, _E _Fill,
  332.         const string_type& _D) const
  333.         {return (do_put(_F, _Intl, _X, _Fill, _D)); }
  334.     static locale::id id;
  335.     explicit money_put(size_t _R = 0)
  336.         : locale::facet(_R) {_Init(_Locinfo()); }
  337.     money_put(const _Locinfo& _Lobj, size_t _R = 0)
  338.         : locale::facet(_R) {_Init(_Lobj); }
  339.     static size_t __cdecl _Getcat()
  340.         {return (_LC_MONETARY); }
  341. _PROTECTED:
  342.     virtual ~money_put()
  343.         {}
  344. protected:
  345.     void _Init(const _Locinfo& _Lobj)
  346.         {}
  347.     virtual _OI do_put(_OI _F, bool _Intl,
  348.         ios_base& _X, _E _Fill, long double _V) const
  349.         {bool _Neg = false;
  350.         if (_V < 0)
  351.             _Neg = true, _V = -_V;
  352.         size_t _Exp;
  353.         for (_Exp = 0; 1e35 <= _V && _Exp < 5000; _Exp += 10)
  354.             _V /= 1e10;
  355.         string_type _D2;
  356.         char _Buf[40];
  357.         int _N = sprintf(_Buf, "%.0Lf", _V);
  358.         for (int _I = 0; _I < _N; ++_I)
  359.             _D2.append(1, _WIDEN(_E, _Buf[_I]));
  360.         _D2.append(_Exp, _WIDEN(_E, '0'));
  361.         return (_Putmfld(_F, _Intl, _X, _Fill, _Neg, _D2)); }
  362.     virtual _OI do_put(_OI _F, bool _Intl,
  363.         ios_base& _X, _E _Fill, const string_type& _D) const
  364.         {const ctype<_E>& _Fac = _USE(_X.getloc(), ctype<_E>);
  365.         const _E *_S = _D.c_str();
  366.         bool _Neg = false;
  367.         if (*_S == _WIDEN(_E, '-'))
  368.             _Neg = true, ++_S;
  369.         size_t _N;
  370.         for (_N = 0; _Fac.is(ctype_base::digit, _S[_N]); ++_N)
  371.             ;
  372.         string_type _D2(_S, _N);
  373.         if (_N == 0)
  374.             _D2.append(1, _WIDEN(_E, '0'));
  375.         return (_Putmfld(_F, _Intl, _X, _Fill, _Neg, _D2)); }
  376. private:
  377.     _OI _Putmfld(_OI _F, bool _Intl, ios_base& _X, _E _Fill,
  378.         bool _Neg, string_type _D) const
  379.         {const _Mpunct<_E> *_Pfac;
  380.         if (_Intl)
  381.             _Pfac = &_USE(_X.getloc(), _Mypunct1);
  382.         else
  383.             _Pfac = &_USE(_X.getloc(), _Mypunct0);
  384.         size_t _Fd = _Pfac->frac_digits();
  385.         const string _Gr = _Pfac->grouping();
  386.         if (_Fd < _D.size() && '\0' < *_Gr.c_str())
  387.             {const _E _Ks = _Pfac->thousands_sep();
  388.             const char *_Pg = _Gr.c_str();
  389.             size_t _I = _D.size() - _Fd;
  390.             while (*_Pg != CHAR_MAX && '\0' < *_Pg && *_Pg < _I)
  391.                 {_D.insert(_I -= *_Pg, (size_t)1, _Ks);
  392.                 if ('\0' < _Pg[1])
  393.                     ++_Pg; }}
  394.         money_base::pattern _Pat;
  395.         string_type _Sg;
  396.         if (_Neg)
  397.             {_Pat = _Pfac->neg_format();
  398.             _Sg = _Pfac->negative_sign(); }
  399.         else
  400.             {_Pat = _Pfac->pos_format();
  401.             _Sg = _Pfac->positive_sign(); }
  402.         string_type _Cs;
  403.         if (_X.flags() & ios_base::showbase)
  404.             _Cs = _Pfac->curr_symbol();
  405.         bool _Intern = false;
  406.         size_t _M, _N;
  407.         for (_M = 0, _N = 0; _N < 4; ++_N)
  408.             switch (_Pat.field[_N])
  409.         {case money_base::symbol:
  410.             _M += _Cs.size();
  411.             break;
  412.         case money_base::sign:
  413.             _M += _Sg.size();
  414.             break;
  415.         case money_base::value:
  416.             _M += _D.size() + (0 < _Fd ? 1 : 0)
  417.                 + (_D.size() <= _Fd ? _Fd - _D.size() + 1 : 0);
  418.             break;
  419.         case money_base::space:
  420.             _Intern = true; }
  421.         _M = _X.width() <= 0 || _X.width() <= _M
  422.             ? 0 : _X.width() - _M;
  423.         ios_base::fmtflags _Afl =
  424.             _X.flags() & ios_base::adjustfield;
  425.         if (_Afl != ios_base::left
  426.             && (_Afl != ios_base::internal || !_Intern))
  427.             _F = _Rep(_F, _Fill, _M), _M = 0;
  428.         for (_N = 0; _N < 4; ++_N)
  429.             switch (_Pat.field[_N])
  430.         {case money_base::symbol:
  431.             _F = _Put(_F, _Cs.begin(), _Cs.size());
  432.             break;
  433.         case money_base::sign:
  434.             if (0 < _Sg.size())
  435.                 _F = _Put(_F, _Sg.begin(), 1);
  436.             break;
  437.         case money_base::value:
  438.             if (_Fd == 0)
  439.                 _F = _Put(_F, _D.begin(), _D.size());
  440.             else if (_D.size() <= _Fd)
  441.                 {*_F++ = _WIDEN(_E, '0');
  442.                 *_F++ = _Pfac->decimal_point();
  443.                 _F = _Rep(_F, _WIDEN(_E, '0'), _Fd - _D.size());
  444.                 _F = _Put(_F, _D.begin(), _D.size()); }
  445.             else
  446.                 {_F = _Put(_F, _D.begin(), _D.size() - _Fd);
  447.                 *_F++ = _Pfac->decimal_point();
  448.                 _F = _Put(_F, _D.end() - _Fd, _Fd); }
  449.             break;
  450.         case money_base::space:
  451.             if (_Afl == ios_base::internal)
  452.                 _F = _Rep(_F, _Fill, _M), _M = 0; }
  453.         if (1 < _Sg.size())
  454.             _F = _Put(_F, _Sg.begin() + 1, _Sg.size() - 1);
  455.         _X.width(0);
  456.         return (_Rep(_F, _Fill, _M)); }
  457.     static _OI _Put(_OI _F, const _E *_S, size_t _N)
  458.         {for (; 0 < _N; --_N, ++_F, ++_S)
  459.             *_F = *_S;
  460.         return (_F); }
  461.     static _OI _Rep(_OI _F, _E _C, size_t _N)
  462.         {for (; 0 < _N; --_N, ++_F)
  463.             *_F = _C;
  464.         return (_F); }
  465.     };
  466. template<class _E, class _OI>
  467.     locale::id money_put<_E, _OI>::id;
  468.  
  469. #ifdef    _DLL
  470.  
  471. #pragma warning(disable:4231) /* the extern before template is a non-standard extension */
  472.  
  473. extern template class _CRTIMP _Mpunct<char>;
  474. extern template class _CRTIMP _Mpunct<wchar_t>;
  475.  
  476. extern template class _CRTIMP moneypunct<char, true>;
  477. extern template class _CRTIMP moneypunct<char, false>;
  478. extern template class _CRTIMP moneypunct<wchar_t, true>;
  479. extern template class _CRTIMP moneypunct<wchar_t, false>;
  480.  
  481. extern template class _CRTIMP money_get<char, 
  482.                       istreambuf_iterator<char, char_traits<char> > >;
  483. extern template class _CRTIMP money_get<wchar_t, 
  484.                       istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  485. extern template class _CRTIMP money_put<char,
  486.                       ostreambuf_iterator<char, char_traits<char> > >;
  487. extern template class _CRTIMP money_put<wchar_t,
  488.                       ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  489.  
  490. #pragma warning(default:4231) /* restore previous warning */
  491.  
  492. #endif        // _DLL
  493.  
  494.  
  495. _STD_END
  496. #ifdef  _MSC_VER
  497. #pragma pack(pop)
  498. #endif  /* _MSC_VER */
  499.  
  500. #endif /* _XLOCMON_ */
  501.  
  502. /*
  503.  * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED. 
  504.  * Consult your license regarding permissions and restrictions.
  505.  */
  506.