// Character Traits for use by standard string and iostream -*- C++ -*-
-// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 1997-2014 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)
+// 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,
// 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.
+// 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.
-// As a special exception, you may use this file as part of a free software
-// library without restriction. Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License. This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// 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/>.
+
+/** @file bits/char_traits.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{string}
+ */
//
// ISO C++ 14882: 21 Strings library
//
-#ifndef _CPP_BITS_CHAR_TRAITS_H
-#define _CPP_BITS_CHAR_TRAITS_H 1
+#ifndef _CHAR_TRAITS_H
+#define _CHAR_TRAITS_H 1
#pragma GCC system_header
-#include <bits/std_cstring.h> // For memmove, memset, memchr
-#include <bits/fpos.h> // For streampos
+#include <bits/stl_algobase.h> // std::copy, std::fill_n
+#include <bits/postypes.h> // For streampos
+#include <cwchar> // For WEOF, wmemmove, wmemset, etc.
-namespace std
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
- // 21.1.2 Basis for explicit _Traits specialization
- // NB: That for any given actual character type this definition is
- // probably wrong.
- template<class _CharT>
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @brief Mapping from character type to associated types.
+ *
+ * @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<typename _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 fundamental types, but classes in
+ * namespace __gnu_cxx may be.
+ *
+ * See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt05ch13s03.html
+ * for advice on how to make use of this class for @a unusual character
+ * types. Also, check out include/ext/pod_char_traits.h.
+ */
+ template<typename _CharT>
struct char_traits
{
- typedef _CharT char_type;
- // Unsigned as wint_t in unsigned.
- typedef unsigned long int_type;
- typedef streampos pos_type;
- typedef streamoff off_type;
- typedef mbstate_t state_type;
-
- static void
+ 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)
{ __c1 = __c2; }
- static bool
+ static _GLIBCXX_CONSTEXPR bool
eq(const char_type& __c1, const char_type& __c2)
{ return __c1 == __c2; }
- static bool
+ static _GLIBCXX_CONSTEXPR bool
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)
- {
- for (size_t __i = 0; __i < __n; ++__i)
- if (!eq(__s1[__i], __s2[__i]))
- return lt(__s1[__i], __s2[__i]) ? -1 : 1;
- return 0;
- }
+ static int
+ compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
- static size_t
- length(const char_type* __s)
- {
- const char_type* __p = __s;
- while (*__p) ++__p;
- return (__p - __s);
- }
+ 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)
- {
- for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p)
- if (*__p == __a) return __p;
- return 0;
- }
+ static const char_type*
+ 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)
- { return (char_type*) std::memmove(__s1, __s2, __n * sizeof(char_type)); }
+ static char_type*
+ 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)
- { return (char_type*) std::memcpy(__s1, __s2, __n * sizeof(char_type)); }
+ static char_type*
+ 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)
- {
- for (char_type* __p = __s; __p < __s + __n; ++__p)
- assign(*__p, __a);
- return __s;
- }
+ static char_type*
+ assign(char_type* __s, std::size_t __n, char_type __a);
- static char_type
+ static _GLIBCXX_CONSTEXPR char_type
to_char_type(const int_type& __c)
- { return char_type(__c); }
+ { return static_cast<char_type>(__c); }
- static int_type
- to_int_type(const char_type& __c) { return int_type(__c); }
+ static _GLIBCXX_CONSTEXPR int_type
+ to_int_type(const char_type& __c)
+ { return static_cast<int_type>(__c); }
- static bool
+ static _GLIBCXX_CONSTEXPR bool
eq_int_type(const int_type& __c1, const int_type& __c2)
{ return __c1 == __c2; }
- static int_type
- eof() { return static_cast<int_type>(-1); }
+ static _GLIBCXX_CONSTEXPR int_type
+ eof()
+ { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
- static int_type
+ static _GLIBCXX_CONSTEXPR int_type
not_eof(const int_type& __c)
- { return eq_int_type(__c, eof()) ? int_type(0) : __c; }
+ { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
};
+ template<typename _CharT>
+ int
+ char_traits<_CharT>::
+ compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
+ {
+ for (std::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*>(__builtin_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)
+ {
+ // NB: Inline std::copy so no recursive dependencies.
+ 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)
+ {
+ // NB: Inline std::fill_n so no recursive dependencies.
+ std::fill_n(__s, __n, __a);
+ return __s;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // 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++/manual/bk01pt05ch13s03.html
+ * for advice on how to make use of this class for @a 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.4 char_traits specializations
+ /// 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;
-
- static void
- assign(char_type& __c1, const char_type& __c2)
+ 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) _GLIBCXX_NOEXCEPT
{ __c1 = __c2; }
- static bool
- eq(const char_type& __c1, const char_type& __c2)
+ static _GLIBCXX_CONSTEXPR bool
+ eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
{ return __c1 == __c2; }
- static bool
- lt(const char_type& __c1, const char_type& __c2)
- { return __c1 < __c2; }
+ static _GLIBCXX_CONSTEXPR bool
+ lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
+ {
+ // LWG 467.
+ return (static_cast<unsigned char>(__c1)
+ < static_cast<unsigned char>(__c2));
+ }
- static int
+ static int
compare(const char_type* __s1, const char_type* __s2, size_t __n)
- { return memcmp(__s1, __s2, __n); }
+ { return __builtin_memcmp(__s1, __s2, __n); }
static size_t
length(const char_type* __s)
- { return strlen(__s); }
+ { return __builtin_strlen(__s); }
- static const char_type*
+ static const char_type*
find(const char_type* __s, size_t __n, const char_type& __a)
- { return static_cast<const char_type*>(memchr(__s, __a, __n)); }
+ { return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); }
- static char_type*
+ static char_type*
move(char_type* __s1, const char_type* __s2, size_t __n)
- { return static_cast<char_type*>(memmove(__s1, __s2, __n)); }
+ { return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); }
- static char_type*
+ static char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n)
- { return static_cast<char_type*>(memcpy(__s1, __s2, __n)); }
+ { return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); }
- static char_type*
+ static char_type*
assign(char_type* __s, size_t __n, char_type __a)
- { return static_cast<char_type*>(memset(__s, __a, __n)); }
+ { return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); }
- static char_type
- to_char_type(const int_type& __c)
+ static _GLIBCXX_CONSTEXPR char_type
+ to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
{ return static_cast<char_type>(__c); }
// To keep both the byte 0xff and the eof symbol 0xffffffff
// from ending up as 0xffffffff.
- static int_type
- to_int_type(const char_type& __c)
+ static _GLIBCXX_CONSTEXPR int_type
+ to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
{ return static_cast<int_type>(static_cast<unsigned char>(__c)); }
- static bool
- eq_int_type(const int_type& __c1, const int_type& __c2)
+ static _GLIBCXX_CONSTEXPR bool
+ eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
{ return __c1 == __c2; }
- static int_type
- eof() { return static_cast<int_type>(EOF); }
+ static _GLIBCXX_CONSTEXPR int_type
+ eof() _GLIBCXX_NOEXCEPT
+ { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
- static int_type
- not_eof(const int_type& __c)
+ static _GLIBCXX_CONSTEXPR int_type
+ not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
{ return (__c == eof()) ? 0 : __c; }
};
-#ifdef _GLIBCPP_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_WCHAR_T
+ /// 21.1.3.2 char_traits specializations
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;
-
- static void
- assign(char_type& __c1, const char_type& __c2)
+ 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) _GLIBCXX_NOEXCEPT
{ __c1 = __c2; }
- static bool
- eq(const char_type& __c1, const char_type& __c2)
+ static _GLIBCXX_CONSTEXPR bool
+ eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
{ return __c1 == __c2; }
- static bool
- lt(const char_type& __c1, const char_type& __c2)
+ static _GLIBCXX_CONSTEXPR bool
+ lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
{ return __c1 < __c2; }
- static int
+ static int
compare(const char_type* __s1, const char_type* __s2, size_t __n)
{ return wmemcmp(__s1, __s2, __n); }
length(const char_type* __s)
{ return wcslen(__s); }
- static const char_type*
+ static const char_type*
find(const char_type* __s, size_t __n, const char_type& __a)
{ return wmemchr(__s, __a, __n); }
- static char_type*
- move(char_type* __s1, const char_type* __s2, int_type __n)
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
{ return wmemmove(__s1, __s2, __n); }
- static char_type*
+ static char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n)
{ return wmemcpy(__s1, __s2, __n); }
- static char_type*
+ static char_type*
assign(char_type* __s, size_t __n, char_type __a)
{ return wmemset(__s, __a, __n); }
- static char_type
- to_char_type(const int_type& __c) { return char_type(__c); }
+ static _GLIBCXX_CONSTEXPR char_type
+ to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
+ { return char_type(__c); }
- static int_type
- to_int_type(const char_type& __c) { return int_type(__c); }
+ static _GLIBCXX_CONSTEXPR int_type
+ to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
+ { return int_type(__c); }
- static bool
- eq_int_type(const int_type& __c1, const int_type& __c2)
+ static _GLIBCXX_CONSTEXPR bool
+ eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
{ return __c1 == __c2; }
- static int_type
- eof() { return static_cast<int_type>(WEOF); }
+ static _GLIBCXX_CONSTEXPR int_type
+ eof() _GLIBCXX_NOEXCEPT
+ { return static_cast<int_type>(WEOF); }
- static int_type
- not_eof(const int_type& __c)
+ static _GLIBCXX_CONSTEXPR int_type
+ not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
{ return eq_int_type(__c, eof()) ? 0 : __c; }
};
-#endif //_GLIBCPP_USE_WCHAR_T
+#endif //_GLIBCXX_USE_WCHAR_T
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#if ((__cplusplus >= 201103L) \
+ && defined(_GLIBCXX_USE_C99_STDINT_TR1))
+
+#include <cstdint>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<>
+ struct char_traits<char16_t>
+ {
+ typedef char16_t char_type;
+ typedef uint_least16_t int_type;
+ typedef streamoff off_type;
+ typedef u16streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2) noexcept
+ { __c1 = __c2; }
+
+ static constexpr bool
+ eq(const char_type& __c1, const char_type& __c2) noexcept
+ { return __c1 == __c2; }
+
+ static constexpr bool
+ lt(const char_type& __c1, const char_type& __c2) noexcept
+ { return __c1 < __c2; }
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, 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;
+ }
+
+ static size_t
+ length(const char_type* __s)
+ {
+ size_t __i = 0;
+ while (!eq(__s[__i], char_type()))
+ ++__i;
+ return __i;
+ }
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ {
+ for (size_t __i = 0; __i < __n; ++__i)
+ if (eq(__s[__i], __a))
+ return __s + __i;
+ return 0;
+ }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ return (static_cast<char_type*>
+ (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+ }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ return (static_cast<char_type*>
+ (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+ }
- template<typename _CharT, typename _Traits>
- struct _Char_traits_match
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ {
+ for (size_t __i = 0; __i < __n; ++__i)
+ assign(__s[__i], __a);
+ return __s;
+ }
+
+ static constexpr char_type
+ to_char_type(const int_type& __c) noexcept
+ { return char_type(__c); }
+
+ static constexpr int_type
+ to_int_type(const char_type& __c) noexcept
+ { return int_type(__c); }
+
+ static constexpr bool
+ eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
+ { return __c1 == __c2; }
+
+ static constexpr int_type
+ eof() noexcept
+ { return static_cast<int_type>(-1); }
+
+ static constexpr int_type
+ not_eof(const int_type& __c) noexcept
+ { return eq_int_type(__c, eof()) ? 0 : __c; }
+ };
+
+ template<>
+ struct char_traits<char32_t>
{
- _CharT _M_c;
- _Char_traits_match(_CharT const& __c) : _M_c(__c) { }
+ typedef char32_t char_type;
+ typedef uint_least32_t int_type;
+ typedef streamoff off_type;
+ typedef u32streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2) noexcept
+ { __c1 = __c2; }
+
+ static constexpr bool
+ eq(const char_type& __c1, const char_type& __c2) noexcept
+ { return __c1 == __c2; }
- bool
- operator()(_CharT const& __a) { return _Traits::eq(_M_c, __a); }
+ static constexpr bool
+ lt(const char_type& __c1, const char_type& __c2) noexcept
+ { return __c1 < __c2; }
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, 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;
+ }
+
+ static size_t
+ length(const char_type* __s)
+ {
+ size_t __i = 0;
+ while (!eq(__s[__i], char_type()))
+ ++__i;
+ return __i;
+ }
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ {
+ for (size_t __i = 0; __i < __n; ++__i)
+ if (eq(__s[__i], __a))
+ return __s + __i;
+ return 0;
+ }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ return (static_cast<char_type*>
+ (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+ }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ {
+ return (static_cast<char_type*>
+ (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+ }
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ {
+ for (size_t __i = 0; __i < __n; ++__i)
+ assign(__s[__i], __a);
+ return __s;
+ }
+
+ static constexpr char_type
+ to_char_type(const int_type& __c) noexcept
+ { return char_type(__c); }
+
+ static constexpr int_type
+ to_int_type(const char_type& __c) noexcept
+ { return int_type(__c); }
+
+ static constexpr bool
+ eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
+ { return __c1 == __c2; }
+
+ static constexpr int_type
+ eof() noexcept
+ { return static_cast<int_type>(-1); }
+
+ static constexpr int_type
+ not_eof(const int_type& __c) noexcept
+ { return eq_int_type(__c, eof()) ? 0 : __c; }
};
-} // namespace std
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif
-#endif
+#endif // _CHAR_TRAITS_H