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.

185 lines
4.7 KiB

  1. // locale0 -- class locale basic member functions
  2. #include <climits>
  3. #include <locale>
  4. #include <xdebug>
  5. struct _Fac_node
  6. { // node for lazy facet recording
  7. _Fac_node(_Fac_node *_Nextarg, std::locale::facet *_Facptrarg)
  8. : _Next(_Nextarg), _Facptr(_Facptrarg)
  9. { // construct a node with value
  10. }
  11. ~_Fac_node()
  12. { // destroy a facet
  13. _DELETE_CRT(_Facptr->_Decref());
  14. }
  15. _Fac_node *_Next;
  16. std::locale::facet *_Facptr;
  17. };
  18. static _Fac_node *_Fac_head = 0;
  19. _C_STD_BEGIN
  20. _EXTERN_C
  21. void __cdecl _Fac_tidy()
  22. { // destroy lazy facets
  23. std::_Lockit lock(_LOCK_LOCALE); // prevent double delete
  24. for (; _Fac_head != 0; )
  25. { // destroy a lazy facet node
  26. _Fac_node *nodeptr = _Fac_head;
  27. _Fac_head = nodeptr->_Next;
  28. _DELETE_CRT(nodeptr);
  29. }
  30. }
  31. void __cdecl _Deletegloballocale(void *ptr)
  32. { // delete a global locale reference
  33. std::locale::_Locimp *locptr = *(std::locale::_Locimp **)ptr;
  34. if (locptr != 0)
  35. _DELETE_CRT(locptr->_Decref());
  36. }
  37. static std::locale::_Locimp *global_locale = 0; // pointer to current locale
  38. static void __cdecl tidy_global()
  39. { // delete static global locale reference
  40. std::_Lockit lock(_LOCK_LOCALE); // prevent double delete
  41. _Deletegloballocale(&global_locale);
  42. }
  43. std::locale::_Locimp *__cdecl _Getgloballocale()
  44. { // return pointer to current locale
  45. return (global_locale);
  46. }
  47. void __cdecl _Setgloballocale(void *ptr)
  48. { // alter pointer to current locale
  49. static bool registered = false;
  50. if (!registered)
  51. { // register cleanup first time
  52. registered = true;
  53. ::_Atexit(&tidy_global);
  54. }
  55. global_locale = (std::locale::_Locimp *)ptr;
  56. }
  57. _END_EXTERN_C
  58. _C_STD_END
  59. _STD_BEGIN
  60. #pragma warning(disable: 4786)
  61. static locale classic_locale(_Noinit); // "C" locale object, uninitialized
  62. locale::_Locimp *locale::_Locimp::_Clocptr = 0; // pointer to classic_locale
  63. int locale::id::_Id_cnt = 0; // unique id counter for facets
  64. _TEMPLATE_STAT const size_t ctype<char>::table_size =
  65. 1 << CHAR_BIT; // size of ctype mapping table, typically 256
  66. locale::locale() _THROW0()
  67. : _Ptr(_Init())
  68. { // construct from current locale
  69. ::_Getgloballocale()->_Incref();
  70. }
  71. const locale& __cdecl locale::classic()
  72. { // get reference to "C" locale
  73. _Init();
  74. return (classic_locale);
  75. }
  76. locale __cdecl locale::empty()
  77. { // make empty transparent locale
  78. _Init();
  79. return (locale(_NEW_CRT _Locimp(true)));
  80. }
  81. const locale::facet *locale::_Getfacet(size_t id) const
  82. { // look up a facet in locale object
  83. const facet *facptr = id < _Ptr->_Facetcount
  84. ? _Ptr->_Facetvec[id] : 0; // null if id off end
  85. if (facptr != 0 || !_Ptr->_Xparent)
  86. return (facptr); // found facet or not transparent, return pointer
  87. else
  88. { // look in current locale
  89. locale::_Locimp *_Ptr = ::_Getgloballocale();
  90. return (id < _Ptr->_Facetcount
  91. ? _Ptr->_Facetvec[id] // get from current locale
  92. : 0); // no entry in current locale
  93. }
  94. }
  95. bool locale::operator==(const locale& loc) const
  96. { // compare locales for equality
  97. return (_Ptr == loc._Ptr
  98. || name().compare("*") != 0 && name().compare(loc.name()) == 0);
  99. }
  100. locale::_Locimp *__cdecl locale::_Init()
  101. { // setup global and "C" locales
  102. locale::_Locimp *_Ptr = ::_Getgloballocale();
  103. if (_Ptr == 0)
  104. { // lock and test again
  105. _Lockit lock(_LOCK_LOCALE); // prevent double initialization
  106. _Ptr = ::_Getgloballocale();
  107. if (_Ptr == 0)
  108. { // create new locales
  109. ::_Setgloballocale(_Ptr = _NEW_CRT _Locimp);
  110. _Ptr->_Catmask = all; // set current locale to "C"
  111. _Ptr->_Name = "C";
  112. _Locimp::_Clocptr = _Ptr; // set classic to match
  113. _Locimp::_Clocptr->_Incref();
  114. new (&classic_locale) locale(_Locimp::_Clocptr);
  115. }
  116. }
  117. return (_Ptr);
  118. }
  119. void locale::facet::_Register()
  120. { // queue up lazy facet for destruction
  121. if (_Fac_head == 0)
  122. ::_Atexit(&_Fac_tidy);
  123. _Fac_head = _NEW_CRT _Fac_node(_Fac_head, this);
  124. }
  125. locale::_Locimp::_Locimp(bool transparent)
  126. : locale::facet(1), _Facetvec(0), _Facetcount(0),
  127. _Catmask(none), _Xparent(transparent), _Name("*")
  128. { // construct an empty _Locimp
  129. }
  130. locale::_Locimp::~_Locimp()
  131. { // destruct a _Locimp
  132. _Lockit lock(_LOCK_LOCALE); // prevent double delete
  133. for (size_t count = _Facetcount; 0 < count; )
  134. if (_Facetvec[--count] != 0)
  135. _DELETE_CRT(_Facetvec[count]->_Decref());
  136. free(_Facetvec);
  137. }
  138. _Locinfo::_Locinfo(const char *locname)
  139. : _Lock(_LOCK_LOCALE)
  140. { // switch to a named locale
  141. _Oldlocname = setlocale(LC_ALL, 0);
  142. _Newlocname = locname == 0
  143. || (locname = setlocale(LC_ALL, locname)) == 0
  144. ? "*" : locname;
  145. }
  146. _Locinfo::~_Locinfo()
  147. { // destroy a _Locinfo object, revert locale
  148. if (0 < _Oldlocname.size())
  149. setlocale(LC_ALL, _Oldlocname.c_str());
  150. }
  151. _STD_END
  152. /*
  153. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  154. * Consult your license regarding permissions and restrictions.
  155. V3.10:0009 */