xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/locale_classes.tcc (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 // Locale support -*- C++ -*-
2 
3 // Copyright (C) 2007, 2008, 2009 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 locale_classes.tcc
26  *  This is an internal header file, included by other library headers.
27  *  You should not attempt to use it directly.
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 _GLIBCXX_BEGIN_NAMESPACE(std)
40 
41   template<typename _Facet>
42     locale::
43     locale(const locale& __other, _Facet* __f)
44     {
45       _M_impl = new _Impl(*__other._M_impl, 1);
46 
47       __try
48 	{ _M_impl->_M_install_facet(&_Facet::id, __f); }
49       __catch(...)
50 	{
51 	  _M_impl->_M_remove_reference();
52 	  __throw_exception_again;
53 	}
54       delete [] _M_impl->_M_names[0];
55       _M_impl->_M_names[0] = 0;   // Unnamed.
56     }
57 
58   template<typename _Facet>
59     locale
60     locale::
61     combine(const locale& __other) const
62     {
63       _Impl* __tmp = new _Impl(*_M_impl, 1);
64       __try
65 	{
66 	  __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
67 	}
68       __catch(...)
69 	{
70 	  __tmp->_M_remove_reference();
71 	  __throw_exception_again;
72 	}
73       return locale(__tmp);
74     }
75 
76   template<typename _CharT, typename _Traits, typename _Alloc>
77     bool
78     locale::
79     operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
80 	       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
81     {
82       typedef std::collate<_CharT> __collate_type;
83       const __collate_type& __collate = use_facet<__collate_type>(*this);
84       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
85 				__s2.data(), __s2.data() + __s2.length()) < 0);
86     }
87 
88 
89   template<typename _Facet>
90     bool
91     has_facet(const locale& __loc) throw()
92     {
93       const size_t __i = _Facet::id._M_id();
94       const locale::facet** __facets = __loc._M_impl->_M_facets;
95       return (__i < __loc._M_impl->_M_facets_size
96 #ifdef __GXX_RTTI
97 	      && dynamic_cast<const _Facet*>(__facets[__i]));
98 #else
99               && static_cast<const _Facet*>(__facets[__i]));
100 #endif
101     }
102 
103   template<typename _Facet>
104     const _Facet&
105     use_facet(const locale& __loc)
106     {
107       const size_t __i = _Facet::id._M_id();
108       const locale::facet** __facets = __loc._M_impl->_M_facets;
109       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
110         __throw_bad_cast();
111 #ifdef __GXX_RTTI
112       return dynamic_cast<const _Facet&>(*__facets[__i]);
113 #else
114       return static_cast<const _Facet&>(*__facets[__i]);
115 #endif
116     }
117 
118 
119   // Generic version does nothing.
120   template<typename _CharT>
121     int
122     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
123     { return 0; }
124 
125   // Generic version does nothing.
126   template<typename _CharT>
127     size_t
128     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
129     { return 0; }
130 
131   template<typename _CharT>
132     int
133     collate<_CharT>::
134     do_compare(const _CharT* __lo1, const _CharT* __hi1,
135 	       const _CharT* __lo2, const _CharT* __hi2) const
136     {
137       // strcoll assumes zero-terminated strings so we make a copy
138       // and then put a zero at the end.
139       const string_type __one(__lo1, __hi1);
140       const string_type __two(__lo2, __hi2);
141 
142       const _CharT* __p = __one.c_str();
143       const _CharT* __pend = __one.data() + __one.length();
144       const _CharT* __q = __two.c_str();
145       const _CharT* __qend = __two.data() + __two.length();
146 
147       // strcoll stops when it sees a nul character so we break
148       // the strings into zero-terminated substrings and pass those
149       // to strcoll.
150       for (;;)
151 	{
152 	  const int __res = _M_compare(__p, __q);
153 	  if (__res)
154 	    return __res;
155 
156 	  __p += char_traits<_CharT>::length(__p);
157 	  __q += char_traits<_CharT>::length(__q);
158 	  if (__p == __pend && __q == __qend)
159 	    return 0;
160 	  else if (__p == __pend)
161 	    return -1;
162 	  else if (__q == __qend)
163 	    return 1;
164 
165 	  __p++;
166 	  __q++;
167 	}
168     }
169 
170   template<typename _CharT>
171     typename collate<_CharT>::string_type
172     collate<_CharT>::
173     do_transform(const _CharT* __lo, const _CharT* __hi) const
174     {
175       string_type __ret;
176 
177       // strxfrm assumes zero-terminated strings so we make a copy
178       const string_type __str(__lo, __hi);
179 
180       const _CharT* __p = __str.c_str();
181       const _CharT* __pend = __str.data() + __str.length();
182 
183       size_t __len = (__hi - __lo) * 2;
184 
185       _CharT* __c = new _CharT[__len];
186 
187       __try
188 	{
189 	  // strxfrm stops when it sees a nul character so we break
190 	  // the string into zero-terminated substrings and pass those
191 	  // to strxfrm.
192 	  for (;;)
193 	    {
194 	      // First try a buffer perhaps big enough.
195 	      size_t __res = _M_transform(__c, __p, __len);
196 	      // If the buffer was not large enough, try again with the
197 	      // correct size.
198 	      if (__res >= __len)
199 		{
200 		  __len = __res + 1;
201 		  delete [] __c, __c = 0;
202 		  __c = new _CharT[__len];
203 		  __res = _M_transform(__c, __p, __len);
204 		}
205 
206 	      __ret.append(__c, __res);
207 	      __p += char_traits<_CharT>::length(__p);
208 	      if (__p == __pend)
209 		break;
210 
211 	      __p++;
212 	      __ret.push_back(_CharT());
213 	    }
214 	}
215       __catch(...)
216 	{
217 	  delete [] __c;
218 	  __throw_exception_again;
219 	}
220 
221       delete [] __c;
222 
223       return __ret;
224     }
225 
226   template<typename _CharT>
227     long
228     collate<_CharT>::
229     do_hash(const _CharT* __lo, const _CharT* __hi) const
230     {
231       unsigned long __val = 0;
232       for (; __lo < __hi; ++__lo)
233 	__val =
234 	  *__lo + ((__val << 7)
235 		   | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
236 				__digits - 7)));
237       return static_cast<long>(__val);
238     }
239 
240   // Inhibit implicit instantiations for required instantiations,
241   // which are defined via explicit instantiations elsewhere.
242   // NB: This syntax is a GNU extension.
243 #if _GLIBCXX_EXTERN_TEMPLATE
244   extern template class collate<char>;
245   extern template class collate_byname<char>;
246 
247   extern template
248     const collate<char>&
249     use_facet<collate<char> >(const locale&);
250 
251   extern template
252     bool
253     has_facet<collate<char> >(const locale&);
254 
255 #ifdef _GLIBCXX_USE_WCHAR_T
256   extern template class collate<wchar_t>;
257   extern template class collate_byname<wchar_t>;
258 
259   extern template
260     const collate<wchar_t>&
261     use_facet<collate<wchar_t> >(const locale&);
262 
263   extern template
264     bool
265     has_facet<collate<wchar_t> >(const locale&);
266 #endif
267 #endif
268 
269 _GLIBCXX_END_NAMESPACE
270 
271 #endif
272