/*	Copyright (C) 2004 Garrett A. Kajmowicz

	This file is part of the uClibc++ Library.
	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, 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
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#pragma once
#ifdef ARDUINO_ARCH_AVR
#include "basic_definitions"
#ifdef __UCLIBCXX_HAS_WCHAR__
#include "cwchar"
#include "cwctype"
#endif
#include <string.h>
namespace std
{
	/* Inlining all wrapped function calls to shrink the amount of code generated*/
	// Typedefs to use for stuff
	typedef signed int char_traits_off_type;

	// Generic char_traits
	template <class charT>
	struct _UCXXEXPORT char_traits
	{
	};

	// Specialize for char
	template <>
	struct _UCXXEXPORT char_traits<char>
	{
		typedef char char_type;
		typedef short int int_type;
		typedef char_traits_off_type off_type;
		typedef char_traits_off_type pos_type;
		typedef char state_type;

		inline static void assign(char_type &c, const char_type &d) { c = d; }

		static bool eq(const char_type &c1, const char_type &c2);

		static char_type to_char_type(const int_type &i);

		inline static int_type to_int_type(const char_type &c)
		{
			return static_cast<short int>(static_cast<unsigned char>(c));
		}

		inline static bool eq_int_type(const int_type &a, const int_type &b)
		{
			if (a == b)
			{
				return true;
			}
			return false;
		}

		inline static bool lt(const char_type &c1, const char_type &c2)
		{
			if (strncmp(&c1, &c2, 1) < 0)
			{
				return true;
			}
			return false;
		}

		inline static char_type *move(char_type *s1, const char_type *s2, size_t n)
		{
			return static_cast<char *>(memmove(s1, s2, n));
		}

		inline static char_type *copy(char_type *s1, const char_type *s2, size_t n)
		{
			for (unsigned long int i = 0; i < n; ++i)
			{
				assign(s1[i], s2[i]);
			}
			return s1 + n;
		}

		inline static char_type *assign(char_type *s, size_t n, char_type a)
		{
			return static_cast<char *>(memset(s, a, n));
		}

		inline static int compare(const char_type *s1, const char_type *s2, size_t n)
		{
			return strncmp(s1, s2, n);
		}

		inline static size_t length(const char_type *s)
		{
			return strlen(s);
		}

		static const char_type *find(const char_type *s, int n, const char_type &a);

		inline static char_type eos() { return 0; }
		inline static int_type eof() { return -1; }
		inline static int_type not_eof(const int_type &i)
		{
			if (i == -1)
			{
				return 0;
			}
			else
			{
				return i;
			}
		}
		static state_type get_state(pos_type p)
		{
			p = p;
			state_type a;
			return a;
		}
	};
#ifdef __UCLIBCXX_HAS_WCHAR__
	template <>
	struct _UCXXEXPORT char_traits<wchar_t>
	{
		typedef wchar_t char_type;
		typedef wint_t int_type;
		typedef char_traits_off_type off_type;
		typedef char_traits_off_type pos_type;
		// typedef mbstate_t state_type;

		static void assign(char_type &c, const char_type &d) { c = d; }

		static char_type to_char_type(const int_type &i)
		{
			return i;
		}

		static int_type to_int_type(const char_type &c)
		{
			return c;
		}

		inline static bool eq_int_type(const int_type &a, const int_type &b)
		{
			if (a == b)
			{
				return true;
			}
			return false;
		}
		/*
				inline static bool eq(const char_type &c1, const char_type &c2)
				{
					if (wcsncmp(&c1, &c2, 1) == 0)
					{
						return true;
					}
					return false;
				}

				inline static bool lt(const char_type &c1, const char_type &c2)
				{
					if (wcsncmp(&c1, &c2, 1) < 0)
					{
						return true;
					}
					return false;
				}
		*/
		inline static char_type *move(char_type *s1, const char_type *s2, size_t n)
		{
			return (char_type *)memmove(s1, s2, n * sizeof(char_type));
		}

		inline static char_type *copy(char_type *s1, const char_type *s2, size_t n)
		{
			for (unsigned long int i = 0; i < n; ++i)
			{
				assign(s1[i], s2[i]);
			}
			return s1 + n;
		}

		inline static char_type *assign(char_type *s, size_t n, char_type a)
		{
			return (char_type *)memset(s, a, n); /*FIXME*/
		}
		/*
				inline static int compare(const char_type *s1, const char_type *s2, size_t n)
				{
					return wcsncmp(s1, s2, n);
				}

				inline static size_t length(const char_type *s)
				{
					return wcslen(s);
				}
		*/
		static const char_type *find(const char_type *s, int n, const char_type &a);

		inline static char_type eos() { return 0; }

		inline static int_type eof() { return WEOF; }

		inline static int_type not_eof(const int_type &i)
		{
			if (i == WEOF)
			{
				return (int_type)0;
			}
			else
			{
				return i;
			}
		}
		/*
				static state_type get_state(pos_type)
				{
					state_type a;
					return a;
				}
		*/
	};
#endif
}
#else
#include "Cpp_Standard_Library.h"
#include _CSL_Official(bits/char_traits.h)
#endif