// file      : xsd/cxx/tree/traits.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005-2006 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

// Do not include this file directly. Rather include elements.hxx.
//

#include <sstream>

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const&, flags, tree::type*);

        template <typename C>
        static type
        create (xml::dom::attribute<C> const&, flags, tree::type*);

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const&, flags, tree::type*);

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };


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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          short t;
          is >> t;

          return static_cast<type> (t);
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          unsigned short t;
          is >> t;

          return static_cast<type> (t);
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };

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

        static bool
        same_container (type&, tree::type*)
        {
          return true;
        }

        template <typename C>
        static type
        create (xml::dom::element<C> const& e, flags f, tree::type* c)
        {
          return create (e.value (), f, c);
        }

        template <typename C>
        static type
        create (xml::dom::attribute<C> const& a, flags f, tree::type* c)
        {
          return create (a.value (), f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s,
                xml::dom::element<C> const&,
                flags f,
                tree::type* c)
        {
          return create (s, f, c);
        }

        template <typename C>
        static type
        create (std::basic_string<C> const& s, flags, tree::type*)
        {
          std::basic_istringstream<C> is (s);

          type t;
          is >> t;

          return t;
        }

        static std::auto_ptr<type>
        clone (type const& other, flags, tree::type*)
        {
          return std::auto_ptr<type> (new type (other));
        }
      };
    }
  }
}

#endif  // XSD_CXX_TREE_TRAITS_HXX

#include <xsd/cxx/tree/traits.ixx>
