Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
6.2 KiB

  1. // locale -- class locale member functions
  2. #include <cstdlib>
  3. #include <istream>
  4. #include <locale>
  5. #include <xdebug>
  6. #include <dbgint.h>
  7. _C_STD_BEGIN
  8. _EXTERN_C
  9. std::locale::_Locimp *__cdecl _Getgloballocale();
  10. void __cdecl _Setgloballocale(void *);
  11. _END_EXTERN_C
  12. _C_STD_END
  13. _STD_BEGIN
  14. typedef char_traits<char> _Traits;
  15. typedef istreambuf_iterator<char, _Traits> _Initer;
  16. typedef ostreambuf_iterator<char, _Traits> _Outiter;
  17. locale::locale(const locale& loc, const locale& other, category cat)
  18. : _Ptr(_NEW_CRT _Locimp(*loc._Ptr))
  19. { // construct a locale by copying named facets
  20. _TRY_BEGIN
  21. _Locinfo _Lobj(loc._Ptr->_Catmask, loc._Ptr->_Name.c_str());
  22. _Locimp::_Makeloc(_Lobj._Addcats(cat & other._Ptr->_Catmask,
  23. other._Ptr->_Name.c_str()), cat, _Ptr, &other);
  24. _CATCH_ALL
  25. _DELETE_CRT(_Ptr->_Decref());
  26. _RERAISE;
  27. _CATCH_END
  28. }
  29. locale::locale(const char *locname, category cat)
  30. : _Ptr(_NEW_CRT _Locimp)
  31. { // construct a locale with named facets
  32. _TRY_BEGIN
  33. _Init();
  34. _Locinfo _Lobj(cat, locname);
  35. if (_Lobj._Getname().compare("*") == 0)
  36. _THROW(runtime_error, "bad locale name");
  37. _Locimp::_Makeloc(_Lobj, cat, _Ptr, 0);
  38. _CATCH_ALL
  39. _DELETE_CRT(_Ptr->_Decref());
  40. _RERAISE;
  41. _CATCH_END
  42. }
  43. locale::locale(const locale& loc, const char *locname, category cat)
  44. : _Ptr(_NEW_CRT _Locimp(*loc._Ptr))
  45. { // construct a locale by copying, replacing named facets
  46. _TRY_BEGIN
  47. _Locinfo _Lobj(loc._Ptr->_Catmask, loc._Ptr->_Name.c_str());
  48. bool _Hadname = _Lobj._Getname().compare("*") != 0;
  49. _Lobj._Addcats(cat, locname);
  50. if (_Hadname && _Lobj._Getname().compare("*") == 0)
  51. _THROW(runtime_error, "bad locale name");
  52. _Locimp::_Makeloc(_Lobj, cat, _Ptr, 0);
  53. _CATCH_ALL
  54. _DELETE_CRT(_Ptr->_Decref());
  55. _RERAISE;
  56. _CATCH_END
  57. }
  58. _DEPRECATED locale& locale::_Addfac(facet *fac, size_t id, size_t catmask)
  59. { // add a facet, copying on write
  60. if (1 < _Ptr->_Refs)
  61. { // shared, make private copy before altering
  62. _Ptr->_Decref();
  63. _Ptr = _NEW_CRT _Locimp(*_Ptr);
  64. }
  65. _Ptr->_Addfac(fac, id);
  66. if (catmask != 0)
  67. _Ptr->_Name = "*";
  68. return (*this);
  69. }
  70. locale __cdecl locale::global(const locale& loc)
  71. { // change global locale
  72. locale _Oldglobal;
  73. _Lockit lock(_LOCK_LOCALE);
  74. locale::_Locimp *_Ptr = ::_Getgloballocale();
  75. if (_Ptr != loc._Ptr)
  76. { // set new global locale
  77. _DELETE_CRT(_Ptr->_Decref());
  78. ::_Setgloballocale(_Ptr = loc._Ptr);
  79. _Ptr->_Incref();
  80. category _Cmask = _Ptr->_Catmask & all;
  81. if (_Cmask == all)
  82. setlocale(LC_ALL, _Ptr->_Name.c_str());
  83. else
  84. for (int catindex = 0; catindex <= _X_MAX; ++catindex)
  85. if ((_CATMASK(catindex) & _Cmask) != 0)
  86. setlocale(catindex, _Ptr->_Name.c_str());
  87. }
  88. return (_Oldglobal);
  89. }
  90. // facets associated with C categories
  91. #define ADDFAC(Facet, cat, ptrimp, ptrloc) \
  92. if ((_CATMASK(Facet::_Getcat()) & cat) == 0) \
  93. ; \
  94. else if (ptrloc == 0) \
  95. ptrimp->_Addfac(_NEW_CRT Facet(lobj), Facet::id); \
  96. else \
  97. ptrimp->_Addfac((locale::facet *)&_USE(*ptrloc, Facet), Facet::id);
  98. typedef ctype<char> _T1;
  99. typedef num_get<char, _Initer> _T2;
  100. typedef num_put<char, _Outiter> _T3;
  101. typedef numpunct<char> _T4;
  102. // others moved to wlocale and xlocale to ease subsetting
  103. typedef codecvt<char, char, mbstate_t> _Tc1;
  104. _TEMPLATE_STAT locale::id ctype<char>::id;
  105. locale::_Locimp *__cdecl locale::_Locimp::_Makeloc(const _Locinfo& lobj,
  106. locale::category cat, _Locimp *ptrimp, const locale *ptrloc)
  107. { // setup a new locale
  108. ADDFAC(_T1, cat, ptrimp, ptrloc);
  109. ADDFAC(_T2, cat, ptrimp, ptrloc);
  110. ADDFAC(_T3, cat, ptrimp, ptrloc);
  111. ADDFAC(_T4, cat, ptrimp, ptrloc);
  112. //...
  113. ADDFAC(_Tc1, cat, ptrimp, ptrloc);
  114. _Locimp::_Makexloc(lobj, cat, ptrimp, ptrloc);
  115. _Locimp::_Makewloc(lobj, cat, ptrimp, ptrloc);
  116. #ifdef _NATIVE_WCHAR_T_DEFINED
  117. _Locimp::_Makeushloc(lobj, cat, ptrimp, ptrloc);
  118. #endif
  119. ptrimp->_Catmask |= cat;
  120. ptrimp->_Name = lobj._Getname();
  121. return (ptrimp);
  122. }
  123. locale::_Locimp::_Locimp(const locale::_Locimp& imp)
  124. : locale::facet(1), _Facetvec(0), _Facetcount(imp._Facetcount),
  125. _Catmask(imp._Catmask), _Xparent(imp._Xparent), _Name(imp._Name)
  126. { // construct a _Locimp from a copy
  127. if (&imp == _Clocptr)
  128. _Makeloc(_Locinfo(), locale::all, this, 0);
  129. else
  130. { // lock to keep facets from disappearing
  131. _Lockit lock(_LOCK_LOCALE);
  132. if (0 < _Facetcount)
  133. { // copy over nonempty facet vector
  134. if ((_Facetvec = (locale::facet **)_malloc_crt(
  135. _Facetcount * sizeof (locale::facet *))) == 0)
  136. _Nomemory();
  137. for (size_t count = _Facetcount; 0 < count; )
  138. { // copy over facet pointers
  139. locale::facet *ptrfac = imp._Facetvec[--count];
  140. if ((_Facetvec[count] = ptrfac) != 0)
  141. ptrfac->_Incref();
  142. }
  143. }
  144. }
  145. }
  146. void locale::_Locimp::_Addfac(locale::facet *ptrfac, size_t id)
  147. { // add a facet to a locale
  148. _Lockit lock(_LOCK_LOCALE);
  149. const size_t MINCAT = 40; // minimum number of facets in a locale
  150. if (_Facetcount <= id)
  151. { // make facet vector larger
  152. size_t count = id + 1;
  153. if (count < MINCAT)
  154. count = MINCAT;
  155. locale::facet **ptrnewvec = (locale::facet **)_realloc_crt(_Facetvec,
  156. count * sizeof (locale::facet **));
  157. if (ptrnewvec == 0)
  158. _Nomemory();
  159. _Facetvec = ptrnewvec;
  160. for (; _Facetcount < count; ++_Facetcount)
  161. _Facetvec[_Facetcount] = 0;
  162. }
  163. ptrfac->_Incref();
  164. if (_Facetvec[id] != 0)
  165. _DELETE_CRT(_Facetvec[id]->_Decref());
  166. _Facetvec[id] = ptrfac;
  167. }
  168. _CRTIMP2 _Locinfo::_Locinfo(int cat, const char *locname)
  169. : _Lock(_LOCK_LOCALE)
  170. { // capture a named locale
  171. _Oldlocname = setlocale(LC_ALL, 0);
  172. _Addcats(cat, locname);
  173. }
  174. _CRTIMP2 _Locinfo& _Locinfo::_Addcats(int cat, const char *locname)
  175. { // merge in another named locale
  176. const char *oldlocname = 0;
  177. if (locname[0] == '*' && locname[1] == '\0')
  178. ;
  179. else if (cat == 0)
  180. oldlocname = setlocale(LC_ALL, 0);
  181. else if (cat == _M_ALL)
  182. oldlocname = setlocale(LC_ALL, locname);
  183. else
  184. { // alter selected categories
  185. for (int catindex = 0; catindex <= _X_MAX; ++catindex)
  186. if ((_CATMASK(catindex) & cat) != 0)
  187. setlocale(catindex, locname);
  188. oldlocname = setlocale(LC_ALL, locname);
  189. }
  190. if (oldlocname == 0)
  191. _Newlocname = "*";
  192. else if (_Newlocname.compare("*") != 0)
  193. _Newlocname = oldlocname;
  194. return (*this);
  195. }
  196. _STD_END
  197. /*
  198. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  199. * Consult your license regarding permissions and restrictions.
  200. V3.10:0009 */