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