1    	// Locale support (codecvt) -*- C++ -*-
2    	
3    	// Copyright (C) 2000-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/codecvt.h
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.2.1.5 Template class codecvt
32   	//
33   	
34   	// Written by Benjamin Kosnik <bkoz@redhat.com>
35   	
36   	#ifndef _CODECVT_H
37   	#define _CODECVT_H 1
38   	
39   	#pragma GCC system_header
40   	
41   	namespace std _GLIBCXX_VISIBILITY(default)
42   	{
43   	_GLIBCXX_BEGIN_NAMESPACE_VERSION
44   	
45   	  /// Empty base class for codecvt facet [22.2.1.5].
46   	  class codecvt_base
47   	  {
48   	  public:
49   	    enum result
50   	    {
51   	      ok,
52   	      partial,
53   	      error,
54   	      noconv
55   	    };
56   	  };
57   	
58   	  /**
59   	   *  @brief  Common base for codecvt functions.
60   	   *
61   	   *  This template class provides implementations of the public functions
62   	   *  that forward to the protected virtual functions.
63   	   *
64   	   *  This template also provides abstract stubs for the protected virtual
65   	   *  functions.
66   	  */
67   	  template<typename _InternT, typename _ExternT, typename _StateT>
68   	    class __codecvt_abstract_base
69   	    : public locale::facet, public codecvt_base
70   	    {
71   	    public:
72   	      // Types:
73   	      typedef codecvt_base::result	result;
74   	      typedef _InternT			intern_type;
75   	      typedef _ExternT			extern_type;
76   	      typedef _StateT			state_type;
77   	
78   	      // 22.2.1.5.1 codecvt members
79   	      /**
80   	       *  @brief  Convert from internal to external character set.
81   	       *
82   	       *  Converts input string of intern_type to output string of
83   	       *  extern_type.  This is analogous to wcsrtombs.  It does this by
84   	       *  calling codecvt::do_out.
85   	       *
86   	       *  The source and destination character sets are determined by the
87   	       *  facet's locale, internal and external types.
88   	       *
89   	       *  The characters in [from,from_end) are converted and written to
90   	       *  [to,to_end).  from_next and to_next are set to point to the
91   	       *  character following the last successfully converted character,
92   	       *  respectively.  If the result needed no conversion, from_next and
93   	       *  to_next are not affected.
94   	       *
95   	       *  The @a state argument should be initialized if the input is at the
96   	       *  beginning and carried from a previous call if continuing
97   	       *  conversion.  There are no guarantees about how @a state is used.
98   	       *
99   	       *  The result returned is a member of codecvt_base::result.  If
100  	       *  all the input is converted, returns codecvt_base::ok.  If no
101  	       *  conversion is necessary, returns codecvt_base::noconv.  If
102  	       *  the input ends early or there is insufficient space in the
103  	       *  output, returns codecvt_base::partial.  Otherwise the
104  	       *  conversion failed and codecvt_base::error is returned.
105  	       *
106  	       *  @param  __state  Persistent conversion state data.
107  	       *  @param  __from  Start of input.
108  	       *  @param  __from_end  End of input.
109  	       *  @param  __from_next  Returns start of unconverted data.
110  	       *  @param  __to  Start of output buffer.
111  	       *  @param  __to_end  End of output buffer.
112  	       *  @param  __to_next  Returns start of unused output area.
113  	       *  @return  codecvt_base::result.
114  	      */
115  	      result
116  	      out(state_type& __state, const intern_type* __from,
117  		  const intern_type* __from_end, const intern_type*& __from_next,
118  		  extern_type* __to, extern_type* __to_end,
119  		  extern_type*& __to_next) const
120  	      {
121  		return this->do_out(__state, __from, __from_end, __from_next,
122  				    __to, __to_end, __to_next);
123  	      }
124  	
125  	      /**
126  	       *  @brief  Reset conversion state.
127  	       *
128  	       *  Writes characters to output that would restore @a state to initial
129  	       *  conditions.  The idea is that if a partial conversion occurs, then
130  	       *  the converting the characters written by this function would leave
131  	       *  the state in initial conditions, rather than partial conversion
132  	       *  state.  It does this by calling codecvt::do_unshift().
133  	       *
134  	       *  For example, if 4 external characters always converted to 1 internal
135  	       *  character, and input to in() had 6 external characters with state
136  	       *  saved, this function would write two characters to the output and
137  	       *  set the state to initialized conditions.
138  	       *
139  	       *  The source and destination character sets are determined by the
140  	       *  facet's locale, internal and external types.
141  	       *
142  	       *  The result returned is a member of codecvt_base::result.  If the
143  	       *  state could be reset and data written, returns codecvt_base::ok.  If
144  	       *  no conversion is necessary, returns codecvt_base::noconv.  If the
145  	       *  output has insufficient space, returns codecvt_base::partial.
146  	       *  Otherwise the reset failed and codecvt_base::error is returned.
147  	       *
148  	       *  @param  __state  Persistent conversion state data.
149  	       *  @param  __to  Start of output buffer.
150  	       *  @param  __to_end  End of output buffer.
151  	       *  @param  __to_next  Returns start of unused output area.
152  	       *  @return  codecvt_base::result.
153  	      */
154  	      result
155  	      unshift(state_type& __state, extern_type* __to, extern_type* __to_end,
156  		      extern_type*& __to_next) const
157  	      { return this->do_unshift(__state, __to,__to_end,__to_next); }
158  	
159  	      /**
160  	       *  @brief  Convert from external to internal character set.
161  	       *
162  	       *  Converts input string of extern_type to output string of
163  	       *  intern_type.  This is analogous to mbsrtowcs.  It does this by
164  	       *  calling codecvt::do_in.
165  	       *
166  	       *  The source and destination character sets are determined by the
167  	       *  facet's locale, internal and external types.
168  	       *
169  	       *  The characters in [from,from_end) are converted and written to
170  	       *  [to,to_end).  from_next and to_next are set to point to the
171  	       *  character following the last successfully converted character,
172  	       *  respectively.  If the result needed no conversion, from_next and
173  	       *  to_next are not affected.
174  	       *
175  	       *  The @a state argument should be initialized if the input is at the
176  	       *  beginning and carried from a previous call if continuing
177  	       *  conversion.  There are no guarantees about how @a state is used.
178  	       *
179  	       *  The result returned is a member of codecvt_base::result.  If
180  	       *  all the input is converted, returns codecvt_base::ok.  If no
181  	       *  conversion is necessary, returns codecvt_base::noconv.  If
182  	       *  the input ends early or there is insufficient space in the
183  	       *  output, returns codecvt_base::partial.  Otherwise the
184  	       *  conversion failed and codecvt_base::error is returned.
185  	       *
186  	       *  @param  __state  Persistent conversion state data.
187  	       *  @param  __from  Start of input.
188  	       *  @param  __from_end  End of input.
189  	       *  @param  __from_next  Returns start of unconverted data.
190  	       *  @param  __to  Start of output buffer.
191  	       *  @param  __to_end  End of output buffer.
192  	       *  @param  __to_next  Returns start of unused output area.
193  	       *  @return  codecvt_base::result.
194  	      */
195  	      result
196  	      in(state_type& __state, const extern_type* __from,
197  		 const extern_type* __from_end, const extern_type*& __from_next,
198  		 intern_type* __to, intern_type* __to_end,
199  		 intern_type*& __to_next) const
200  	      {
201  		return this->do_in(__state, __from, __from_end, __from_next,
202  				   __to, __to_end, __to_next);
203  	      }
204  	
205  	      int
206  	      encoding() const throw()
207  	      { return this->do_encoding(); }
208  	
209  	      bool
210  	      always_noconv() const throw()
211  	      { return this->do_always_noconv(); }
212  	
213  	      int
214  	      length(state_type& __state, const extern_type* __from,
215  		     const extern_type* __end, size_t __max) const
216  	      { return this->do_length(__state, __from, __end, __max); }
217  	
218  	      int
219  	      max_length() const throw()
220  	      { return this->do_max_length(); }
221  	
222  	    protected:
223  	      explicit
224  	      __codecvt_abstract_base(size_t __refs = 0) : locale::facet(__refs) { }
225  	
226  	      virtual
227  	      ~__codecvt_abstract_base() { }
228  	
229  	      /**
230  	       *  @brief  Convert from internal to external character set.
231  	       *
232  	       *  Converts input string of intern_type to output string of
233  	       *  extern_type.  This function is a hook for derived classes to change
234  	       *  the value returned.  @see out for more information.
235  	      */
236  	      virtual result
237  	      do_out(state_type& __state, const intern_type* __from,
238  		     const intern_type* __from_end, const intern_type*& __from_next,
239  		     extern_type* __to, extern_type* __to_end,
240  		     extern_type*& __to_next) const = 0;
241  	
242  	      virtual result
243  	      do_unshift(state_type& __state, extern_type* __to,
244  			 extern_type* __to_end, extern_type*& __to_next) const = 0;
245  	
246  	      virtual result
247  	      do_in(state_type& __state, const extern_type* __from,
248  		    const extern_type* __from_end, const extern_type*& __from_next,
249  		    intern_type* __to, intern_type* __to_end,
250  		    intern_type*& __to_next) const = 0;
251  	
252  	      virtual int
253  	      do_encoding() const throw() = 0;
254  	
255  	      virtual bool
256  	      do_always_noconv() const throw() = 0;
257  	
258  	      virtual int
259  	      do_length(state_type&, const extern_type* __from,
260  			const extern_type* __end, size_t __max) const = 0;
261  	
262  	      virtual int
263  	      do_max_length() const throw() = 0;
264  	    };
265  	
266  	
267  	
268  	  /**
269  	   *  @brief  Primary class template codecvt.
270  	   *  @ingroup locales
271  	   *
272  	   *  NB: Generic, mostly useless implementation.
273  	   *
274  	  */
275  	   template<typename _InternT, typename _ExternT, typename _StateT>
276  	    class codecvt
277  	    : public __codecvt_abstract_base<_InternT, _ExternT, _StateT>
278  	    {
279  	    public:
280  	      // Types:
281  	      typedef codecvt_base::result	result;
282  	      typedef _InternT			intern_type;
283  	      typedef _ExternT			extern_type;
284  	      typedef _StateT			state_type;
285  	
286  	    protected:
287  	      __c_locale			_M_c_locale_codecvt;
288  	
289  	    public:
290  	      static locale::id			id;
291  	
292  	      explicit
293  	      codecvt(size_t __refs = 0)
294  	      : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs),
295  		_M_c_locale_codecvt(0)
296  	      { }
297  	
298  	      explicit
299  	      codecvt(__c_locale __cloc, size_t __refs = 0);
300  	
301  	    protected:
302  	      virtual
303  	      ~codecvt() { }
304  	
305  	      virtual result
306  	      do_out(state_type& __state, const intern_type* __from,
307  		     const intern_type* __from_end, const intern_type*& __from_next,
308  		     extern_type* __to, extern_type* __to_end,
309  		     extern_type*& __to_next) const;
310  	
311  	      virtual result
312  	      do_unshift(state_type& __state, extern_type* __to,
313  			 extern_type* __to_end, extern_type*& __to_next) const;
314  	
315  	      virtual result
316  	      do_in(state_type& __state, const extern_type* __from,
317  		    const extern_type* __from_end, const extern_type*& __from_next,
318  		    intern_type* __to, intern_type* __to_end,
319  		    intern_type*& __to_next) const;
320  	
321  	      virtual int
322  	      do_encoding() const throw();
323  	
324  	      virtual bool
325  	      do_always_noconv() const throw();
326  	
327  	      virtual int
328  	      do_length(state_type&, const extern_type* __from,
329  			const extern_type* __end, size_t __max) const;
330  	
331  	      virtual int
332  	      do_max_length() const throw();
333  	    };
334  	
335  	  template<typename _InternT, typename _ExternT, typename _StateT>
336  	    locale::id codecvt<_InternT, _ExternT, _StateT>::id;
337  	
338  	  /// class codecvt<char, char, mbstate_t> specialization.
339  	  template<>
340  	    class codecvt<char, char, mbstate_t>
341  	    : public __codecvt_abstract_base<char, char, mbstate_t>
342  	    {
343  	    public:
344  	      // Types:
345  	      typedef char			intern_type;
346  	      typedef char			extern_type;
347  	      typedef mbstate_t			state_type;
348  	
349  	    protected:
350  	      __c_locale			_M_c_locale_codecvt;
351  	
352  	    public:
353  	      static locale::id id;
354  	
355  	      explicit
356  	      codecvt(size_t __refs = 0);
357  	
358  	      explicit
359  	      codecvt(__c_locale __cloc, size_t __refs = 0);
360  	
361  	    protected:
362  	      virtual
363  	      ~codecvt();
364  	
365  	      virtual result
366  	      do_out(state_type& __state, const intern_type* __from,
367  		     const intern_type* __from_end, const intern_type*& __from_next,
368  		     extern_type* __to, extern_type* __to_end,
369  		     extern_type*& __to_next) const;
370  	
371  	      virtual result
372  	      do_unshift(state_type& __state, extern_type* __to,
373  			 extern_type* __to_end, extern_type*& __to_next) const;
374  	
375  	      virtual result
376  	      do_in(state_type& __state, const extern_type* __from,
377  		    const extern_type* __from_end, const extern_type*& __from_next,
378  		    intern_type* __to, intern_type* __to_end,
379  		    intern_type*& __to_next) const;
380  	
381  	      virtual int
382  	      do_encoding() const throw();
383  	
384  	      virtual bool
385  	      do_always_noconv() const throw();
386  	
387  	      virtual int
388  	      do_length(state_type&, const extern_type* __from,
389  			const extern_type* __end, size_t __max) const;
390  	
391  	      virtual int
392  	      do_max_length() const throw();
393  	  };
394  	
395  	#ifdef _GLIBCXX_USE_WCHAR_T
396  	  /// class codecvt<wchar_t, char, mbstate_t> specialization.
397  	  template<>
398  	    class codecvt<wchar_t, char, mbstate_t>
399  	    : public __codecvt_abstract_base<wchar_t, char, mbstate_t>
400  	    {
401  	    public:
402  	      // Types:
403  	      typedef wchar_t			intern_type;
404  	      typedef char			extern_type;
405  	      typedef mbstate_t			state_type;
406  	
407  	    protected:
408  	      __c_locale			_M_c_locale_codecvt;
409  	
410  	    public:
411  	      static locale::id			id;
412  	
413  	      explicit
414  	      codecvt(size_t __refs = 0);
415  	
416  	      explicit
417  	      codecvt(__c_locale __cloc, size_t __refs = 0);
418  	
419  	    protected:
420  	      virtual
421  	      ~codecvt();
422  	
423  	      virtual result
424  	      do_out(state_type& __state, const intern_type* __from,
425  		     const intern_type* __from_end, const intern_type*& __from_next,
426  		     extern_type* __to, extern_type* __to_end,
427  		     extern_type*& __to_next) const;
428  	
429  	      virtual result
430  	      do_unshift(state_type& __state,
431  			 extern_type* __to, extern_type* __to_end,
432  			 extern_type*& __to_next) const;
433  	
434  	      virtual result
435  	      do_in(state_type& __state,
436  		     const extern_type* __from, const extern_type* __from_end,
437  		     const extern_type*& __from_next,
438  		     intern_type* __to, intern_type* __to_end,
439  		     intern_type*& __to_next) const;
440  	
441  	      virtual
442  	      int do_encoding() const throw();
443  	
444  	      virtual
445  	      bool do_always_noconv() const throw();
446  	
447  	      virtual
448  	      int do_length(state_type&, const extern_type* __from,
449  			    const extern_type* __end, size_t __max) const;
450  	
451  	      virtual int
452  	      do_max_length() const throw();
453  	    };
454  	#endif //_GLIBCXX_USE_WCHAR_T
455  	
456  	  /// class codecvt_byname [22.2.1.6].
457  	  template<typename _InternT, typename _ExternT, typename _StateT>
458  	    class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT>
459  	    {
460  	    public:
461  	      explicit
462  	      codecvt_byname(const char* __s, size_t __refs = 0)
463  	      : codecvt<_InternT, _ExternT, _StateT>(__refs)
464  	      {
465  		if (__builtin_strcmp(__s, "C") != 0
466  		    && __builtin_strcmp(__s, "POSIX") != 0)
467  		  {
468  		    this->_S_destroy_c_locale(this->_M_c_locale_codecvt);
469  		    this->_S_create_c_locale(this->_M_c_locale_codecvt, __s);
470  		  }
471  	      }
472  	
473  	    protected:
474  	      virtual
475  	      ~codecvt_byname() { }
476  	    };
477  	
478  	  // Inhibit implicit instantiations for required instantiations,
479  	  // which are defined via explicit instantiations elsewhere.
480  	#if _GLIBCXX_EXTERN_TEMPLATE
481  	  extern template class codecvt_byname<char, char, mbstate_t>;
482  	
483  	  extern template
484  	    const codecvt<char, char, mbstate_t>&
485  	    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
486  	
487  	  extern template
488  	    bool
489  	    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
490  	
491  	#ifdef _GLIBCXX_USE_WCHAR_T
492  	  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
493  	
494  	  extern template
495  	    const codecvt<wchar_t, char, mbstate_t>&
496  	    use_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
497  	
498  	  extern template
499  	    bool
500  	    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
501  	#endif
502  	#endif
503  	
504  	_GLIBCXX_END_NAMESPACE_VERSION
505  	} // namespace std
506  	
507  	#endif // _CODECVT_H
508