Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / libstdc++-v3 / include / bits / locale_classes.tcc
1 // Locale support -*- C++ -*-
2
3 // Copyright (C) 2007-2015 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::
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     use_facet(const locale& __loc)
133     {
134       const size_t __i = _Facet::id._M_id();
135       const locale::facet** __facets = __loc._M_impl->_M_facets;
136       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
137         __throw_bad_cast();
138 #if __cpp_rtti
139       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