197403Sobrien// Locale support (codecvt) -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
4169691Skan//  Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
31169691Skan/** @file bits/codecvt.h
32169691Skan *  This is an internal header file, included by other library headers.
33169691Skan *  You should not attempt to use it directly.
34169691Skan */
35169691Skan
3697403Sobrien//
3797403Sobrien// ISO C++ 14882: 22.2.1.5 Template class codecvt
3897403Sobrien//
3997403Sobrien
40169691Skan// Written by Benjamin Kosnik <bkoz@redhat.com>
4197403Sobrien
42132720Skan#ifndef _CODECVT_H
43132720Skan#define _CODECVT_H 1
4497403Sobrien
4597403Sobrien#pragma GCC system_header
4697403Sobrien
47169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
48169691Skan
49169691Skan  /// @brief  Empty base class for codecvt facet [22.2.1.5].
5097403Sobrien  class codecvt_base
5197403Sobrien  {
5297403Sobrien  public:
5397403Sobrien    enum result
5497403Sobrien    {
5597403Sobrien      ok,
5697403Sobrien      partial,
5797403Sobrien      error,
5897403Sobrien      noconv
5997403Sobrien    };
6097403Sobrien  };
6197403Sobrien
62132720Skan  /**
63169691Skan   *  @brief  Common base for codecvt functions.
64132720Skan   *
65132720Skan   *  This template class provides implementations of the public functions
66132720Skan   *  that forward to the protected virtual functions.
67132720Skan   *
68132720Skan   *  This template also provides abstract stubs for the protected virtual
69132720Skan   *  functions.
70132720Skan  */
7197403Sobrien  template<typename _InternT, typename _ExternT, typename _StateT>
72132720Skan    class __codecvt_abstract_base
7397403Sobrien    : public locale::facet, public codecvt_base
7497403Sobrien    {
7597403Sobrien    public:
7697403Sobrien      // Types:
77103447Skan      typedef codecvt_base::result	result;
78132720Skan      typedef _InternT			intern_type;
79132720Skan      typedef _ExternT			extern_type;
80132720Skan      typedef _StateT			state_type;
81132720Skan
8297403Sobrien      // 22.2.1.5.1 codecvt members
83132720Skan      /**
84132720Skan       *  @brief  Convert from internal to external character set.
85132720Skan       *
86132720Skan       *  Converts input string of intern_type to output string of
87132720Skan       *  extern_type.  This is analogous to wcsrtombs.  It does this by
88132720Skan       *  calling codecvt::do_out.
89132720Skan       *
90132720Skan       *  The source and destination character sets are determined by the
91132720Skan       *  facet's locale, internal and external types.
92132720Skan       *
93132720Skan       *  The characters in [from,from_end) are converted and written to
94132720Skan       *  [to,to_end).  from_next and to_next are set to point to the
95132720Skan       *  character following the last successfully converted character,
96132720Skan       *  respectively.  If the result needed no conversion, from_next and
97132720Skan       *  to_next are not affected.
98132720Skan       *
99132720Skan       *  The @a state argument should be intialized if the input is at the
100132720Skan       *  beginning and carried from a previous call if continuing
101132720Skan       *  conversion.  There are no guarantees about how @a state is used.
102132720Skan       *
103169691Skan       *  The result returned is a member of codecvt_base::result.  If
104169691Skan       *  all the input is converted, returns codecvt_base::ok.  If no
105169691Skan       *  conversion is necessary, returns codecvt_base::noconv.  If
106169691Skan       *  the input ends early or there is insufficient space in the
107169691Skan       *  output, returns codecvt_base::partial.  Otherwise the
108169691Skan       *  conversion failed and codecvt_base::error is returned.
109132720Skan       *
110132720Skan       *  @param  state  Persistent conversion state data.
111132720Skan       *  @param  from  Start of input.
112132720Skan       *  @param  from_end  End of input.
113132720Skan       *  @param  from_next  Returns start of unconverted data.
114132720Skan       *  @param  to  Start of output buffer.
115132720Skan       *  @param  to_end  End of output buffer.
116132720Skan       *  @param  to_next  Returns start of unused output area.
117132720Skan       *  @return  codecvt_base::result.
118132720Skan      */
11997403Sobrien      result
120132720Skan      out(state_type& __state, const intern_type* __from,
12197403Sobrien	  const intern_type* __from_end, const intern_type*& __from_next,
122132720Skan	  extern_type* __to, extern_type* __to_end,
12397403Sobrien	  extern_type*& __to_next) const
124132720Skan      {
125132720Skan	return this->do_out(__state, __from, __from_end, __from_next,
126132720Skan			    __to, __to_end, __to_next);
12797403Sobrien      }
12897403Sobrien
129132720Skan      /**
130132720Skan       *  @brief  Reset conversion state.
131132720Skan       *
132132720Skan       *  Writes characters to output that would restore @a state to initial
133132720Skan       *  conditions.  The idea is that if a partial conversion occurs, then
134132720Skan       *  the converting the characters written by this function would leave
135132720Skan       *  the state in initial conditions, rather than partial conversion
136132720Skan       *  state.  It does this by calling codecvt::do_unshift().
137132720Skan       *
138132720Skan       *  For example, if 4 external characters always converted to 1 internal
139132720Skan       *  character, and input to in() had 6 external characters with state
140132720Skan       *  saved, this function would write two characters to the output and
141132720Skan       *  set the state to initialized conditions.
142132720Skan       *
143132720Skan       *  The source and destination character sets are determined by the
144132720Skan       *  facet's locale, internal and external types.
145132720Skan       *
146132720Skan       *  The result returned is a member of codecvt_base::result.  If the
147132720Skan       *  state could be reset and data written, returns codecvt_base::ok.  If
148132720Skan       *  no conversion is necessary, returns codecvt_base::noconv.  If the
149132720Skan       *  output has insufficient space, returns codecvt_base::partial.
150132720Skan       *  Otherwise the reset failed and codecvt_base::error is returned.
151132720Skan       *
152132720Skan       *  @param  state  Persistent conversion state data.
153132720Skan       *  @param  to  Start of output buffer.
154132720Skan       *  @param  to_end  End of output buffer.
155132720Skan       *  @param  to_next  Returns start of unused output area.
156132720Skan       *  @return  codecvt_base::result.
157132720Skan      */
15897403Sobrien      result
15997403Sobrien      unshift(state_type& __state, extern_type* __to, extern_type* __to_end,
16097403Sobrien	      extern_type*& __to_next) const
16197403Sobrien      { return this->do_unshift(__state, __to,__to_end,__to_next); }
16297403Sobrien
163132720Skan      /**
164132720Skan       *  @brief  Convert from external to internal character set.
165132720Skan       *
166132720Skan       *  Converts input string of extern_type to output string of
167132720Skan       *  intern_type.  This is analogous to mbsrtowcs.  It does this by
168132720Skan       *  calling codecvt::do_in.
169132720Skan       *
170132720Skan       *  The source and destination character sets are determined by the
171132720Skan       *  facet's locale, internal and external types.
172132720Skan       *
173132720Skan       *  The characters in [from,from_end) are converted and written to
174132720Skan       *  [to,to_end).  from_next and to_next are set to point to the
175132720Skan       *  character following the last successfully converted character,
176132720Skan       *  respectively.  If the result needed no conversion, from_next and
177132720Skan       *  to_next are not affected.
178132720Skan       *
179132720Skan       *  The @a state argument should be intialized if the input is at the
180132720Skan       *  beginning and carried from a previous call if continuing
181132720Skan       *  conversion.  There are no guarantees about how @a state is used.
182132720Skan       *
183169691Skan       *  The result returned is a member of codecvt_base::result.  If
184169691Skan       *  all the input is converted, returns codecvt_base::ok.  If no
185169691Skan       *  conversion is necessary, returns codecvt_base::noconv.  If
186169691Skan       *  the input ends early or there is insufficient space in the
187169691Skan       *  output, returns codecvt_base::partial.  Otherwise the
188169691Skan       *  conversion failed and codecvt_base::error is returned.
189132720Skan       *
190132720Skan       *  @param  state  Persistent conversion state data.
191132720Skan       *  @param  from  Start of input.
192132720Skan       *  @param  from_end  End of input.
193132720Skan       *  @param  from_next  Returns start of unconverted data.
194132720Skan       *  @param  to  Start of output buffer.
195132720Skan       *  @param  to_end  End of output buffer.
196132720Skan       *  @param  to_next  Returns start of unused output area.
197132720Skan       *  @return  codecvt_base::result.
198132720Skan      */
19997403Sobrien      result
200132720Skan      in(state_type& __state, const extern_type* __from,
20197403Sobrien	 const extern_type* __from_end, const extern_type*& __from_next,
202132720Skan	 intern_type* __to, intern_type* __to_end,
20397403Sobrien	 intern_type*& __to_next) const
204132720Skan      {
20597403Sobrien	return this->do_in(__state, __from, __from_end, __from_next,
206132720Skan			   __to, __to_end, __to_next);
20797403Sobrien      }
20897403Sobrien
209132720Skan      int
21097403Sobrien      encoding() const throw()
21197403Sobrien      { return this->do_encoding(); }
21297403Sobrien
213132720Skan      bool
21497403Sobrien      always_noconv() const throw()
21597403Sobrien      { return this->do_always_noconv(); }
21697403Sobrien
21797403Sobrien      int
218132720Skan      length(state_type& __state, const extern_type* __from,
21997403Sobrien	     const extern_type* __end, size_t __max) const
22097403Sobrien      { return this->do_length(__state, __from, __end, __max); }
22197403Sobrien
222132720Skan      int
22397403Sobrien      max_length() const throw()
22497403Sobrien      { return this->do_max_length(); }
22597403Sobrien
22697403Sobrien    protected:
227132720Skan      explicit
22897403Sobrien      __codecvt_abstract_base(size_t __refs = 0) : locale::facet(__refs) { }
22997403Sobrien
230132720Skan      virtual
23197403Sobrien      ~__codecvt_abstract_base() { }
23297403Sobrien
233132720Skan      /**
234132720Skan       *  @brief  Convert from internal to external character set.
235132720Skan       *
236132720Skan       *  Converts input string of intern_type to output string of
237132720Skan       *  extern_type.  This function is a hook for derived classes to change
238132720Skan       *  the value returned.  @see out for more information.
239132720Skan      */
24097403Sobrien      virtual result
241132720Skan      do_out(state_type& __state, const intern_type* __from,
24297403Sobrien	     const intern_type* __from_end, const intern_type*& __from_next,
24397403Sobrien	     extern_type* __to, extern_type* __to_end,
24497403Sobrien	     extern_type*& __to_next) const = 0;
24597403Sobrien
24697403Sobrien      virtual result
247132720Skan      do_unshift(state_type& __state, extern_type* __to,
24897403Sobrien		 extern_type* __to_end, extern_type*& __to_next) const = 0;
249132720Skan
25097403Sobrien      virtual result
251132720Skan      do_in(state_type& __state, const extern_type* __from,
252132720Skan	    const extern_type* __from_end, const extern_type*& __from_next,
253132720Skan	    intern_type* __to, intern_type* __to_end,
25497403Sobrien	    intern_type*& __to_next) const = 0;
255132720Skan
256132720Skan      virtual int
25797403Sobrien      do_encoding() const throw() = 0;
25897403Sobrien
259132720Skan      virtual bool
26097403Sobrien      do_always_noconv() const throw() = 0;
26197403Sobrien
262132720Skan      virtual int
263132720Skan      do_length(state_type&, const extern_type* __from,
26497403Sobrien		const extern_type* __end, size_t __max) const = 0;
26597403Sobrien
266132720Skan      virtual int
26797403Sobrien      do_max_length() const throw() = 0;
26897403Sobrien    };
26997403Sobrien
270169691Skan  /// @brief class codecvt [22.2.1.5].
271169691Skan  /// NB: Generic, mostly useless implementation.
27297403Sobrien  template<typename _InternT, typename _ExternT, typename _StateT>
273132720Skan    class codecvt
27497403Sobrien    : public __codecvt_abstract_base<_InternT, _ExternT, _StateT>
27597403Sobrien    {
276132720Skan    public:
27797403Sobrien      // Types:
278103447Skan      typedef codecvt_base::result	result;
279132720Skan      typedef _InternT			intern_type;
280132720Skan      typedef _ExternT			extern_type;
281132720Skan      typedef _StateT			state_type;
28297403Sobrien
283132720Skan    protected:
284132720Skan      __c_locale			_M_c_locale_codecvt;
285132720Skan
286103447Skan    public:
287132720Skan      static locale::id			id;
28897403Sobrien
289132720Skan      explicit
290132720Skan      codecvt(size_t __refs = 0)
291103447Skan      : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs) { }
29297403Sobrien
293132720Skan      explicit
294132720Skan      codecvt(__c_locale __cloc, size_t __refs = 0);
295132720Skan
29697403Sobrien    protected:
297132720Skan      virtual
29897403Sobrien      ~codecvt() { }
29997403Sobrien
30097403Sobrien      virtual result
301132720Skan      do_out(state_type& __state, const intern_type* __from,
30297403Sobrien	     const intern_type* __from_end, const intern_type*& __from_next,
30397403Sobrien	     extern_type* __to, extern_type* __to_end,
30497403Sobrien	     extern_type*& __to_next) const;
30597403Sobrien
30697403Sobrien      virtual result
307132720Skan      do_unshift(state_type& __state, extern_type* __to,
30897403Sobrien		 extern_type* __to_end, extern_type*& __to_next) const;
309132720Skan
31097403Sobrien      virtual result
311132720Skan      do_in(state_type& __state, const extern_type* __from,
312132720Skan	    const extern_type* __from_end, const extern_type*& __from_next,
313132720Skan	    intern_type* __to, intern_type* __to_end,
31497403Sobrien	    intern_type*& __to_next) const;
315132720Skan
316132720Skan      virtual int
31797403Sobrien      do_encoding() const throw();
31897403Sobrien
319132720Skan      virtual bool
32097403Sobrien      do_always_noconv() const throw();
32197403Sobrien
322132720Skan      virtual int
323132720Skan      do_length(state_type&, const extern_type* __from,
32497403Sobrien		const extern_type* __end, size_t __max) const;
32597403Sobrien
326132720Skan      virtual int
32797403Sobrien      do_max_length() const throw();
32897403Sobrien    };
32997403Sobrien
33097403Sobrien  template<typename _InternT, typename _ExternT, typename _StateT>
33197403Sobrien    locale::id codecvt<_InternT, _ExternT, _StateT>::id;
33297403Sobrien
333169691Skan  /// @brief class codecvt<char, char, mbstate_t> specialization.
33497403Sobrien  template<>
335132720Skan    class codecvt<char, char, mbstate_t>
33697403Sobrien    : public __codecvt_abstract_base<char, char, mbstate_t>
33797403Sobrien    {
338132720Skan    public:
33997403Sobrien      // Types:
340132720Skan      typedef char			intern_type;
341132720Skan      typedef char			extern_type;
342132720Skan      typedef mbstate_t			state_type;
34397403Sobrien
344132720Skan    protected:
345132720Skan      __c_locale			_M_c_locale_codecvt;
346132720Skan
347103447Skan    public:
34897403Sobrien      static locale::id id;
34997403Sobrien
350132720Skan      explicit
35197403Sobrien      codecvt(size_t __refs = 0);
35297403Sobrien
353132720Skan      explicit
354132720Skan      codecvt(__c_locale __cloc, size_t __refs = 0);
355132720Skan
35697403Sobrien    protected:
357132720Skan      virtual
35897403Sobrien      ~codecvt();
35997403Sobrien
36097403Sobrien      virtual result
361132720Skan      do_out(state_type& __state, const intern_type* __from,
36297403Sobrien	     const intern_type* __from_end, const intern_type*& __from_next,
36397403Sobrien	     extern_type* __to, extern_type* __to_end,
36497403Sobrien	     extern_type*& __to_next) const;
36597403Sobrien
36697403Sobrien      virtual result
367132720Skan      do_unshift(state_type& __state, extern_type* __to,
36897403Sobrien		 extern_type* __to_end, extern_type*& __to_next) const;
36997403Sobrien
37097403Sobrien      virtual result
371132720Skan      do_in(state_type& __state, const extern_type* __from,
37297403Sobrien	    const extern_type* __from_end, const extern_type*& __from_next,
373132720Skan	    intern_type* __to, intern_type* __to_end,
37497403Sobrien	    intern_type*& __to_next) const;
37597403Sobrien
376132720Skan      virtual int
37797403Sobrien      do_encoding() const throw();
37897403Sobrien
379132720Skan      virtual bool
38097403Sobrien      do_always_noconv() const throw();
38197403Sobrien
382132720Skan      virtual int
383132720Skan      do_length(state_type&, const extern_type* __from,
38497403Sobrien		const extern_type* __end, size_t __max) const;
38597403Sobrien
386132720Skan      virtual int
38797403Sobrien      do_max_length() const throw();
38897403Sobrien  };
38997403Sobrien
390132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
391169691Skan  /// @brief  class codecvt<wchar_t, char, mbstate_t> specialization.
39297403Sobrien  template<>
393132720Skan    class codecvt<wchar_t, char, mbstate_t>
39497403Sobrien    : public __codecvt_abstract_base<wchar_t, char, mbstate_t>
39597403Sobrien    {
39697403Sobrien    public:
39797403Sobrien      // Types:
398132720Skan      typedef wchar_t			intern_type;
399132720Skan      typedef char			extern_type;
400132720Skan      typedef mbstate_t			state_type;
40197403Sobrien
402132720Skan    protected:
403132720Skan      __c_locale			_M_c_locale_codecvt;
404132720Skan
405103447Skan    public:
406132720Skan      static locale::id			id;
40797403Sobrien
408132720Skan      explicit
40997403Sobrien      codecvt(size_t __refs = 0);
41097403Sobrien
411132720Skan      explicit
412132720Skan      codecvt(__c_locale __cloc, size_t __refs = 0);
413132720Skan
41497403Sobrien    protected:
415132720Skan      virtual
41697403Sobrien      ~codecvt();
41797403Sobrien
41897403Sobrien      virtual result
419132720Skan      do_out(state_type& __state, const intern_type* __from,
42097403Sobrien	     const intern_type* __from_end, const intern_type*& __from_next,
42197403Sobrien	     extern_type* __to, extern_type* __to_end,
42297403Sobrien	     extern_type*& __to_next) const;
42397403Sobrien
42497403Sobrien      virtual result
42597403Sobrien      do_unshift(state_type& __state,
42697403Sobrien		 extern_type* __to, extern_type* __to_end,
42797403Sobrien		 extern_type*& __to_next) const;
42897403Sobrien
42997403Sobrien      virtual result
43097403Sobrien      do_in(state_type& __state,
43197403Sobrien	     const extern_type* __from, const extern_type* __from_end,
43297403Sobrien	     const extern_type*& __from_next,
43397403Sobrien	     intern_type* __to, intern_type* __to_end,
43497403Sobrien	     intern_type*& __to_next) const;
43597403Sobrien
436132720Skan      virtual
43797403Sobrien      int do_encoding() const throw();
43897403Sobrien
439132720Skan      virtual
44097403Sobrien      bool do_always_noconv() const throw();
44197403Sobrien
442132720Skan      virtual
443132720Skan      int do_length(state_type&, const extern_type* __from,
44497403Sobrien		    const extern_type* __end, size_t __max) const;
44597403Sobrien
446132720Skan      virtual int
44797403Sobrien      do_max_length() const throw();
44897403Sobrien    };
449132720Skan#endif //_GLIBCXX_USE_WCHAR_T
45097403Sobrien
451169691Skan  /// @brief class codecvt_byname [22.2.1.6].
45297403Sobrien  template<typename _InternT, typename _ExternT, typename _StateT>
45397403Sobrien    class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT>
45497403Sobrien    {
45597403Sobrien    public:
456132720Skan      explicit
457132720Skan      codecvt_byname(const char* __s, size_t __refs = 0)
458132720Skan      : codecvt<_InternT, _ExternT, _StateT>(__refs)
459132720Skan      {
460132720Skan	if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
461132720Skan	  {
462132720Skan	    this->_S_destroy_c_locale(this->_M_c_locale_codecvt);
463132720Skan	    this->_S_create_c_locale(this->_M_c_locale_codecvt, __s);
464132720Skan	  }
465132720Skan      }
466103447Skan
46797403Sobrien    protected:
468132720Skan      virtual
46997403Sobrien      ~codecvt_byname() { }
47097403Sobrien    };
47197403Sobrien
472169691Skan_GLIBCXX_END_NAMESPACE
47397403Sobrien
474132720Skan#endif // _CODECVT_H
475