diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 75dcdccbae282f1d6877d240fd22d74ad6e6df50..f2925d0e65e98122ac9f439500a21f4a3b0d2b4f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2003-07-24 Matt Austern <austern@apple.com> + + * /include/bits/char_traits.h (class char_traits): Put all the + real work into the new class template __gnu_cxx::char_traits. + Gave generic definitions for member functions. Types are taken + from the new class template __gnu_cxx::_Char_types. + * testsuite/21_strings/char_traits/requirements/short/1.cc: New + file. Test of std::char_traits<short>, which serves as a test of + the char_traits primary template. + 2003-07-24 Benjamin Kosnik <bkoz@redhat.com> * testsuite/*: Change __gnu_cxx_test to __gnu_test. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 80736942b9076d946b4fe751751efb908bb202a6..23b69f32bfd5191cd6e6cded5ca4e72133133f38 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -43,83 +43,200 @@ #pragma GCC system_header #include <cstring> // For memmove, memset, memchr +#include <bits/stl_algobase.h>// For copy, lexicographical_compare, fill_n #include <bits/fpos.h> // For streampos -namespace std +namespace __gnu_cxx { - // 21.1 + /** - * @brief Basis for explicit traits specializations. + * @brief Mapping from character type to associated types. + * * - * @note For any given actual character type, this definition is - * probably wrong. + * @note This is an implementation class for the generic version + * of char_traits. It defines int_type, off_type, pos_type, and + * state_type. By default these are unsigned long, streamoff, + * streampos, and mbstate_t. Users who need a different set of + * types, but who don't need to change the definitions of any function + * defined in char_traits, can specialize __gnu_cxx::_Char_types + * while leaving __gnu_cxx::char_traits alone. */ + template <class _CharT> + struct _Char_types + { + typedef unsigned long int_type; + typedef std::streampos pos_type; + typedef std::streamoff off_type; + typedef std::mbstate_t state_type; + }; + + + /** + * @brief Base class used to implement std::char_traits. + * + * @note For any given actual character type, this definition is + * probably wrong. (Most of the member functions are likely to be + * right, but the int_type and state_type typedefs, and the eof() + * member function, are likely to be wrong.) The reason this class + * exists is so users can specialize it. Classes in namespace std + * may not be specialized for fundamentl types, but classes in + * namespace __gnu_cxx may be. * * See http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#5 * for advice on how to make use of this class for "unusual" character - * types. Also, check out include/ext/pod_char_traits.h. - */ - template<class _CharT> + * types. Also, check out include/ext/pod_char_traits.h. */ + template<typename _CharT> struct char_traits { - typedef _CharT char_type; - typedef unsigned long int_type; - typedef streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; + typedef _CharT char_type; + typedef typename _Char_types<_CharT>::int_type int_type; + typedef typename _Char_types<_CharT>::pos_type pos_type; + typedef typename _Char_types<_CharT>::off_type off_type; + typedef typename _Char_types<_CharT>::state_type state_type; static void - assign(char_type& __c1, const char_type& __c2); + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } static bool - eq(const char_type& __c1, const char_type& __c2); + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } static bool - lt(const char_type& __c1, const char_type& __c2); + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } static int - compare(const char_type* __s1, const char_type* __s2, size_t __n); + compare(const char_type* __s1, const char_type* __s2, std::size_t __n); - static size_t + static std::size_t length(const char_type* __s); static const char_type* - find(const char_type* __s, size_t __n, const char_type& __a); + find(const char_type* __s, std::size_t __n, const char_type& __a); static char_type* - move(char_type* __s1, const char_type* __s2, size_t __n); + move(char_type* __s1, const char_type* __s2, std::size_t __n); static char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n); + copy(char_type* __s1, const char_type* __s2, std::size_t __n); static char_type* - assign(char_type* __s, size_t __n, char_type __a); + assign(char_type* __s, std::size_t __n, char_type __a); static char_type - to_char_type(const int_type& __c); + to_char_type(const int_type& __c) + { return static_cast<char_type>(__c); } static int_type - to_int_type(const char_type& __c); + to_int_type(const char_type& __c) + { return static_cast<int_type>(__c); } static bool - eq_int_type(const int_type& __c1, const int_type& __c2); + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } static int_type - eof(); + eof() + { return static_cast<int_type>(EOF); } static int_type - not_eof(const int_type& __c); + not_eof(const int_type& __c) + { return !eq_int_type(__c, eof()) ? __c : char_type(); } }; + template<typename _CharT> + int + char_traits<_CharT>:: + compare(const char_type* __s1, const char_type* __s2, std::size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + template<typename _CharT> + std::size_t + char_traits<_CharT>:: + length(const char_type* __p) + { + std::size_t __i = 0; + while (!eq(__p[__i], char_type())) + ++__i; + return __i; + } + + template<typename _CharT> + const typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + find(const char_type* __s, std::size_t __n, const char_type& __a) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + template<typename _CharT> + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + move(char_type* __s1, const char_type* __s2, std::size_t __n) + { + return static_cast<_CharT*>(std::memmove(__s1, __s2, + __n * sizeof(char_type))); + } + + template<typename _CharT> + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + copy(char_type* __s1, const char_type* __s2, std::size_t __n) + { + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } + + template<typename _CharT> + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + assign(char_type* __s, std::size_t __n, char_type __a) + { + std::fill_n(__s, __n, __a); + return __s; + } +} + +namespace std +{ + // 21.1 + /** + * @brief Basis for explicit traits specializations. + * + * @note For any given actual character type, this definition is + * probably wrong. Since this is just a thin wrapper around + * __gnu_cxx::char_traits, it is possible to achieve a more + * appropriate definition by specializing __gnu_cxx::char_traits. + * + * See http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#5 + * for advice on how to make use of this class for "unusual" character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template<class _CharT> + struct char_traits + : public __gnu_cxx::char_traits<_CharT> + { }; + /// 21.1.3.1 char_traits specializations template<> struct char_traits<char> { - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; static void assign(char_type& __c1, const char_type& __c2) @@ -185,11 +302,11 @@ namespace std template<> struct char_traits<wchar_t> { - typedef wchar_t char_type; - typedef wint_t int_type; - typedef streamoff off_type; - typedef wstreampos pos_type; - typedef mbstate_t state_type; + typedef wchar_t char_type; + typedef wint_t int_type; + typedef streamoff off_type; + typedef wstreampos pos_type; + typedef mbstate_t state_type; static void assign(char_type& __c1, const char_type& __c2) diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/short/1.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/short/1.cc new file mode 100644 index 0000000000000000000000000000000000000000..4a61942efc7a5cc729bc56078bf177c7544b0e75 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/short/1.cc @@ -0,0 +1,172 @@ +// 1999-06-03 bkoz +// 2003-07-22 Matt Austern + +// Copyright (C) 1999, 2000, 2001, 2003 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 2, 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 COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 21.1.1 Character traits requirements +// Make sure we can instantiate char_traits and basic_string for +// charT = 'short', and make sure the char_traits memeber functions +// satisfy the requirements of 21.1.1. + +#include <string> +#include <testsuite_hooks.h> + +void test02(void) +{ + bool test = true; + + // 21.1.1 character traits requirements + + // Key for decoding what function signatures really mean: + // X == char_traits<_CharT> + // [c,d] == _CharT + // [p,q] == const _CharT* + // s == _CharT* + // [n,i,j] == size_t + // f == X::int_type + // pos == X::pos_type + // state == X::state_type + + // void X::assign(short c, short d) + // assigns c = d; + short c1 = 'z'; + short c2 = 'u'; + VERIFY( c1 != c2 ); + std::char_traits<short>::assign(c1,c2); + VERIFY( c1 == 'u' ); + + // bool X::eq(short c, short d) + c1 = 'z'; + c2 = 'u'; + VERIFY ( !std::char_traits<short>::eq(c1, c2) ); + VERIFY ( std::char_traits<short>::eq(c1, c1) ); + VERIFY ( std::char_traits<short>::eq(c2, c2) ); + + // bool X::lt(short c, short d) + c1 = 'z'; + c2 = 'u'; + VERIFY ( std::char_traits<short>::lt(c2, c1) ); + VERIFY ( !std::char_traits<short>::lt(c1, c2) ); + VERIFY ( !std::char_traits<short>::lt(c1, c1) ); + VERIFY ( !std::char_traits<short>::lt(c2, c2) ); + + // short* X::move(short* s, const short* p, size_t n) + // for each i in [0,n) performs X::assign(s[i], p[i]). Copies + // correctly even where p is in [s, s + n), and yields s. + short array1[] = {'z', 'u', 'm', 'a', ' ', 'b', 'e', 'a', 'c', 'h', 0}; + const std::basic_string<short> str_01(array1 + 0, array1 + 10); + + const short str_lit1[] = {'m', 'o', 'n', 't', 'a', 'r', 'a', ' ', 'a', 'n', 'd', ' ', 'o', 'c', 'e', 'a', 'n', ' ', 'b', 'e', 'a', 'c', 'h', 0}; + + int len = sizeof(str_lit1)/sizeof(short) + sizeof(array1)/sizeof(short) - 1; + // two terminating chars + short array2[len]; + + VERIFY( str_lit1[0] == 'm' ); + c1 = array2[0]; + c2 = str_lit1[0]; + short c3 = array2[1]; + short c4 = str_lit1[1]; + std::char_traits<short>::move(array2, str_lit1, 0); + VERIFY( array2[0] == c1 ); + VERIFY( str_lit1[0] == c2 ); + std::char_traits<short>::move(array2, str_lit1, 1); + VERIFY( array2[0] == c2 ); + VERIFY( str_lit1[0] == c2 ); + VERIFY( array2[1] == c3 ); + VERIFY( str_lit1[1] == c4 ); + std::char_traits<short>::move(array2, str_lit1, 2); + VERIFY( array2[0] == c2 ); + VERIFY( str_lit1[0] == c2 ); + VERIFY( array2[1] == c4 ); + VERIFY( str_lit1[1] == c4 ); + + short* pc1 = array1 + 1; + c1 = pc1[0]; + c2 = array1[0]; + VERIFY( c1 != c2 ); + short* pc2 = std::char_traits<short>::move(array1, pc1, 0); + c3 = pc1[0]; + c4 = array1[0]; + VERIFY( c1 == c3 ); + VERIFY( c2 == c4 ); + VERIFY( pc2 == array1 ); + + c1 = pc1[0]; + c2 = array1[0]; + short* pc3 = pc1; + pc2 = std::char_traits<short>::move(array1, pc1, 10); + c3 = pc1[0]; + c4 = array1[0]; + VERIFY( c1 != c3 ); // underlying short array changed. + VERIFY( c4 != c3 ); + VERIFY( pc2 == array1 ); + VERIFY( pc3 == pc1 ); // but pointers o-tay + c1 = *(str_01.data()); + c2 = array1[0]; + VERIFY( c1 != c2 ); + + // size_t X::length(const short* p) + len = std::char_traits<short>::length(str_lit1); + VERIFY( len == sizeof(str_lit1) / sizeof(short) - 1 ); + + // const short* X::find(const short* s, size_t n, short c) + const int N4 = sizeof(str_lit1) / sizeof(short); + const short* pc4 = std::char_traits<short>::find(str_lit1, N4, 'a'); + VERIFY( pc4 != 0 ); + VERIFY( *pc4 == 'a' ); + + pc4 = std::char_traits<short>::find(str_lit1, N4, 0x0a73); + VERIFY( pc4 == 0 ); + + // short* X::assign(short* s, size_t n, short c) + len = sizeof(array2) / sizeof(short); + memset(array2, 0xaf, len * sizeof(short)); + VERIFY( array2[0] != 0x15a8 ); + + pc1 = std::char_traits<short>::assign (array2, len, 0x15a8); + VERIFY( pc1 == array2 ); + for (int i = 0; i < len; ++i) + VERIFY( array2[i] == 0x15a8 ); + + // short* X::copy(short* s, const short* p, size_t n) + int n1 = sizeof(str_lit1) / sizeof(short); + pc1 = std::char_traits<short>::copy(array2, str_lit1, n1); + len = std::char_traits<short>::length(array2); + VERIFY( len == n1 - 1 ); + for (int i = 0; i < len; ++i) + VERIFY( str_lit1[i] == array2[i] ); + + // int X::compare(const short* p, const short* q, size_t n) + const short* pconst1 = str_01.data(); + const short* pconst2 = str_lit1; + + VERIFY( std::char_traits<short>::compare(pconst1, pconst2, 10) > 0 ); + VERIFY( std::char_traits<short>::compare(pconst2, pconst1, 10) < 0 ); + VERIFY( std::char_traits<short>::compare(pconst1, pconst1, 10) == 0 ); + VERIFY( std::char_traits<short>::compare(pconst2, pconst2, 10) == 0 ); +} + + + +int main() +{ + test02(); + return 0; +}