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