// POD character, std::char_traits specialization -*- C++ -*-

// Copyright (C) 2002-2021 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/>.

/** @file ext/pod_char_traits.h
 *  This file is a GNU extension to the Standard C++ Library.
 */

// Gabriel Dos Reis <gdr@integrable-solutions.net>
// Benjamin Kosnik <bkoz@redhat.com>

#ifndef _POD_CHAR_TRAITS_H
#define _POD_CHAR_TRAITS_H 1

#pragma GCC system_header

#include <string>

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  // POD character abstraction.
  // NB: The char_type parameter is a subset of int_type, as to allow
  // int_type to properly hold the full range of char_type values as
  // well as EOF.
  /// @brief A POD class that serves as a character abstraction class.
  template<typename _Value, typename _Int, typename _St = std::mbstate_t>
    struct character
    {
      typedef _Value				value_type;
      typedef _Int				int_type;
      typedef _St				state_type;
      typedef character<_Value, _Int, _St>	char_type;

      value_type	value;

      template<typename V2>
        static char_type
        from(const V2& v)
        {
	  char_type ret = { static_cast<value_type>(v) };
	  return ret;
	}

      template<typename V2>
        static V2
        to(const char_type& c)
        {
	  V2 ret = { static_cast<V2>(c.value) };
	  return ret;
	}

    };

  template<typename _Value, typename _Int, typename _St>
    inline bool
    operator==(const character<_Value, _Int, _St>& lhs,
	       const character<_Value, _Int, _St>& rhs)
    { return lhs.value == rhs.value; }

  template<typename _Value, typename _Int, typename _St>
    inline bool
    operator<(const character<_Value, _Int, _St>& lhs,
	      const character<_Value, _Int, _St>& rhs)
    { return lhs.value < rhs.value; }

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /// char_traits<__gnu_cxx::character> specialization.
  template<typename _Value, typename _Int, typename _St>
    struct char_traits<__gnu_cxx::character<_Value, _Int, _St> >
    {
      typedef __gnu_cxx::character<_Value, _Int, _St>	char_type;
      typedef typename char_type::int_type		int_type;
      typedef typename char_type::state_type		state_type;
      typedef fpos<state_type>				pos_type;
      typedef streamoff					off_type;

      static void
      assign(char_type& __c1, const char_type& __c2)
      { __c1 = __c2; }

      static bool
      eq(const char_type& __c1, const char_type& __c2)
      { return __c1 == __c2; }

      static 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 size_t
      length(const char_type* __s)
      {
	const char_type* __p = __s;
	while (__p->value)
	  ++__p;
	return (__p - __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 char_type*
      move(char_type* __s1, const char_type* __s2, size_t __n)
      { 
	if (__n == 0)
	  return __s1;
	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)
      {
	if (__n == 0)
	  return __s1;
	std::copy(__s2, __s2 + __n, __s1);
	return __s1;
      }

      static char_type*
      assign(char_type* __s, size_t __n, char_type __a)
      {
	std::fill_n(__s, __n, __a);
        return __s;
      }

      static char_type
      to_char_type(const int_type& __i)
      { return char_type::template from(__i); }

      static int_type
      to_int_type(const char_type& __c)
      { return char_type::template to<int_type>(__c); }

      static bool
      eq_int_type(const int_type& __c1, const int_type& __c2)
      { return __c1 == __c2; }

      static int_type
      eof() 
      {
	int_type __r = { static_cast<typename __gnu_cxx::__conditional_type
			 <std::__is_integer<int_type>::__value,
			 int_type, int>::__type>(-1) };
	return __r;
      }

      static int_type
      not_eof(const int_type& __c)
      { return eq_int_type(__c, eof()) ? int_type() : __c; }
    };

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif
