xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/locale_classes.tcc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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>
44     locale::
locale(const locale & __other,_Facet * __f)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
62     locale::
combine(const locale & __other) const63     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::
operator ()(const basic_string<_CharT,_Traits,_Alloc> & __s1,const basic_string<_CharT,_Traits,_Alloc> & __s2) const81     operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
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
has_facet(const locale & __loc)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&
use_facet(const locale & __loc)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
_M_compare(const _CharT *,const _CharT *) const172     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
_M_transform(_CharT *,const _CharT *,size_t) const178     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
179     { return 0; }
180 
181   template<typename _CharT>
182     int
183     collate<_CharT>::
do_compare(const _CharT * __lo1,const _CharT * __hi1,const _CharT * __lo2,const _CharT * __hi2) const184     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>
221     typename collate<_CharT>::string_type
222     collate<_CharT>::
do_transform(const _CharT * __lo,const _CharT * __hi) const223     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
278     collate<_CharT>::
do_hash(const _CharT * __lo,const _CharT * __hi) const279     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
322