xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/ext/codecvt_specializations.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // Locale support (codecvt) -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2000-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj //
26*38fd1498Szrj // ISO C++ 14882: 22.2.1.5 Template class codecvt
27*38fd1498Szrj //
28*38fd1498Szrj 
29*38fd1498Szrj // Written by Benjamin Kosnik <bkoz@redhat.com>
30*38fd1498Szrj 
31*38fd1498Szrj /** @file ext/codecvt_specializations.h
32*38fd1498Szrj  *  This file is a GNU extension to the Standard C++ Library.
33*38fd1498Szrj  */
34*38fd1498Szrj 
35*38fd1498Szrj #ifndef _EXT_CODECVT_SPECIALIZATIONS_H
36*38fd1498Szrj #define _EXT_CODECVT_SPECIALIZATIONS_H 1
37*38fd1498Szrj 
38*38fd1498Szrj #include <bits/c++config.h>
39*38fd1498Szrj #include <locale>
40*38fd1498Szrj #include <iconv.h>
41*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)42*38fd1498Szrj namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
43*38fd1498Szrj {
44*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
45*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_CXX11
46*38fd1498Szrj 
47*38fd1498Szrj   /// Extension to use iconv for dealing with character encodings.
48*38fd1498Szrj   // This includes conversions and comparisons between various character
49*38fd1498Szrj   // sets.  This object encapsulates data that may need to be shared between
50*38fd1498Szrj   // char_traits, codecvt and ctype.
51*38fd1498Szrj   class encoding_state
52*38fd1498Szrj   {
53*38fd1498Szrj   public:
54*38fd1498Szrj     // Types:
55*38fd1498Szrj     // NB: A conversion descriptor subsumes and enhances the
56*38fd1498Szrj     // functionality of a simple state type such as mbstate_t.
57*38fd1498Szrj     typedef iconv_t	descriptor_type;
58*38fd1498Szrj 
59*38fd1498Szrj   protected:
60*38fd1498Szrj     // Name of internal character set encoding.
61*38fd1498Szrj     std::string	       	_M_int_enc;
62*38fd1498Szrj 
63*38fd1498Szrj     // Name of external character set encoding.
64*38fd1498Szrj     std::string  	_M_ext_enc;
65*38fd1498Szrj 
66*38fd1498Szrj     // Conversion descriptor between external encoding to internal encoding.
67*38fd1498Szrj     descriptor_type	_M_in_desc;
68*38fd1498Szrj 
69*38fd1498Szrj     // Conversion descriptor between internal encoding to external encoding.
70*38fd1498Szrj     descriptor_type	_M_out_desc;
71*38fd1498Szrj 
72*38fd1498Szrj     // The byte-order marker for the external encoding, if necessary.
73*38fd1498Szrj     int			_M_ext_bom;
74*38fd1498Szrj 
75*38fd1498Szrj     // The byte-order marker for the internal encoding, if necessary.
76*38fd1498Szrj     int			_M_int_bom;
77*38fd1498Szrj 
78*38fd1498Szrj     // Number of external bytes needed to construct one complete
79*38fd1498Szrj     // character in the internal encoding.
80*38fd1498Szrj     // NB: -1 indicates variable, or stateful, encodings.
81*38fd1498Szrj     int 		_M_bytes;
82*38fd1498Szrj 
83*38fd1498Szrj   public:
84*38fd1498Szrj     explicit
85*38fd1498Szrj     encoding_state()
86*38fd1498Szrj     : _M_in_desc(0), _M_out_desc(0), _M_ext_bom(0), _M_int_bom(0), _M_bytes(0)
87*38fd1498Szrj     { }
88*38fd1498Szrj 
89*38fd1498Szrj     explicit
90*38fd1498Szrj     encoding_state(const char* __int, const char* __ext,
91*38fd1498Szrj 		   int __ibom = 0, int __ebom = 0, int __bytes = 1)
92*38fd1498Szrj     : _M_int_enc(__int), _M_ext_enc(__ext), _M_in_desc(0), _M_out_desc(0),
93*38fd1498Szrj       _M_ext_bom(__ebom), _M_int_bom(__ibom), _M_bytes(__bytes)
94*38fd1498Szrj     { init(); }
95*38fd1498Szrj 
96*38fd1498Szrj     // 21.1.2 traits typedefs
97*38fd1498Szrj     // p4
98*38fd1498Szrj     // typedef STATE_T state_type
99*38fd1498Szrj     // requires: state_type shall meet the requirements of
100*38fd1498Szrj     // CopyConstructible types (20.1.3)
101*38fd1498Szrj     // NB: This does not preserve the actual state of the conversion
102*38fd1498Szrj     // descriptor member, but it does duplicate the encoding
103*38fd1498Szrj     // information.
104*38fd1498Szrj     encoding_state(const encoding_state& __obj) : _M_in_desc(0), _M_out_desc(0)
105*38fd1498Szrj     { construct(__obj); }
106*38fd1498Szrj 
107*38fd1498Szrj     // Need assignment operator as well.
108*38fd1498Szrj     encoding_state&
109*38fd1498Szrj     operator=(const encoding_state& __obj)
110*38fd1498Szrj     {
111*38fd1498Szrj       construct(__obj);
112*38fd1498Szrj       return *this;
113*38fd1498Szrj     }
114*38fd1498Szrj 
115*38fd1498Szrj     ~encoding_state()
116*38fd1498Szrj     { destroy(); }
117*38fd1498Szrj 
118*38fd1498Szrj     bool
119*38fd1498Szrj     good() const throw()
120*38fd1498Szrj     {
121*38fd1498Szrj       const descriptor_type __err = (iconv_t)(-1);
122*38fd1498Szrj       bool __test = _M_in_desc && _M_in_desc != __err;
123*38fd1498Szrj       __test &=  _M_out_desc && _M_out_desc != __err;
124*38fd1498Szrj       return __test;
125*38fd1498Szrj     }
126*38fd1498Szrj 
127*38fd1498Szrj     int
128*38fd1498Szrj     character_ratio() const
129*38fd1498Szrj     { return _M_bytes; }
130*38fd1498Szrj 
131*38fd1498Szrj     const std::string
132*38fd1498Szrj     internal_encoding() const
133*38fd1498Szrj     { return _M_int_enc; }
134*38fd1498Szrj 
135*38fd1498Szrj     int
136*38fd1498Szrj     internal_bom() const
137*38fd1498Szrj     { return _M_int_bom; }
138*38fd1498Szrj 
139*38fd1498Szrj     const std::string
140*38fd1498Szrj     external_encoding() const
141*38fd1498Szrj     { return _M_ext_enc; }
142*38fd1498Szrj 
143*38fd1498Szrj     int
144*38fd1498Szrj     external_bom() const
145*38fd1498Szrj     { return _M_ext_bom; }
146*38fd1498Szrj 
147*38fd1498Szrj     const descriptor_type&
148*38fd1498Szrj     in_descriptor() const
149*38fd1498Szrj     { return _M_in_desc; }
150*38fd1498Szrj 
151*38fd1498Szrj     const descriptor_type&
152*38fd1498Szrj     out_descriptor() const
153*38fd1498Szrj     { return _M_out_desc; }
154*38fd1498Szrj 
155*38fd1498Szrj   protected:
156*38fd1498Szrj     void
157*38fd1498Szrj     init()
158*38fd1498Szrj     {
159*38fd1498Szrj       const descriptor_type __err = (iconv_t)(-1);
160*38fd1498Szrj       const bool __have_encodings = _M_int_enc.size() && _M_ext_enc.size();
161*38fd1498Szrj       if (!_M_in_desc && __have_encodings)
162*38fd1498Szrj 	{
163*38fd1498Szrj 	  _M_in_desc = iconv_open(_M_int_enc.c_str(), _M_ext_enc.c_str());
164*38fd1498Szrj 	  if (_M_in_desc == __err)
165*38fd1498Szrj 	    std::__throw_runtime_error(__N("encoding_state::_M_init "
166*38fd1498Szrj 				    "creating iconv input descriptor failed"));
167*38fd1498Szrj 	}
168*38fd1498Szrj       if (!_M_out_desc && __have_encodings)
169*38fd1498Szrj 	{
170*38fd1498Szrj 	  _M_out_desc = iconv_open(_M_ext_enc.c_str(), _M_int_enc.c_str());
171*38fd1498Szrj 	  if (_M_out_desc == __err)
172*38fd1498Szrj 	    std::__throw_runtime_error(__N("encoding_state::_M_init "
173*38fd1498Szrj 				  "creating iconv output descriptor failed"));
174*38fd1498Szrj 	}
175*38fd1498Szrj     }
176*38fd1498Szrj 
177*38fd1498Szrj     void
178*38fd1498Szrj     construct(const encoding_state& __obj)
179*38fd1498Szrj     {
180*38fd1498Szrj       destroy();
181*38fd1498Szrj       _M_int_enc = __obj._M_int_enc;
182*38fd1498Szrj       _M_ext_enc = __obj._M_ext_enc;
183*38fd1498Szrj       _M_ext_bom = __obj._M_ext_bom;
184*38fd1498Szrj       _M_int_bom = __obj._M_int_bom;
185*38fd1498Szrj       _M_bytes = __obj._M_bytes;
186*38fd1498Szrj       init();
187*38fd1498Szrj     }
188*38fd1498Szrj 
189*38fd1498Szrj     void
190*38fd1498Szrj     destroy() throw()
191*38fd1498Szrj     {
192*38fd1498Szrj       const descriptor_type __err = (iconv_t)(-1);
193*38fd1498Szrj       if (_M_in_desc && _M_in_desc != __err)
194*38fd1498Szrj 	{
195*38fd1498Szrj 	  iconv_close(_M_in_desc);
196*38fd1498Szrj 	  _M_in_desc = 0;
197*38fd1498Szrj 	}
198*38fd1498Szrj       if (_M_out_desc && _M_out_desc != __err)
199*38fd1498Szrj 	{
200*38fd1498Szrj 	  iconv_close(_M_out_desc);
201*38fd1498Szrj 	  _M_out_desc = 0;
202*38fd1498Szrj 	}
203*38fd1498Szrj     }
204*38fd1498Szrj   };
205*38fd1498Szrj 
206*38fd1498Szrj   /// encoding_char_traits
207*38fd1498Szrj   // Custom traits type with encoding_state for the state type, and the
208*38fd1498Szrj   // associated fpos<encoding_state> for the position type, all other
209*38fd1498Szrj   // bits equivalent to the required char_traits instantiations.
210*38fd1498Szrj   template<typename _CharT>
211*38fd1498Szrj     struct encoding_char_traits
212*38fd1498Szrj     : public std::char_traits<_CharT>
213*38fd1498Szrj     {
214*38fd1498Szrj       typedef encoding_state				state_type;
215*38fd1498Szrj       typedef typename std::fpos<state_type>		pos_type;
216*38fd1498Szrj     };
217*38fd1498Szrj 
218*38fd1498Szrj _GLIBCXX_END_NAMESPACE_CXX11
219*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
220*38fd1498Szrj } // namespace
221*38fd1498Szrj 
222*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)223*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
224*38fd1498Szrj {
225*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
226*38fd1498Szrj 
227*38fd1498Szrj   using __gnu_cxx::encoding_state;
228*38fd1498Szrj 
229*38fd1498Szrj   /// codecvt<InternT, _ExternT, encoding_state> specialization.
230*38fd1498Szrj   // This partial specialization takes advantage of iconv to provide
231*38fd1498Szrj   // code conversions between a large number of character encodings.
232*38fd1498Szrj   template<typename _InternT, typename _ExternT>
233*38fd1498Szrj     class codecvt<_InternT, _ExternT, encoding_state>
234*38fd1498Szrj     : public __codecvt_abstract_base<_InternT, _ExternT, encoding_state>
235*38fd1498Szrj     {
236*38fd1498Szrj     public:
237*38fd1498Szrj       // Types:
238*38fd1498Szrj       typedef codecvt_base::result			result;
239*38fd1498Szrj       typedef _InternT 					intern_type;
240*38fd1498Szrj       typedef _ExternT 					extern_type;
241*38fd1498Szrj       typedef __gnu_cxx::encoding_state 		state_type;
242*38fd1498Szrj       typedef state_type::descriptor_type 		descriptor_type;
243*38fd1498Szrj 
244*38fd1498Szrj       // Data Members:
245*38fd1498Szrj       static locale::id 		id;
246*38fd1498Szrj 
247*38fd1498Szrj       explicit
248*38fd1498Szrj       codecvt(size_t __refs = 0)
249*38fd1498Szrj       : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
250*38fd1498Szrj       { }
251*38fd1498Szrj 
252*38fd1498Szrj       explicit
253*38fd1498Szrj       codecvt(state_type& __enc, size_t __refs = 0)
254*38fd1498Szrj       : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
255*38fd1498Szrj       { }
256*38fd1498Szrj 
257*38fd1498Szrj      protected:
258*38fd1498Szrj       virtual
259*38fd1498Szrj       ~codecvt() { }
260*38fd1498Szrj 
261*38fd1498Szrj       virtual result
262*38fd1498Szrj       do_out(state_type& __state, const intern_type* __from,
263*38fd1498Szrj 	     const intern_type* __from_end, const intern_type*& __from_next,
264*38fd1498Szrj 	     extern_type* __to, extern_type* __to_end,
265*38fd1498Szrj 	     extern_type*& __to_next) const;
266*38fd1498Szrj 
267*38fd1498Szrj       virtual result
268*38fd1498Szrj       do_unshift(state_type& __state, extern_type* __to,
269*38fd1498Szrj 		 extern_type* __to_end, extern_type*& __to_next) const;
270*38fd1498Szrj 
271*38fd1498Szrj       virtual result
272*38fd1498Szrj       do_in(state_type& __state, const extern_type* __from,
273*38fd1498Szrj 	    const extern_type* __from_end, const extern_type*& __from_next,
274*38fd1498Szrj 	    intern_type* __to, intern_type* __to_end,
275*38fd1498Szrj 	    intern_type*& __to_next) const;
276*38fd1498Szrj 
277*38fd1498Szrj       virtual int
278*38fd1498Szrj       do_encoding() const throw();
279*38fd1498Szrj 
280*38fd1498Szrj       virtual bool
281*38fd1498Szrj       do_always_noconv() const throw();
282*38fd1498Szrj 
283*38fd1498Szrj       virtual int
284*38fd1498Szrj       do_length(state_type&, const extern_type* __from,
285*38fd1498Szrj 		const extern_type* __end, size_t __max) const;
286*38fd1498Szrj 
287*38fd1498Szrj       virtual int
288*38fd1498Szrj       do_max_length() const throw();
289*38fd1498Szrj     };
290*38fd1498Szrj 
291*38fd1498Szrj   template<typename _InternT, typename _ExternT>
292*38fd1498Szrj     locale::id
293*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::id;
294*38fd1498Szrj 
295*38fd1498Szrj   // This adaptor works around the signature problems of the second
296*38fd1498Szrj   // argument to iconv():  SUSv2 and others use 'const char**', but glibc 2.2
297*38fd1498Szrj   // uses 'char**', which matches the POSIX 1003.1-2001 standard.
298*38fd1498Szrj   // Using this adaptor, g++ will do the work for us.
299*38fd1498Szrj   template<typename _Tp>
300*38fd1498Szrj     inline size_t
301*38fd1498Szrj     __iconv_adaptor(size_t(*__func)(iconv_t, _Tp, size_t*, char**, size_t*),
302*38fd1498Szrj                     iconv_t __cd, char** __inbuf, size_t* __inbytes,
303*38fd1498Szrj                     char** __outbuf, size_t* __outbytes)
304*38fd1498Szrj     { return __func(__cd, (_Tp)__inbuf, __inbytes, __outbuf, __outbytes); }
305*38fd1498Szrj 
306*38fd1498Szrj   template<typename _InternT, typename _ExternT>
307*38fd1498Szrj     codecvt_base::result
308*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
309*38fd1498Szrj     do_out(state_type& __state, const intern_type* __from,
310*38fd1498Szrj 	   const intern_type* __from_end, const intern_type*& __from_next,
311*38fd1498Szrj 	   extern_type* __to, extern_type* __to_end,
312*38fd1498Szrj 	   extern_type*& __to_next) const
313*38fd1498Szrj     {
314*38fd1498Szrj       result __ret = codecvt_base::error;
315*38fd1498Szrj       if (__state.good())
316*38fd1498Szrj 	{
317*38fd1498Szrj 	  const descriptor_type& __desc = __state.out_descriptor();
318*38fd1498Szrj 	  const size_t __fmultiple = sizeof(intern_type);
319*38fd1498Szrj 	  size_t __fbytes = __fmultiple * (__from_end - __from);
320*38fd1498Szrj 	  const size_t __tmultiple = sizeof(extern_type);
321*38fd1498Szrj 	  size_t __tbytes = __tmultiple * (__to_end - __to);
322*38fd1498Szrj 
323*38fd1498Szrj 	  // Argument list for iconv specifies a byte sequence. Thus,
324*38fd1498Szrj 	  // all to/from arrays must be brutally casted to char*.
325*38fd1498Szrj 	  char* __cto = reinterpret_cast<char*>(__to);
326*38fd1498Szrj 	  char* __cfrom;
327*38fd1498Szrj 	  size_t __conv;
328*38fd1498Szrj 
329*38fd1498Szrj 	  // Some encodings need a byte order marker as the first item
330*38fd1498Szrj 	  // in the byte stream, to designate endian-ness. The default
331*38fd1498Szrj 	  // value for the byte order marker is NULL, so if this is
332*38fd1498Szrj 	  // the case, it's not necessary and we can just go on our
333*38fd1498Szrj 	  // merry way.
334*38fd1498Szrj 	  int __int_bom = __state.internal_bom();
335*38fd1498Szrj 	  if (__int_bom)
336*38fd1498Szrj 	    {
337*38fd1498Szrj 	      size_t __size = __from_end - __from;
338*38fd1498Szrj 	      intern_type* __cfixed = static_cast<intern_type*>
339*38fd1498Szrj 		(__builtin_alloca(sizeof(intern_type) * (__size + 1)));
340*38fd1498Szrj 	      __cfixed[0] = static_cast<intern_type>(__int_bom);
341*38fd1498Szrj 	      char_traits<intern_type>::copy(__cfixed + 1, __from, __size);
342*38fd1498Szrj 	      __cfrom = reinterpret_cast<char*>(__cfixed);
343*38fd1498Szrj 	      __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
344*38fd1498Szrj                                         &__fbytes, &__cto, &__tbytes);
345*38fd1498Szrj 	    }
346*38fd1498Szrj 	  else
347*38fd1498Szrj 	    {
348*38fd1498Szrj 	      intern_type* __cfixed = const_cast<intern_type*>(__from);
349*38fd1498Szrj 	      __cfrom = reinterpret_cast<char*>(__cfixed);
350*38fd1498Szrj 	      __conv = __iconv_adaptor(iconv, __desc, &__cfrom, &__fbytes,
351*38fd1498Szrj 				       &__cto, &__tbytes);
352*38fd1498Szrj 	    }
353*38fd1498Szrj 
354*38fd1498Szrj 	  if (__conv != size_t(-1))
355*38fd1498Szrj 	    {
356*38fd1498Szrj 	      __from_next = reinterpret_cast<const intern_type*>(__cfrom);
357*38fd1498Szrj 	      __to_next = reinterpret_cast<extern_type*>(__cto);
358*38fd1498Szrj 	      __ret = codecvt_base::ok;
359*38fd1498Szrj 	    }
360*38fd1498Szrj 	  else
361*38fd1498Szrj 	    {
362*38fd1498Szrj 	      if (__fbytes < __fmultiple * (__from_end - __from))
363*38fd1498Szrj 		{
364*38fd1498Szrj 		  __from_next = reinterpret_cast<const intern_type*>(__cfrom);
365*38fd1498Szrj 		  __to_next = reinterpret_cast<extern_type*>(__cto);
366*38fd1498Szrj 		  __ret = codecvt_base::partial;
367*38fd1498Szrj 		}
368*38fd1498Szrj 	      else
369*38fd1498Szrj 		__ret = codecvt_base::error;
370*38fd1498Szrj 	    }
371*38fd1498Szrj 	}
372*38fd1498Szrj       return __ret;
373*38fd1498Szrj     }
374*38fd1498Szrj 
375*38fd1498Szrj   template<typename _InternT, typename _ExternT>
376*38fd1498Szrj     codecvt_base::result
377*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
378*38fd1498Szrj     do_unshift(state_type& __state, extern_type* __to,
379*38fd1498Szrj 	       extern_type* __to_end, extern_type*& __to_next) const
380*38fd1498Szrj     {
381*38fd1498Szrj       result __ret = codecvt_base::error;
382*38fd1498Szrj       if (__state.good())
383*38fd1498Szrj 	{
384*38fd1498Szrj 	  const descriptor_type& __desc = __state.in_descriptor();
385*38fd1498Szrj 	  const size_t __tmultiple = sizeof(intern_type);
386*38fd1498Szrj 	  size_t __tlen = __tmultiple * (__to_end - __to);
387*38fd1498Szrj 
388*38fd1498Szrj 	  // Argument list for iconv specifies a byte sequence. Thus,
389*38fd1498Szrj 	  // all to/from arrays must be brutally casted to char*.
390*38fd1498Szrj 	  char* __cto = reinterpret_cast<char*>(__to);
391*38fd1498Szrj 	  size_t __conv = __iconv_adaptor(iconv,__desc, 0, 0,
392*38fd1498Szrj                                           &__cto, &__tlen);
393*38fd1498Szrj 
394*38fd1498Szrj 	  if (__conv != size_t(-1))
395*38fd1498Szrj 	    {
396*38fd1498Szrj 	      __to_next = reinterpret_cast<extern_type*>(__cto);
397*38fd1498Szrj 	      if (__tlen == __tmultiple * (__to_end - __to))
398*38fd1498Szrj 		__ret = codecvt_base::noconv;
399*38fd1498Szrj 	      else if (__tlen == 0)
400*38fd1498Szrj 		__ret = codecvt_base::ok;
401*38fd1498Szrj 	      else
402*38fd1498Szrj 		__ret = codecvt_base::partial;
403*38fd1498Szrj 	    }
404*38fd1498Szrj 	  else
405*38fd1498Szrj 	    __ret = codecvt_base::error;
406*38fd1498Szrj 	}
407*38fd1498Szrj       return __ret;
408*38fd1498Szrj     }
409*38fd1498Szrj 
410*38fd1498Szrj   template<typename _InternT, typename _ExternT>
411*38fd1498Szrj     codecvt_base::result
412*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
413*38fd1498Szrj     do_in(state_type& __state, const extern_type* __from,
414*38fd1498Szrj 	  const extern_type* __from_end, const extern_type*& __from_next,
415*38fd1498Szrj 	  intern_type* __to, intern_type* __to_end,
416*38fd1498Szrj 	  intern_type*& __to_next) const
417*38fd1498Szrj     {
418*38fd1498Szrj       result __ret = codecvt_base::error;
419*38fd1498Szrj       if (__state.good())
420*38fd1498Szrj 	{
421*38fd1498Szrj 	  const descriptor_type& __desc = __state.in_descriptor();
422*38fd1498Szrj 	  const size_t __fmultiple = sizeof(extern_type);
423*38fd1498Szrj 	  size_t __flen = __fmultiple * (__from_end - __from);
424*38fd1498Szrj 	  const size_t __tmultiple = sizeof(intern_type);
425*38fd1498Szrj 	  size_t __tlen = __tmultiple * (__to_end - __to);
426*38fd1498Szrj 
427*38fd1498Szrj 	  // Argument list for iconv specifies a byte sequence. Thus,
428*38fd1498Szrj 	  // all to/from arrays must be brutally casted to char*.
429*38fd1498Szrj 	  char* __cto = reinterpret_cast<char*>(__to);
430*38fd1498Szrj 	  char* __cfrom;
431*38fd1498Szrj 	  size_t __conv;
432*38fd1498Szrj 
433*38fd1498Szrj 	  // Some encodings need a byte order marker as the first item
434*38fd1498Szrj 	  // in the byte stream, to designate endian-ness. The default
435*38fd1498Szrj 	  // value for the byte order marker is NULL, so if this is
436*38fd1498Szrj 	  // the case, it's not necessary and we can just go on our
437*38fd1498Szrj 	  // merry way.
438*38fd1498Szrj 	  int __ext_bom = __state.external_bom();
439*38fd1498Szrj 	  if (__ext_bom)
440*38fd1498Szrj 	    {
441*38fd1498Szrj 	      size_t __size = __from_end - __from;
442*38fd1498Szrj 	      extern_type* __cfixed =  static_cast<extern_type*>
443*38fd1498Szrj 		(__builtin_alloca(sizeof(extern_type) * (__size + 1)));
444*38fd1498Szrj 	      __cfixed[0] = static_cast<extern_type>(__ext_bom);
445*38fd1498Szrj 	      char_traits<extern_type>::copy(__cfixed + 1, __from, __size);
446*38fd1498Szrj 	      __cfrom = reinterpret_cast<char*>(__cfixed);
447*38fd1498Szrj 	      __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
448*38fd1498Szrj                                        &__flen, &__cto, &__tlen);
449*38fd1498Szrj 	    }
450*38fd1498Szrj 	  else
451*38fd1498Szrj 	    {
452*38fd1498Szrj 	      extern_type* __cfixed = const_cast<extern_type*>(__from);
453*38fd1498Szrj 	      __cfrom = reinterpret_cast<char*>(__cfixed);
454*38fd1498Szrj 	      __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
455*38fd1498Szrj                                        &__flen, &__cto, &__tlen);
456*38fd1498Szrj 	    }
457*38fd1498Szrj 
458*38fd1498Szrj 
459*38fd1498Szrj 	  if (__conv != size_t(-1))
460*38fd1498Szrj 	    {
461*38fd1498Szrj 	      __from_next = reinterpret_cast<const extern_type*>(__cfrom);
462*38fd1498Szrj 	      __to_next = reinterpret_cast<intern_type*>(__cto);
463*38fd1498Szrj 	      __ret = codecvt_base::ok;
464*38fd1498Szrj 	    }
465*38fd1498Szrj 	  else
466*38fd1498Szrj 	    {
467*38fd1498Szrj 	      if (__flen < static_cast<size_t>(__from_end - __from))
468*38fd1498Szrj 		{
469*38fd1498Szrj 		  __from_next = reinterpret_cast<const extern_type*>(__cfrom);
470*38fd1498Szrj 		  __to_next = reinterpret_cast<intern_type*>(__cto);
471*38fd1498Szrj 		  __ret = codecvt_base::partial;
472*38fd1498Szrj 		}
473*38fd1498Szrj 	      else
474*38fd1498Szrj 		__ret = codecvt_base::error;
475*38fd1498Szrj 	    }
476*38fd1498Szrj 	}
477*38fd1498Szrj       return __ret;
478*38fd1498Szrj     }
479*38fd1498Szrj 
480*38fd1498Szrj   template<typename _InternT, typename _ExternT>
481*38fd1498Szrj     int
482*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
483*38fd1498Szrj     do_encoding() const throw()
484*38fd1498Szrj     {
485*38fd1498Szrj       int __ret = 0;
486*38fd1498Szrj       if (sizeof(_ExternT) <= sizeof(_InternT))
487*38fd1498Szrj 	__ret = sizeof(_InternT) / sizeof(_ExternT);
488*38fd1498Szrj       return __ret;
489*38fd1498Szrj     }
490*38fd1498Szrj 
491*38fd1498Szrj   template<typename _InternT, typename _ExternT>
492*38fd1498Szrj     bool
493*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
494*38fd1498Szrj     do_always_noconv() const throw()
495*38fd1498Szrj     { return false; }
496*38fd1498Szrj 
497*38fd1498Szrj   template<typename _InternT, typename _ExternT>
498*38fd1498Szrj     int
499*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
500*38fd1498Szrj     do_length(state_type&, const extern_type* __from,
501*38fd1498Szrj 	      const extern_type* __end, size_t __max) const
502*38fd1498Szrj     { return std::min(__max, static_cast<size_t>(__end - __from)); }
503*38fd1498Szrj 
504*38fd1498Szrj   // _GLIBCXX_RESOLVE_LIB_DEFECTS
505*38fd1498Szrj   // 74.  Garbled text for codecvt::do_max_length
506*38fd1498Szrj   template<typename _InternT, typename _ExternT>
507*38fd1498Szrj     int
508*38fd1498Szrj     codecvt<_InternT, _ExternT, encoding_state>::
509*38fd1498Szrj     do_max_length() const throw()
510*38fd1498Szrj     { return 1; }
511*38fd1498Szrj 
512*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
513*38fd1498Szrj } // namespace
514*38fd1498Szrj 
515*38fd1498Szrj #endif
516