libstdc++
locale_classes.tcc
Go to the documentation of this file.
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 
39 namespace 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::
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
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>
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
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