]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - libstdc++-v3/testsuite/util/testsuite_character.h
Imported gcc-4.4.3
[msp430-gcc.git] / libstdc++-v3 / testsuite / util / testsuite_character.h
diff --git a/libstdc++-v3/testsuite/util/testsuite_character.h b/libstdc++-v3/testsuite/util/testsuite_character.h
new file mode 100644 (file)
index 0000000..35ccfa8
--- /dev/null
@@ -0,0 +1,568 @@
+// -*- C++ -*-
+
+// Testing character type and state type with char_traits and codecvt
+// specializations for the C++ library testsuite.
+//
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 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.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
+#define _GLIBCXX_TESTSUITE_CHARACTER_H
+
+#include <climits>
+#include <string> // for char_traits
+#include <locale> // for codecvt
+#include <algorithm> // for transform
+#include <ext/pod_char_traits.h>
+
+namespace __gnu_test
+{  
+  struct pod_int
+  {
+    int value;
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+    // For std::iota.
+    pod_int&
+    operator++()
+    {
+      ++value;
+      return *this;
+    }
+#endif
+  };
+
+  // For 20.1 requirements for instantiable type: equality comparable
+  // and less than comparable.
+  inline bool
+  operator==(const pod_int& lhs, const pod_int& rhs)
+  { return lhs.value == rhs.value; }
+  
+  inline bool
+  operator<(const pod_int& lhs, const pod_int& rhs)
+  { return lhs.value < rhs.value; }
+
+  // For 26 numeric algorithms requirements, need addable,
+  // subtractable, multiplicable.
+  inline pod_int
+  operator+(const pod_int& lhs, const pod_int& rhs)
+  {
+    pod_int ret = { lhs.value + rhs.value };
+    return ret;
+  }
+
+  inline pod_int
+  operator-(const pod_int& lhs, const pod_int& rhs)
+  { 
+    pod_int ret = { lhs.value - rhs.value };
+    return ret;
+  }
+
+  inline pod_int
+  operator*(const pod_int& lhs, const pod_int& rhs)
+  { 
+    pod_int ret = { lhs.value * rhs.value };
+    return ret;
+  }
+
+  struct pod_state
+  {
+    unsigned long value;
+  };
+
+  inline bool
+  operator==(const pod_state& lhs, const pod_state& rhs)
+  { return lhs.value == rhs.value; }
+
+  inline bool
+  operator<(const pod_state& lhs, const pod_state& rhs)
+  { return lhs.value < rhs.value; }
+
+  // Alternate character types.
+  using __gnu_cxx::character;
+  typedef character<unsigned char, pod_int, pod_state>         pod_char;
+  typedef character<unsigned char, unsigned int, pod_state>    pod_uchar;
+  typedef character<unsigned short, unsigned int>              pod_ushort;
+  typedef character<unsigned int, unsigned long>               pod_uint;  
+}
+
+namespace __gnu_cxx 
+{
+  // Specializations.
+  // pod_char
+  template<>
+    template<typename V2>
+      inline __gnu_test::pod_char::char_type
+      __gnu_test::pod_char::char_type::from(const V2& v)
+      {
+       char_type ret = { static_cast<value_type>(v.value) };
+       return ret;
+      }
+
+  template<>
+    template<typename V2>
+      inline V2
+      __gnu_test::pod_char::char_type::to(const char_type& c)
+      {
+       V2 ret = { c.value };
+       return ret;
+      }
+  
+  template<>
+    template<typename V2>
+      inline __gnu_test::pod_uchar::char_type
+      __gnu_test::pod_uchar::char_type::from(const V2& v)
+      {
+       char_type ret;
+       ret.value = (v >> 5);
+       return ret;
+      }
+
+  template<>
+    template<typename V2>
+      inline V2
+      __gnu_test::pod_uchar::char_type::to(const char_type& c)
+      { return static_cast<V2>(c.value << 5); }
+} // namespace __gnu_test
+
+namespace std
+{
+  // codecvt specialization
+  //
+  // The conversion performed by the specialization is not supposed to
+  // be useful, rather it has been designed to demonstrate the
+  // essential features of stateful conversions:
+  // * Number and value of bytes for each internal character depends on the
+  //   state in addition to the character itself.
+  // * Unshift produces an unshift sequence and resets the state. On input
+  //   the unshift sequence causes the state to be reset.
+  //
+  // The conversion for output is as follows:
+  // 1. Calculate the value tmp by xor-ing the state and the internal
+  //    character
+  // 2. Split tmp into either two or three bytes depending on the value of
+  //    state. Output those bytes.
+  // 3. tmp becomes the new value of state.
+  template<>
+    class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
+    : public __codecvt_abstract_base<__gnu_test::pod_uchar, char, 
+                                    __gnu_test::pod_state>
+    {
+    public:
+      typedef codecvt_base::result     result;
+      typedef __gnu_test::pod_uchar    intern_type;
+      typedef char                     extern_type;
+      typedef __gnu_test::pod_state    state_type;
+      typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
+      base_type;
+
+      explicit codecvt(size_t refs = 0) : base_type(refs)
+      { }
+
+      static locale::id id;
+
+    protected:
+      ~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_limit,
+            extern_type*& to_next) const
+      {
+       while (from < from_end && to < to_limit)
+         {
+           unsigned char tmp = (state.value ^ from->value);
+           if (state.value & 0x8)
+             {
+               if (to >= to_limit - 2)
+                 break;
+               *to++ = (tmp & 0x7);
+               *to++ = ((tmp >> 3) & 0x7);
+               *to++ = ((tmp >> 6) & 0x3);
+             }
+           else
+             {
+               if (to >= to_limit - 1)
+                 break;
+               *to++ = (tmp & 0xf);
+               *to++ = ((tmp >> 4) & 0xf);
+             }
+           state.value = tmp;
+           ++from;
+         }
+
+       from_next = from;
+       to_next = to;
+       return (from < from_end) ? partial : ok;
+      }
+
+      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_limit,
+           intern_type*& to_next) const
+      {
+       while (from < from_end && to < to_limit)
+         {
+           unsigned char c = *from;
+           if (c & 0xc0)
+             {
+               // Unshift sequence
+               state.value &= c;
+               ++from;
+               continue;
+             }
+
+           unsigned char tmp;
+           if (state.value & 0x8)
+             {
+               if (from >= from_end - 2)
+                 break;
+               tmp = (*from++ & 0x7);
+               tmp |= ((*from++ << 3) & 0x38);
+               tmp |= ((*from++ << 6) & 0xc0);
+             }
+           else
+             {
+               if (from >= from_end - 1)
+                 break;
+               tmp = (*from++ & 0xf);
+               tmp |= ((*from++ << 4) & 0xf0);
+             }
+           to->value = (tmp ^ state.value);
+           state.value = tmp;
+           ++to;
+         }
+
+       from_next = from;
+       to_next = to;
+       return (from < from_end) ? partial : ok;
+      }
+
+      virtual result
+      do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
+                extern_type*& to_next) const
+      {
+       for (unsigned int i = 0; i < CHAR_BIT; ++i)
+         {
+           unsigned int mask = (1 << i);
+           if (state.value & mask)
+             {
+               if (to == to_limit)
+                 {
+                   to_next = to;
+                   return partial;
+                 }
+
+               state.value &= ~mask;
+               *to++ = static_cast<unsigned char>(~mask);
+             }
+         }
+
+       to_next = to;
+       return state.value == 0 ? ok : error;
+      }
+
+      virtual int
+      do_encoding() const throw()
+      { return -1; }
+
+      virtual bool
+      do_always_noconv() const throw()
+      { return false; }
+
+      virtual int
+      do_length(state_type& state, const extern_type* from,
+               const extern_type* end, size_t max) const
+      {
+       const extern_type* beg = from;
+       while (from < end && max)
+         {
+           unsigned char c = *from;
+           if (c & 0xc0)
+             {
+               // Unshift sequence
+               state.value &= c;
+               ++from;
+               continue;
+             }
+
+           unsigned char tmp;
+           if (state.value & 0x8)
+             {
+               if (from >= end - 2)
+                 break;
+               tmp = (*from++ & 0x7);
+               tmp |= ((*from++ << 3) & 0x38);
+               tmp |= ((*from++ << 6) & 0xc0);
+             }
+           else
+             {
+               if (from >= end - 1)
+                 break;
+               tmp = (*from++ & 0xf);
+               tmp |= ((*from++ << 4) & 0xf0);
+             }
+           state.value = tmp;
+           --max;
+         }
+       return from - beg;
+      }
+
+      // Maximum 8 bytes unshift sequence followed by max 3 bytes for
+      // one character.
+      virtual int
+      do_max_length() const throw()
+      { return 11; }
+    };
+
+  template<>
+    class ctype<__gnu_test::pod_uchar>
+    : public __ctype_abstract_base<__gnu_test::pod_uchar>
+    {
+    public:
+      typedef __gnu_test::pod_uchar char_type;
+
+      explicit ctype(size_t refs  = 0)
+      : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
+
+      static locale::id id;
+
+    protected:
+      ~ctype()
+      { }
+
+      virtual bool
+      do_is(mask, char_type) const
+      { return false; }
+
+      virtual const char_type*
+      do_is(const char_type* low, const char_type* high, mask* vec) const
+      {
+       fill_n(vec, high - low, mask());
+       return high;
+      }
+
+      virtual const char_type*
+      do_scan_is(mask, const char_type*, const char_type* high) const
+      { return high; }
+
+      virtual const char_type*
+      do_scan_not(mask, const char_type* low, const char_type*) const
+      { return low; }
+
+      virtual char_type
+      do_toupper(char_type c) const
+      { return c; }
+
+      virtual const char_type*
+      do_toupper(char_type*, const char_type*  high) const
+      { return high; }
+
+      virtual char_type
+      do_tolower(char_type c) const
+      { return c; }
+
+      virtual const char_type*
+      do_tolower(char_type*, const char_type*  high) const
+      { return high; }
+
+      virtual char_type
+      do_widen(char c) const
+      { return __gnu_test::pod_uchar::from<char>(c); }
+
+      virtual const char* 
+      do_widen(const char* low, const char* high, char_type* dest) const
+      {
+       transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
+       return high;
+      }
+
+      virtual char
+      do_narrow(char_type, char dfault) const
+      { return dfault; }
+
+      virtual const char_type*
+      do_narrow(const char_type* low, const char_type* high,
+               char dfault, char*  dest) const
+      {
+       fill_n(dest, high - low, dfault);
+       return high;
+      }
+    };
+
+  // numpunct specializations
+  template<> 
+    class numpunct<__gnu_test::pod_uint>
+    : public locale::facet
+    { 
+    public: 
+      typedef __gnu_test::pod_uint    char_type; 
+      typedef basic_string<char_type> string_type; 
+    
+      static locale::id id; 
+      
+      explicit
+      numpunct(size_t refs = 0)
+      : locale::facet(refs) 
+      { } 
+      char_type
+      decimal_point() const 
+      { return this->do_decimal_point(); } 
+      char_type
+      thousands_sep() const 
+      { return this->do_thousands_sep(); } 
+      string
+      grouping() const 
+      { return this->do_grouping(); } 
+      string_type
+      truename() const 
+      { return this->do_truename(); } 
+      string_type
+      falsename() const 
+      { return this->do_falsename(); } 
+    protected: 
+      ~numpunct()
+      { } 
+      virtual char_type
+      do_decimal_point() const 
+      { return char_type(); } 
+      virtual char_type
+      do_thousands_sep() const 
+      { return char_type(); } 
+      virtual string
+      do_grouping() const 
+      { return string(); } 
+      virtual string_type
+      do_truename() const 
+      { return string_type(); }
+      virtual string_type
+      do_falsename() const 
+      { return string_type(); } 
+    };
+
+  template<> 
+    class moneypunct<__gnu_test::pod_uint>
+    : public locale::facet, public money_base
+    { 
+    public: 
+      typedef __gnu_test::pod_uint    char_type; 
+      typedef basic_string<char_type> string_type; 
+    
+      static locale::id id; 
+      static const bool intl = false;
+
+      explicit
+      moneypunct(size_t refs = 0)
+      : locale::facet(refs) 
+      { }
+      char_type
+      decimal_point() const 
+      { return this->do_decimal_point(); } 
+      char_type
+      thousands_sep() const 
+      { return this->do_thousands_sep(); }
+
+      string
+      grouping() const
+      { return this->do_grouping(); }
+
+      string_type
+      curr_symbol() const 
+      { return this->do_curr_symbol(); } 
+      string_type
+      positive_sign() const 
+      { return this->do_positive_sign(); } 
+
+      string_type
+      negative_sign() const 
+      { return this->do_negative_sign(); } 
+      
+      int
+      frac_digits() const
+      { return this->do_frac_digits(); }
+
+      pattern
+      pos_format() const
+      { return this->do_pos_format(); }
+      pattern
+      neg_format() const
+      { return this->do_neg_format(); }
+  
+    protected: 
+      ~moneypunct() 
+      { } 
+      virtual char_type
+      do_decimal_point() const 
+      { return char_type(); } 
+      virtual char_type
+      do_thousands_sep() const 
+      { return char_type(); } 
+      virtual string
+      do_grouping() const 
+      { return string(); }
+
+      virtual string_type
+      do_curr_symbol() const 
+      { return string_type(); } 
+      string_type
+      do_positive_sign() const 
+      { return string_type(); } 
+
+      string_type
+      do_negative_sign() const 
+      { return string_type(); } 
+      
+      int
+      do_frac_digits() const
+      { return 0; }
+
+      pattern
+      do_pos_format() const
+      { return pattern(); }
+      pattern
+      do_neg_format() const
+      { return pattern(); }
+     };
+} // namespace std
+
+#endif // _GLIBCXX_TESTSUITE_CHARACTER_H
+