Line data Source code
1 : // Locale support -*- C++ -*-
2 :
3 : // Copyright (C) 2007-2019 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 0 : locale::
45 : locale(const locale& __other, _Facet* __f)
46 : {
47 0 : _M_impl = new _Impl(*__other._M_impl, 1);
48 :
49 : __try
50 0 : { _M_impl->_M_install_facet(&_Facet::id, __f); }
51 0 : __catch(...)
52 : {
53 0 : _M_impl->_M_remove_reference();
54 0 : __throw_exception_again;
55 : }
56 0 : delete [] _M_impl->_M_names[0];
57 0 : _M_impl->_M_names[0] = 0; // Unnamed.
58 0 : }
59 :
60 : template<typename _Facet>
61 : locale
62 : 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::
81 : 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
104 : has_facet(const locale& __loc) throw()
105 : {
106 : const size_t __i = _Facet::id._M_id();
107 : const locale::facet** __facets = __loc._M_impl->_M_facets;
108 : return (__i < __loc._M_impl->_M_facets_size
109 : #if __cpp_rtti
110 : && dynamic_cast<const _Facet*>(__facets[__i]));
111 : #else
112 : && static_cast<const _Facet*>(__facets[__i]));
113 : #endif
114 : }
115 :
116 : /**
117 : * @brief Return a facet.
118 : * @ingroup locales
119 : *
120 : * use_facet looks for and returns a reference to a facet of type Facet
121 : * where Facet is the template parameter. If has_facet(locale) is true,
122 : * there is a suitable facet to return. It throws std::bad_cast if the
123 : * locale doesn't contain a facet of type Facet.
124 : *
125 : * @tparam _Facet The facet type to access.
126 : * @param __loc The locale to use.
127 : * @return Reference to facet of type Facet.
128 : * @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
129 : */
130 : template<typename _Facet>
131 : const _Facet&
132 955 : use_facet(const locale& __loc)
133 : {
134 955 : const size_t __i = _Facet::id._M_id();
135 955 : const locale::facet** __facets = __loc._M_impl->_M_facets;
136 955 : if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
137 0 : __throw_bad_cast();
138 : #if __cpp_rtti
139 955 : return dynamic_cast<const _Facet&>(*__facets[__i]);
140 : #else
141 : return static_cast<const _Facet&>(*__facets[__i]);
142 : #endif
143 : }
144 :
145 :
146 : // Generic version does nothing.
147 : template<typename _CharT>
148 : int
149 : collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
150 : { return 0; }
151 :
152 : // Generic version does nothing.
153 : template<typename _CharT>
154 : size_t
155 : collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
156 : { return 0; }
157 :
158 : template<typename _CharT>
159 : int
160 : collate<_CharT>::
161 : do_compare(const _CharT* __lo1, const _CharT* __hi1,
162 : const _CharT* __lo2, const _CharT* __hi2) const
163 : {
164 : // strcoll assumes zero-terminated strings so we make a copy
165 : // and then put a zero at the end.
166 : const string_type __one(__lo1, __hi1);
167 : const string_type __two(__lo2, __hi2);
168 :
169 : const _CharT* __p = __one.c_str();
170 : const _CharT* __pend = __one.data() + __one.length();
171 : const _CharT* __q = __two.c_str();
172 : const _CharT* __qend = __two.data() + __two.length();
173 :
174 : // strcoll stops when it sees a nul character so we break
175 : // the strings into zero-terminated substrings and pass those
176 : // to strcoll.
177 : for (;;)
178 : {
179 : const int __res = _M_compare(__p, __q);
180 : if (__res)
181 : return __res;
182 :
183 : __p += char_traits<_CharT>::length(__p);
184 : __q += char_traits<_CharT>::length(__q);
185 : if (__p == __pend && __q == __qend)
186 : return 0;
187 : else if (__p == __pend)
188 : return -1;
189 : else if (__q == __qend)
190 : return 1;
191 :
192 : __p++;
193 : __q++;
194 : }
195 : }
196 :
197 : template<typename _CharT>
198 : typename collate<_CharT>::string_type
199 : collate<_CharT>::
200 : do_transform(const _CharT* __lo, const _CharT* __hi) const
201 : {
202 : string_type __ret;
203 :
204 : // strxfrm assumes zero-terminated strings so we make a copy
205 : const string_type __str(__lo, __hi);
206 :
207 : const _CharT* __p = __str.c_str();
208 : const _CharT* __pend = __str.data() + __str.length();
209 :
210 : size_t __len = (__hi - __lo) * 2;
211 :
212 : _CharT* __c = new _CharT[__len];
213 :
214 : __try
215 : {
216 : // strxfrm stops when it sees a nul character so we break
217 : // the string into zero-terminated substrings and pass those
218 : // to strxfrm.
219 : for (;;)
220 : {
221 : // First try a buffer perhaps big enough.
222 : size_t __res = _M_transform(__c, __p, __len);
223 : // If the buffer was not large enough, try again with the
224 : // correct size.
225 : if (__res >= __len)
226 : {
227 : __len = __res + 1;
228 : delete [] __c, __c = 0;
229 : __c = new _CharT[__len];
230 : __res = _M_transform(__c, __p, __len);
231 : }
232 :
233 : __ret.append(__c, __res);
234 : __p += char_traits<_CharT>::length(__p);
235 : if (__p == __pend)
236 : break;
237 :
238 : __p++;
239 : __ret.push_back(_CharT());
240 : }
241 : }
242 : __catch(...)
243 : {
244 : delete [] __c;
245 : __throw_exception_again;
246 : }
247 :
248 : delete [] __c;
249 :
250 : return __ret;
251 : }
252 :
253 : template<typename _CharT>
254 : long
255 : collate<_CharT>::
256 : do_hash(const _CharT* __lo, const _CharT* __hi) const
257 : {
258 : unsigned long __val = 0;
259 : for (; __lo < __hi; ++__lo)
260 : __val =
261 : *__lo + ((__val << 7)
262 : | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
263 : __digits - 7)));
264 : return static_cast<long>(__val);
265 : }
266 :
267 : // Inhibit implicit instantiations for required instantiations,
268 : // which are defined via explicit instantiations elsewhere.
269 : #if _GLIBCXX_EXTERN_TEMPLATE
270 : extern template class collate<char>;
271 : extern template class collate_byname<char>;
272 :
273 : extern template
274 : const collate<char>&
275 : use_facet<collate<char> >(const locale&);
276 :
277 : extern template
278 : bool
279 : has_facet<collate<char> >(const locale&);
280 :
281 : #ifdef _GLIBCXX_USE_WCHAR_T
282 : extern template class collate<wchar_t>;
283 : extern template class collate_byname<wchar_t>;
284 :
285 : extern template
286 : const collate<wchar_t>&
287 : use_facet<collate<wchar_t> >(const locale&);
288 :
289 : extern template
290 : bool
291 : has_facet<collate<wchar_t> >(const locale&);
292 : #endif
293 : #endif
294 :
295 : _GLIBCXX_END_NAMESPACE_VERSION
296 : } // namespace std
297 :
298 : #endif
|