]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - libstdc++-v3/include/ext/codecvt_specializations.h
Imported gcc-4.4.3
[msp430-gcc.git] / libstdc++-v3 / include / ext / codecvt_specializations.h
diff --git a/libstdc++-v3/include/ext/codecvt_specializations.h b/libstdc++-v3/include/ext/codecvt_specializations.h
new file mode 100644 (file)
index 0000000..89adb3f
--- /dev/null
@@ -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