home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / locale.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  7KB  |  192 lines

  1. // locale -- class locale member functions
  2. #include <cstdlib>
  3. #include <istream>
  4. #include <locale>
  5. _STD_BEGIN
  6.  
  7. typedef char_traits<char> _Traits;
  8. typedef istreambuf_iterator<char, _Traits> _Initer;
  9. typedef ostreambuf_iterator<char, _Traits> _Outiter;
  10.  
  11. locale::locale(const locale& _X, const locale& _Y, category _C)
  12.         : _Ptr(new _Locimp(*_X._Ptr))
  13.         {       // construct a locale by copying named facets
  14.         _Locinfo _Lobj(_X._Ptr->_Cat, _X._Ptr->_Name.c_str());
  15.         _Locimp::_Makeloc(_Lobj._Addcats(_C & _Y._Ptr->_Cat,
  16.                 _Y._Ptr->_Name.c_str()), _C, _Ptr, &_Y);
  17.         }
  18.  
  19. locale::locale(const char *_S, category _C)
  20.         : _Ptr(new _Locimp)
  21.         {       // construct a locale with named facets
  22.         _Init();
  23.         _Locinfo _Lobj(_C, _S);
  24.         if (_Lobj._Getname().compare("*") == 0)
  25.                 _THROW(runtime_error, "bad locale name");
  26.         _Locimp::_Makeloc(_Lobj, _C, _Ptr, 0);
  27.         }
  28.  
  29. locale::locale(const locale& _X, const char *_S, category _C)
  30.         : _Ptr(new _Locimp(*_X._Ptr))
  31.         {       // construct a locale by copying, replacing named facets
  32.         _Locinfo _Lobj(_C, _S);
  33.         if (_Lobj._Getname().compare("*") == 0)
  34.                 _THROW(runtime_error, "bad locale name");
  35.         _Locimp::_Makeloc(_Lobj._Addcats(_Ptr->_Cat,
  36.                 _Ptr->_Name.c_str()), _C, _Ptr, 0);
  37.         }
  38.  
  39. locale& locale::_Addfac(facet *_Fac, size_t _Id, size_t _Cat)
  40.         {       // add a facet, copying on write
  41.         if (1 < _Ptr->_Refs)
  42.                 {_Ptr->_Decref();
  43.                 _Ptr = new _Locimp(*_Ptr); }
  44.         _Ptr->_Addfac(_Fac, _Id);
  45.         if (_Cat != 0)
  46.                 _Ptr->_Name = "*";
  47.         return (*this); }
  48.  
  49. locale __cdecl locale::global(const locale& _X)
  50.         {       // change global locale
  51.         locale _L;
  52.         _Lockit _Lk;
  53.         if (_Locimp::_Global != _X._Ptr)
  54.                 {       // set new global locale
  55.                 delete _Locimp::_Global->_Decref();
  56.                 _Locimp::_Global = new _Locimp(*_X._Ptr);
  57.                 category _Cmask = _Locimp::_Global->_Cat & all;
  58.                 if (_Cmask == all)
  59.                         setlocale(LC_ALL, _Locimp::_Global->_Name.c_str());
  60.                 else
  61.                         for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat)
  62.                                 if ((_CATMASK(_Cat) & _Cmask) != 0)
  63.                                         setlocale(_Cat,
  64.                                                 _Locimp::_Global->_Name.c_str());
  65.                 }
  66.         return (_L);
  67.         }
  68.  
  69.         // facets associated with C categories
  70. #define ADDFAC(T, cat, pi, pl) \
  71.         if ((_CATMASK(T::_Getcat()) & cat) == 0) \
  72.                 ; \
  73.         else if (pl == 0) \
  74.                 pi->_Addfac(new T(_Lobj), T::id); \
  75.         else \
  76.                 pi->_Addfac((locale::facet *)&_USE(*pl, T), T::id);
  77.  
  78. typedef ctype<char> _T1;
  79. typedef num_get<char, _Initer> _T2;
  80. typedef num_put<char, _Outiter> _T3;
  81. typedef numpunct<char> _T4;
  82.  
  83. typedef codecvt<char, char, mbstate_t> _Tc1;
  84.  
  85. template<> locale::id ctype<char>::id;
  86. template<> locale::id codecvt<char,char,int>::id;
  87. template<> locale::id num_get<char, _Initer>::id;
  88. template<> locale::id num_put<char, _Outiter>::id;
  89. template<> locale::id numpunct<char>::id;
  90.  
  91. locale::_Locimp *__cdecl locale::_Locimp::_Makeloc(
  92.         const _Locinfo& _Lobj, locale::category _C,
  93.                 _Locimp *_Pi, const locale *_Pl)
  94.         {       // setup a new locale
  95.         _Lockit _Lk;
  96.         ADDFAC(_T1, _C, _Pi, _Pl);
  97.         ADDFAC(_T2, _C, _Pi, _Pl);
  98.         ADDFAC(_T3, _C, _Pi, _Pl);
  99.         ADDFAC(_T4, _C, _Pi, _Pl);
  100.         //...
  101.         ADDFAC(_Tc1, _C, _Pi, _Pl);
  102.         _Locimp::_Makexloc(_Lobj, _C, _Pi, _Pl);
  103.         _Locimp::_Makewloc(_Lobj, _C, _Pi, _Pl);
  104.         _Pi->_Cat |= _C;
  105.         _Pi->_Name = _Lobj._Getname();
  106.         return (_Pi);
  107.         }
  108.  
  109. locale::_Locimp::_Locimp(const locale::_Locimp& _X)
  110.         : locale::facet(1), _Fv(0), _Nfv(_X._Nfv),
  111.                 _Cat(_X._Cat), _Xpar(_X._Xpar), _Name(_X._Name)
  112.         {       // construct a _Locimp from a copy
  113.         _Lockit Lk;
  114.         if (&_X == _Clocptr)
  115.                 _Makeloc(_Locinfo(), locale::all, this, 0);
  116.         else
  117.                 {_Lockit _Lk;
  118.                 if (0 < _Nfv)
  119.                         {       // copy over nonempty facet vector
  120.                         if ((_Fv = (locale::facet **)malloc(
  121.                                 _Nfv * sizeof (locale::facet *))) == 0)
  122.                                 _Nomemory();
  123.                         for (size_t _N = _Nfv; 0 < _N; )
  124.                                 {       // copy over facet pointers
  125.                                 locale::facet *_Pf = _X._Fv[--_N];
  126.                                 if ((_Fv[_N] = _Pf) != 0)
  127.                                         _Pf->_Incref();
  128.                                 }
  129.                         }
  130.                 }
  131.         }
  132.  
  133. void locale::_Locimp::_Addfac(locale::facet *_Pf, size_t _Id)
  134.         {       // add a facet to a locale
  135.         _Lockit _Lk;
  136.         const size_t _MINCAT = 32;
  137.         if (_Nfv <= _Id)
  138.                 {       // make facet vector larger
  139.                 size_t _N = _Id + 1;
  140.                 if (_N < _MINCAT)
  141.                         _N = _MINCAT;
  142.                 locale::facet **_Pvn = (locale::facet **)realloc(_Fv,
  143.                         _N * sizeof (locale::facet **));
  144.                 if (_Pvn == 0)
  145.                         _Nomemory();
  146.                 _Fv = _Pvn;
  147.                 for (; _Nfv < _N; ++_Nfv)
  148.                         _Fv[_Nfv] = 0;
  149.                 }
  150.         _Pf->_Incref();
  151.         if (_Fv[_Id] != 0)
  152.                 delete _Fv[_Id]->_Decref();
  153.         _Fv[_Id] = _Pf;
  154.         }
  155.  
  156. _CRTIMP2 _Locinfo::_Locinfo(const char *_Name)
  157.         {       // switch to a named locale
  158.         _Oname = setlocale(LC_ALL, 0);
  159.         _Nname = _Name == 0
  160.                 || (_Name = setlocale(LC_ALL, _Name)) == 0
  161.                         ? "*" : _Name; }
  162.  
  163. _CRTIMP2 _Locinfo::_Locinfo(int _C, const char *_Name)
  164.         {_Addcats(_C, _Name); }
  165.  
  166.  
  167. _CRTIMP2 _Locinfo::~_Locinfo()
  168.         {       // destroy a _Locinfo object, revert locale
  169.         if (0 < _Oname.size())
  170.                 setlocale(LC_ALL, _Oname.c_str()); }
  171.  
  172. _CRTIMP2 _Locinfo& _Locinfo::_Addcats(int _C, const char *_Name)
  173.         {       // merge in another named locale
  174.         const char *_Lname = 0;
  175.         if (_C == 0)
  176.                 _Lname = setlocale(LC_ALL, 0);
  177.         else if (_C == _M_ALL)
  178.                 _Lname = setlocale(LC_ALL, _Name);
  179.         else
  180.                 for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat)
  181.                         if ((_CATMASK(_Cat) & _C) != 0)
  182.                                 _Lname = setlocale(_Cat, _Name);
  183.         _Nname = _Lname != 0 ? _Lname : "*";
  184.         return (*this); }
  185.  
  186. _STD_END
  187.  
  188. /*
  189.  * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED. 
  190.  * Consult your license regarding permissions and restrictions.
  191.  */
  192.