aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h')
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h507
1 files changed, 507 insertions, 0 deletions
diff --git a/gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h b/gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h
new file mode 100644
index 000000000..89adb3f20
--- /dev/null
+++ b/gcc-4.4.3/libstdc++-v3/include/ext/codecvt_specializations.h
@@ -0,0 +1,507 @@
+// Locale support (codecvt) -*- C++ -*-
+
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.2.1.5 Template class codecvt
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.com>
+
+/** @file ext/codecvt_specializations.h
+ * This file is a GNU extension to the Standard C++ Library.
+ */
+
+#ifndef _EXT_CODECVT_SPECIALIZATIONS_H
+#define _EXT_CODECVT_SPECIALIZATIONS_H 1
+
+#include <bits/c++config.h>
+#include <locale>
+#include <iconv.h>
+
+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+
+ /// Extension to use iconv for dealing with character encodings.
+ // This includes conversions and comparisons between various character
+ // sets. This object encapsulates data that may need to be shared between
+ // char_traits, codecvt and ctype.
+ class encoding_state
+ {
+ public:
+ // Types:
+ // NB: A conversion descriptor subsumes and enhances the
+ // functionality of a simple state type such as mbstate_t.
+ typedef iconv_t descriptor_type;
+
+ protected:
+ // Name of internal character set encoding.
+ std::string _M_int_enc;
+
+ // Name of external character set encoding.
+ std::string _M_ext_enc;
+
+ // Conversion descriptor between external encoding to internal encoding.
+ descriptor_type _M_in_desc;
+
+ // Conversion descriptor between internal encoding to external encoding.
+ descriptor_type _M_out_desc;
+
+ // The byte-order marker for the external encoding, if necessary.
+ int _M_ext_bom;
+
+ // The byte-order marker for the internal encoding, if necessary.
+ int _M_int_bom;
+
+ // Number of external bytes needed to construct one complete
+ // character in the internal encoding.
+ // NB: -1 indicates variable, or stateful, encodings.
+ int _M_bytes;
+
+ public:
+ explicit
+ encoding_state()
+ : _M_in_desc(0), _M_out_desc(0), _M_ext_bom(0), _M_int_bom(0), _M_bytes(0)
+ { }
+
+ explicit
+ encoding_state(const char* __int, const char* __ext,
+ int __ibom = 0, int __ebom = 0, int __bytes = 1)
+ : _M_int_enc(__int), _M_ext_enc(__ext), _M_in_desc(0), _M_out_desc(0),
+ _M_ext_bom(__ebom), _M_int_bom(__ibom), _M_bytes(__bytes)
+ { init(); }
+
+ // 21.1.2 traits typedefs
+ // p4
+ // typedef STATE_T state_type
+ // requires: state_type shall meet the requirements of
+ // CopyConstructible types (20.1.3)
+ // NB: This does not preserve the actual state of the conversion
+ // descriptor member, but it does duplicate the encoding
+ // information.
+ encoding_state(const encoding_state& __obj) : _M_in_desc(0), _M_out_desc(0)
+ { construct(__obj); }
+
+ // Need assignment operator as well.
+ encoding_state&
+ operator=(const encoding_state& __obj)
+ {
+ construct(__obj);
+ return *this;
+ }
+
+ ~encoding_state()
+ { destroy(); }
+
+ bool
+ good() const throw()
+ {
+ const descriptor_type __err = (iconv_t)(-1);
+ bool __test = _M_in_desc && _M_in_desc != __err;
+ __test &= _M_out_desc && _M_out_desc != __err;
+ return __test;
+ }
+
+ int
+ character_ratio() const
+ { return _M_bytes; }
+
+ const std::string
+ internal_encoding() const
+ { return _M_int_enc; }
+
+ int
+ internal_bom() const
+ { return _M_int_bom; }
+
+ const std::string
+ external_encoding() const
+ { return _M_ext_enc; }
+
+ int
+ external_bom() const
+ { return _M_ext_bom; }
+
+ const descriptor_type&
+ in_descriptor() const
+ { return _M_in_desc; }
+
+ const descriptor_type&
+ out_descriptor() const
+ { return _M_out_desc; }
+
+ protected:
+ void
+ init()
+ {
+ const descriptor_type __err = (iconv_t)(-1);
+ const bool __have_encodings = _M_int_enc.size() && _M_ext_enc.size();
+ if (!_M_in_desc && __have_encodings)
+ {
+ _M_in_desc = iconv_open(_M_int_enc.c_str(), _M_ext_enc.c_str());
+ if (_M_in_desc == __err)
+ std::__throw_runtime_error(__N("encoding_state::_M_init "
+ "creating iconv input descriptor failed"));
+ }
+ if (!_M_out_desc && __have_encodings)
+ {
+ _M_out_desc = iconv_open(_M_ext_enc.c_str(), _M_int_enc.c_str());
+ if (_M_out_desc == __err)
+ std::__throw_runtime_error(__N("encoding_state::_M_init "
+ "creating iconv output descriptor failed"));
+ }
+ }
+
+ void
+ construct(const encoding_state& __obj)
+ {
+ destroy();
+ _M_int_enc = __obj._M_int_enc;
+ _M_ext_enc = __obj._M_ext_enc;
+ _M_ext_bom = __obj._M_ext_bom;
+ _M_int_bom = __obj._M_int_bom;
+ _M_bytes = __obj._M_bytes;
+ init();
+ }
+
+ void
+ destroy() throw()
+ {
+ const descriptor_type __err = (iconv_t)(-1);
+ if (_M_in_desc && _M_in_desc != __err)
+ {
+ iconv_close(_M_in_desc);
+ _M_in_desc = 0;
+ }
+ if (_M_out_desc && _M_out_desc != __err)
+ {
+ iconv_close(_M_out_desc);
+ _M_out_desc = 0;
+ }
+ }
+ };
+
+ /// encoding_char_traits
+ // Custom traits type with encoding_state for the state type, and the
+ // associated fpos<encoding_state> for the position type, all other
+ // bits equivalent to the required char_traits instantiations.
+ template<typename _CharT>
+ struct encoding_char_traits : public std::char_traits<_CharT>
+ {
+ typedef encoding_state state_type;
+ typedef typename std::fpos<state_type> pos_type;
+ };
+
+_GLIBCXX_END_NAMESPACE
+
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+ using __gnu_cxx::encoding_state;
+
+ /// codecvt<InternT, _ExternT, encoding_state> specialization.
+ // This partial specialization takes advantage of iconv to provide
+ // code conversions between a large number of character encodings.
+ template<typename _InternT, typename _ExternT>
+ class codecvt<_InternT, _ExternT, encoding_state>
+ : public __codecvt_abstract_base<_InternT, _ExternT, encoding_state>
+ {
+ public:
+ // Types:
+ typedef codecvt_base::result result;
+ typedef _InternT intern_type;
+ typedef _ExternT extern_type;
+ typedef __gnu_cxx::encoding_state state_type;
+ typedef state_type::descriptor_type descriptor_type;
+
+ // Data Members:
+ static locale::id id;
+
+ explicit
+ codecvt(size_t __refs = 0)
+ : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
+ { }
+
+ explicit
+ codecvt(state_type& __enc, size_t __refs = 0)
+ : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
+ { }
+
+ protected:
+ virtual
+ ~codecvt() { }
+
+ virtual result
+ do_out(state_type& __state, const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_unshift(state_type& __state, extern_type* __to,
+ extern_type* __to_end, extern_type*& __to_next) const;
+
+ virtual result
+ do_in(state_type& __state, const extern_type* __from,
+ const extern_type* __from_end, const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const;
+
+ virtual int
+ do_encoding() const throw();
+
+ virtual bool
+ do_always_noconv() const throw();
+
+ virtual int
+ do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const;
+
+ virtual int
+ do_max_length() const throw();
+ };
+
+ template<typename _InternT, typename _ExternT>
+ locale::id
+ codecvt<_InternT, _ExternT, encoding_state>::id;
+
+ // This adaptor works around the signature problems of the second
+ // argument to iconv(): SUSv2 and others use 'const char**', but glibc 2.2
+ // uses 'char**', which matches the POSIX 1003.1-2001 standard.
+ // Using this adaptor, g++ will do the work for us.
+ template<typename _Tp>
+ inline size_t
+ __iconv_adaptor(size_t(*__func)(iconv_t, _Tp, size_t*, char**, size_t*),
+ iconv_t __cd, char** __inbuf, size_t* __inbytes,
+ char** __outbuf, size_t* __outbytes)
+ { return __func(__cd, (_Tp)__inbuf, __inbytes, __outbuf, __outbytes); }
+
+ template<typename _InternT, typename _ExternT>
+ codecvt_base::result
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_out(state_type& __state, const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const
+ {
+ result __ret = codecvt_base::error;
+ if (__state.good())
+ {
+ const descriptor_type& __desc = __state.out_descriptor();
+ const size_t __fmultiple = sizeof(intern_type);
+ size_t __fbytes = __fmultiple * (__from_end - __from);
+ const size_t __tmultiple = sizeof(extern_type);
+ size_t __tbytes = __tmultiple * (__to_end - __to);
+
+ // Argument list for iconv specifies a byte sequence. Thus,
+ // all to/from arrays must be brutally casted to char*.
+ char* __cto = reinterpret_cast<char*>(__to);
+ char* __cfrom;
+ size_t __conv;
+
+ // Some encodings need a byte order marker as the first item
+ // in the byte stream, to designate endian-ness. The default
+ // value for the byte order marker is NULL, so if this is
+ // the case, it's not necessary and we can just go on our
+ // merry way.
+ int __int_bom = __state.internal_bom();
+ if (__int_bom)
+ {
+ size_t __size = __from_end - __from;
+ intern_type* __cfixed = static_cast<intern_type*>
+ (__builtin_alloca(sizeof(intern_type) * (__size + 1)));
+ __cfixed[0] = static_cast<intern_type>(__int_bom);
+ char_traits<intern_type>::copy(__cfixed + 1, __from, __size);
+ __cfrom = reinterpret_cast<char*>(__cfixed);
+ __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
+ &__fbytes, &__cto, &__tbytes);
+ }
+ else
+ {
+ intern_type* __cfixed = const_cast<intern_type*>(__from);
+ __cfrom = reinterpret_cast<char*>(__cfixed);
+ __conv = __iconv_adaptor(iconv, __desc, &__cfrom, &__fbytes,
+ &__cto, &__tbytes);
+ }
+
+ if (__conv != size_t(-1))
+ {
+ __from_next = reinterpret_cast<const intern_type*>(__cfrom);
+ __to_next = reinterpret_cast<extern_type*>(__cto);
+ __ret = codecvt_base::ok;
+ }
+ else
+ {
+ if (__fbytes < __fmultiple * (__from_end - __from))
+ {
+ __from_next = reinterpret_cast<const intern_type*>(__cfrom);
+ __to_next = reinterpret_cast<extern_type*>(__cto);
+ __ret = codecvt_base::partial;
+ }
+ else
+ __ret = codecvt_base::error;
+ }
+ }
+ return __ret;
+ }
+
+ template<typename _InternT, typename _ExternT>
+ codecvt_base::result
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_unshift(state_type& __state, extern_type* __to,
+ extern_type* __to_end, extern_type*& __to_next) const
+ {
+ result __ret = codecvt_base::error;
+ if (__state.good())
+ {
+ const descriptor_type& __desc = __state.in_descriptor();
+ const size_t __tmultiple = sizeof(intern_type);
+ size_t __tlen = __tmultiple * (__to_end - __to);
+
+ // Argument list for iconv specifies a byte sequence. Thus,
+ // all to/from arrays must be brutally casted to char*.
+ char* __cto = reinterpret_cast<char*>(__to);
+ size_t __conv = __iconv_adaptor(iconv,__desc, NULL, NULL,
+ &__cto, &__tlen);
+
+ if (__conv != size_t(-1))
+ {
+ __to_next = reinterpret_cast<extern_type*>(__cto);
+ if (__tlen == __tmultiple * (__to_end - __to))
+ __ret = codecvt_base::noconv;
+ else if (__tlen == 0)
+ __ret = codecvt_base::ok;
+ else
+ __ret = codecvt_base::partial;
+ }
+ else
+ __ret = codecvt_base::error;
+ }
+ return __ret;
+ }
+
+ template<typename _InternT, typename _ExternT>
+ codecvt_base::result
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_in(state_type& __state, const extern_type* __from,
+ const extern_type* __from_end, const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const
+ {
+ result __ret = codecvt_base::error;
+ if (__state.good())
+ {
+ const descriptor_type& __desc = __state.in_descriptor();
+ const size_t __fmultiple = sizeof(extern_type);
+ size_t __flen = __fmultiple * (__from_end - __from);
+ const size_t __tmultiple = sizeof(intern_type);
+ size_t __tlen = __tmultiple * (__to_end - __to);
+
+ // Argument list for iconv specifies a byte sequence. Thus,
+ // all to/from arrays must be brutally casted to char*.
+ char* __cto = reinterpret_cast<char*>(__to);
+ char* __cfrom;
+ size_t __conv;
+
+ // Some encodings need a byte order marker as the first item
+ // in the byte stream, to designate endian-ness. The default
+ // value for the byte order marker is NULL, so if this is
+ // the case, it's not necessary and we can just go on our
+ // merry way.
+ int __ext_bom = __state.external_bom();
+ if (__ext_bom)
+ {
+ size_t __size = __from_end - __from;
+ extern_type* __cfixed = static_cast<extern_type*>
+ (__builtin_alloca(sizeof(extern_type) * (__size + 1)));
+ __cfixed[0] = static_cast<extern_type>(__ext_bom);
+ char_traits<extern_type>::copy(__cfixed + 1, __from, __size);
+ __cfrom = reinterpret_cast<char*>(__cfixed);
+ __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
+ &__flen, &__cto, &__tlen);
+ }
+ else
+ {
+ extern_type* __cfixed = const_cast<extern_type*>(__from);
+ __cfrom = reinterpret_cast<char*>(__cfixed);
+ __conv = __iconv_adaptor(iconv, __desc, &__cfrom,
+ &__flen, &__cto, &__tlen);
+ }
+
+
+ if (__conv != size_t(-1))
+ {
+ __from_next = reinterpret_cast<const extern_type*>(__cfrom);
+ __to_next = reinterpret_cast<intern_type*>(__cto);
+ __ret = codecvt_base::ok;
+ }
+ else
+ {
+ if (__flen < static_cast<size_t>(__from_end - __from))
+ {
+ __from_next = reinterpret_cast<const extern_type*>(__cfrom);
+ __to_next = reinterpret_cast<intern_type*>(__cto);
+ __ret = codecvt_base::partial;
+ }
+ else
+ __ret = codecvt_base::error;
+ }
+ }
+ return __ret;
+ }
+
+ template<typename _InternT, typename _ExternT>
+ int
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_encoding() const throw()
+ {
+ int __ret = 0;
+ if (sizeof(_ExternT) <= sizeof(_InternT))
+ __ret = sizeof(_InternT) / sizeof(_ExternT);
+ return __ret;
+ }
+
+ template<typename _InternT, typename _ExternT>
+ bool
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_always_noconv() const throw()
+ { return false; }
+
+ template<typename _InternT, typename _ExternT>
+ int
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const
+ { return std::min(__max, static_cast<size_t>(__end - __from)); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 74. Garbled text for codecvt::do_max_length
+ template<typename _InternT, typename _ExternT>
+ int
+ codecvt<_InternT, _ExternT, encoding_state>::
+ do_max_length() const throw()
+ { return 1; }
+
+_GLIBCXX_END_NAMESPACE
+
+#endif