1    	// Locale support -*- C++ -*-
2    	
3    	// Copyright (C) 2007-2013 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  	#ifdef __GXX_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  	#ifdef __GXX_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
299