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.

299 lines
8.2KB

  1. // Locale support -*- C++ -*-
  2. // Copyright (C) 2007-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/locale_classes.tcc
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{locale}
  23. */
  24. //
  25. // ISO C++ 14882: 22.1 Locales
  26. //
  27. #ifndef _LOCALE_CLASSES_TCC
  28. #define _LOCALE_CLASSES_TCC 1
  29. #pragma GCC system_header
  30. namespace std _GLIBCXX_VISIBILITY(default)
  31. {
  32. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  33. template<typename _Facet>
  34. locale::
  35. locale(const locale& __other, _Facet* __f)
  36. {
  37. _M_impl = new _Impl(*__other._M_impl, 1);
  38. __try
  39. { _M_impl->_M_install_facet(&_Facet::id, __f); }
  40. __catch(...)
  41. {
  42. _M_impl->_M_remove_reference();
  43. __throw_exception_again;
  44. }
  45. delete [] _M_impl->_M_names[0];
  46. _M_impl->_M_names[0] = 0; // Unnamed.
  47. }
  48. template<typename _Facet>
  49. locale
  50. locale::
  51. combine(const locale& __other) const
  52. {
  53. _Impl* __tmp = new _Impl(*_M_impl, 1);
  54. __try
  55. {
  56. __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
  57. }
  58. __catch(...)
  59. {
  60. __tmp->_M_remove_reference();
  61. __throw_exception_again;
  62. }
  63. return locale(__tmp);
  64. }
  65. template<typename _CharT, typename _Traits, typename _Alloc>
  66. bool
  67. locale::
  68. operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
  69. const basic_string<_CharT, _Traits, _Alloc>& __s2) const
  70. {
  71. typedef std::collate<_CharT> __collate_type;
  72. const __collate_type& __collate = use_facet<__collate_type>(*this);
  73. return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
  74. __s2.data(), __s2.data() + __s2.length()) < 0);
  75. }
  76. /**
  77. * @brief Test for the presence of a facet.
  78. * @ingroup locales
  79. *
  80. * has_facet tests the locale argument for the presence of the facet type
  81. * provided as the template parameter. Facets derived from the facet
  82. * parameter will also return true.
  83. *
  84. * @tparam _Facet The facet type to test the presence of.
  85. * @param __loc The locale to test.
  86. * @return true if @p __loc contains a facet of type _Facet, else false.
  87. */
  88. template<typename _Facet>
  89. bool
  90. has_facet(const locale& __loc) throw()
  91. {
  92. const size_t __i = _Facet::id._M_id();
  93. const locale::facet** __facets = __loc._M_impl->_M_facets;
  94. return (__i < __loc._M_impl->_M_facets_size
  95. #if __cpp_rtti
  96. && dynamic_cast<const _Facet*>(__facets[__i]));
  97. #else
  98. && static_cast<const _Facet*>(__facets[__i]));
  99. #endif
  100. }
  101. /**
  102. * @brief Return a facet.
  103. * @ingroup locales
  104. *
  105. * use_facet looks for and returns a reference to a facet of type Facet
  106. * where Facet is the template parameter. If has_facet(locale) is true,
  107. * there is a suitable facet to return. It throws std::bad_cast if the
  108. * locale doesn't contain a facet of type Facet.
  109. *
  110. * @tparam _Facet The facet type to access.
  111. * @param __loc The locale to use.
  112. * @return Reference to facet of type Facet.
  113. * @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
  114. */
  115. template<typename _Facet>
  116. const _Facet&
  117. use_facet(const locale& __loc)
  118. {
  119. const size_t __i = _Facet::id._M_id();
  120. const locale::facet** __facets = __loc._M_impl->_M_facets;
  121. if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
  122. __throw_bad_cast();
  123. #if __cpp_rtti
  124. return dynamic_cast<const _Facet&>(*__facets[__i]);
  125. #else
  126. return static_cast<const _Facet&>(*__facets[__i]);
  127. #endif
  128. }
  129. // Generic version does nothing.
  130. template<typename _CharT>
  131. int
  132. collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
  133. { return 0; }
  134. // Generic version does nothing.
  135. template<typename _CharT>
  136. size_t
  137. collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
  138. { return 0; }
  139. template<typename _CharT>
  140. int
  141. collate<_CharT>::
  142. do_compare(const _CharT* __lo1, const _CharT* __hi1,
  143. const _CharT* __lo2, const _CharT* __hi2) const
  144. {
  145. // strcoll assumes zero-terminated strings so we make a copy
  146. // and then put a zero at the end.
  147. const string_type __one(__lo1, __hi1);
  148. const string_type __two(__lo2, __hi2);
  149. const _CharT* __p = __one.c_str();
  150. const _CharT* __pend = __one.data() + __one.length();
  151. const _CharT* __q = __two.c_str();
  152. const _CharT* __qend = __two.data() + __two.length();
  153. // strcoll stops when it sees a nul character so we break
  154. // the strings into zero-terminated substrings and pass those
  155. // to strcoll.
  156. for (;;)
  157. {
  158. const int __res = _M_compare(__p, __q);
  159. if (__res)
  160. return __res;
  161. __p += char_traits<_CharT>::length(__p);
  162. __q += char_traits<_CharT>::length(__q);
  163. if (__p == __pend && __q == __qend)
  164. return 0;
  165. else if (__p == __pend)
  166. return -1;
  167. else if (__q == __qend)
  168. return 1;
  169. __p++;
  170. __q++;
  171. }
  172. }
  173. template<typename _CharT>
  174. typename collate<_CharT>::string_type
  175. collate<_CharT>::
  176. do_transform(const _CharT* __lo, const _CharT* __hi) const
  177. {
  178. string_type __ret;
  179. // strxfrm assumes zero-terminated strings so we make a copy
  180. const string_type __str(__lo, __hi);
  181. const _CharT* __p = __str.c_str();
  182. const _CharT* __pend = __str.data() + __str.length();
  183. size_t __len = (__hi - __lo) * 2;
  184. _CharT* __c = new _CharT[__len];
  185. __try
  186. {
  187. // strxfrm stops when it sees a nul character so we break
  188. // the string into zero-terminated substrings and pass those
  189. // to strxfrm.
  190. for (;;)
  191. {
  192. // First try a buffer perhaps big enough.
  193. size_t __res = _M_transform(__c, __p, __len);
  194. // If the buffer was not large enough, try again with the
  195. // correct size.
  196. if (__res >= __len)
  197. {
  198. __len = __res + 1;
  199. delete [] __c, __c = 0;
  200. __c = new _CharT[__len];
  201. __res = _M_transform(__c, __p, __len);
  202. }
  203. __ret.append(__c, __res);
  204. __p += char_traits<_CharT>::length(__p);
  205. if (__p == __pend)
  206. break;
  207. __p++;
  208. __ret.push_back(_CharT());
  209. }
  210. }
  211. __catch(...)
  212. {
  213. delete [] __c;
  214. __throw_exception_again;
  215. }
  216. delete [] __c;
  217. return __ret;
  218. }
  219. template<typename _CharT>
  220. long
  221. collate<_CharT>::
  222. do_hash(const _CharT* __lo, const _CharT* __hi) const
  223. {
  224. unsigned long __val = 0;
  225. for (; __lo < __hi; ++__lo)
  226. __val =
  227. *__lo + ((__val << 7)
  228. | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
  229. __digits - 7)));
  230. return static_cast<long>(__val);
  231. }
  232. // Inhibit implicit instantiations for required instantiations,
  233. // which are defined via explicit instantiations elsewhere.
  234. #if _GLIBCXX_EXTERN_TEMPLATE
  235. extern template class collate<char>;
  236. extern template class collate_byname<char>;
  237. extern template
  238. const collate<char>&
  239. use_facet<collate<char> >(const locale&);
  240. extern template
  241. bool
  242. has_facet<collate<char> >(const locale&);
  243. #ifdef _GLIBCXX_USE_WCHAR_T
  244. extern template class collate<wchar_t>;
  245. extern template class collate_byname<wchar_t>;
  246. extern template
  247. const collate<wchar_t>&
  248. use_facet<collate<wchar_t> >(const locale&);
  249. extern template
  250. bool
  251. has_facet<collate<wchar_t> >(const locale&);
  252. #endif
  253. #endif
  254. _GLIBCXX_END_NAMESPACE_VERSION
  255. } // namespace std
  256. #endif