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