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