1// Locale support -*- C++ -*-
2
3// Copyright (C) 2007, 2008, 2009, 2010, 2011 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
39namespace std _GLIBCXX_VISIBILITY(default)
40{
41_GLIBCXX_BEGIN_NAMESPACE_VERSION
42
43  template<typename _Facet>
44    locale::
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::
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  template<typename _Facet>
92    bool
93    has_facet(const locale& __loc) throw()
94    {
95      const size_t __i = _Facet::id._M_id();
96      const locale::facet** __facets = __loc._M_impl->_M_facets;
97      return (__i < __loc._M_impl->_M_facets_size
98#ifdef __GXX_RTTI
99	      && dynamic_cast<const _Facet*>(__facets[__i]));
100#else
101              && static_cast<const _Facet*>(__facets[__i]));
102#endif
103    }
104
105  template<typename _Facet>
106    const _Facet&
107    use_facet(const locale& __loc)
108    {
109      const size_t __i = _Facet::id._M_id();
110      const locale::facet** __facets = __loc._M_impl->_M_facets;
111      if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
112        __throw_bad_cast();
113#ifdef __GXX_RTTI
114      return dynamic_cast<const _Facet&>(*__facets[__i]);
115#else
116      return static_cast<const _Facet&>(*__facets[__i]);
117#endif
118    }
119
120
121  // Generic version does nothing.
122  template<typename _CharT>
123    int
124    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
125    { return 0; }
126
127  // Generic version does nothing.
128  template<typename _CharT>
129    size_t
130    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
131    { return 0; }
132
133  template<typename _CharT>
134    int
135    collate<_CharT>::
136    do_compare(const _CharT* __lo1, const _CharT* __hi1,
137	       const _CharT* __lo2, const _CharT* __hi2) const
138    {
139      // strcoll assumes zero-terminated strings so we make a copy
140      // and then put a zero at the end.
141      const string_type __one(__lo1, __hi1);
142      const string_type __two(__lo2, __hi2);
143
144      const _CharT* __p = __one.c_str();
145      const _CharT* __pend = __one.data() + __one.length();
146      const _CharT* __q = __two.c_str();
147      const _CharT* __qend = __two.data() + __two.length();
148
149      // strcoll stops when it sees a nul character so we break
150      // the strings into zero-terminated substrings and pass those
151      // to strcoll.
152      for (;;)
153	{
154	  const int __res = _M_compare(__p, __q);
155	  if (__res)
156	    return __res;
157
158	  __p += char_traits<_CharT>::length(__p);
159	  __q += char_traits<_CharT>::length(__q);
160	  if (__p == __pend && __q == __qend)
161	    return 0;
162	  else if (__p == __pend)
163	    return -1;
164	  else if (__q == __qend)
165	    return 1;
166
167	  __p++;
168	  __q++;
169	}
170    }
171
172  template<typename _CharT>
173    typename collate<_CharT>::string_type
174    collate<_CharT>::
175    do_transform(const _CharT* __lo, const _CharT* __hi) const
176    {
177      string_type __ret;
178
179      // strxfrm assumes zero-terminated strings so we make a copy
180      const string_type __str(__lo, __hi);
181
182      const _CharT* __p = __str.c_str();
183      const _CharT* __pend = __str.data() + __str.length();
184
185      size_t __len = (__hi - __lo) * 2;
186
187      _CharT* __c = new _CharT[__len];
188
189      __try
190	{
191	  // strxfrm stops when it sees a nul character so we break
192	  // the string into zero-terminated substrings and pass those
193	  // to strxfrm.
194	  for (;;)
195	    {
196	      // First try a buffer perhaps big enough.
197	      size_t __res = _M_transform(__c, __p, __len);
198	      // If the buffer was not large enough, try again with the
199	      // correct size.
200	      if (__res >= __len)
201		{
202		  __len = __res + 1;
203		  delete [] __c, __c = 0;
204		  __c = new _CharT[__len];
205		  __res = _M_transform(__c, __p, __len);
206		}
207
208	      __ret.append(__c, __res);
209	      __p += char_traits<_CharT>::length(__p);
210	      if (__p == __pend)
211		break;
212
213	      __p++;
214	      __ret.push_back(_CharT());
215	    }
216	}
217      __catch(...)
218	{
219	  delete [] __c;
220	  __throw_exception_again;
221	}
222
223      delete [] __c;
224
225      return __ret;
226    }
227
228  template<typename _CharT>
229    long
230    collate<_CharT>::
231    do_hash(const _CharT* __lo, const _CharT* __hi) const
232    {
233      unsigned long __val = 0;
234      for (; __lo < __hi; ++__lo)
235	__val =
236	  *__lo + ((__val << 7)
237		   | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
238				__digits - 7)));
239      return static_cast<long>(__val);
240    }
241
242  // Inhibit implicit instantiations for required instantiations,
243  // which are defined via explicit instantiations elsewhere.
244#if _GLIBCXX_EXTERN_TEMPLATE
245  extern template class collate<char>;
246  extern template class collate_byname<char>;
247
248  extern template
249    const collate<char>&
250    use_facet<collate<char> >(const locale&);
251
252  extern template
253    bool
254    has_facet<collate<char> >(const locale&);
255
256#ifdef _GLIBCXX_USE_WCHAR_T
257  extern template class collate<wchar_t>;
258  extern template class collate_byname<wchar_t>;
259
260  extern template
261    const collate<wchar_t>&
262    use_facet<collate<wchar_t> >(const locale&);
263
264  extern template
265    bool
266    has_facet<collate<wchar_t> >(const locale&);
267#endif
268#endif
269
270_GLIBCXX_END_NAMESPACE_VERSION
271} // namespace std
272
273#endif
274