// file      : xsd/cxx/tree/traits.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_TREE_TRAITS_HXX
#define XSD_CXX_TREE_TRAITS_HXX

#include <sstream>

#include <xsd/cxx/tree/elements.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      // bool
      //
      template <>
      struct traits<bool>
      {
        typedef bool type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e);

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a);
      };

      template <>
      inline
      traits<bool>::type traits<bool>::
      create<char> (xml::dom::element<char> const& e)
      {
        return (e.value () == "true") || (e.value () == "1");
      }

      template <>
      inline
      traits<bool>::type traits<bool>::
      create<wchar_t> (xml::dom::element<wchar_t> const& e)
      {
        return (e.value () == L"true") || (e.value () == L"1");
      }

      template <>
      inline
      traits<bool>::type traits<bool>::
      create<char> (xml::dom::attribute<char> const& a)
      {
        return (a.value () == "true") || (a.value () == "1");
      }

      template <>
      inline
      traits<bool>::type traits<bool>::
      create<wchar_t> (xml::dom::attribute<wchar_t> const& a)
      {
        return (a.value () == L"true") || (a.value () == L"1");
      }


      // 8 bit
      //
      template <>
      struct traits<signed char>
      {
        typedef signed char type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          short t;
          s >> t;

          return static_cast<type> (t);
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          short t;
          s >> t;

          return static_cast<type> (t);
        }
      };

      template <>
      struct traits<unsigned char>
      {
        typedef unsigned char type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          unsigned short t;
          s >> t;

          return static_cast<type> (t);
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          unsigned short t;
          s >> t;

          return static_cast<type> (t);
        }
      };

      // 16 bit
      //
      template <>
      struct traits<short>
      {
        typedef short type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      template <>
      struct traits<unsigned short>
      {
        typedef unsigned short type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      // 32 bit
      //
      template <>
      struct traits<int>
      {
        typedef int type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      template <>
      struct traits<unsigned int>
      {
        typedef unsigned int type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      // 64 bit
      //
      template <>
      struct traits<long long>
      {
        typedef long long type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      template <>
      struct traits<unsigned long long>
      {
        typedef unsigned long long type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      // floating point
      //
      template <>
      struct traits<float>
      {
        typedef float type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      template <>
      struct traits<double>
      {
        typedef double type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };

      template <>
      struct traits<long double>
      {
        typedef long double type;

        static void
        set_container (type&, tree::type*)
        {
        }

        template <typename c>
        static type
        create (xml::dom::element<c> const& e)
        {
          std::basic_istringstream<c> s (e.value ());

          type t;
          s >> t;

          return t;
        }

        template <typename c>
        static type
        create (xml::dom::attribute<c> const& a)
        {
          std::basic_istringstream<c> s (a.value ());

          type t;
          s >> t;

          return t;
        }
      };
    }
  }
}

#endif  // XSD_CXX_TREE_TRAITS_HXX
