added type conversion to supported types

pull/40/head
Nestal Wan 2013-05-01 13:36:29 +08:00
parent 658fb757e3
commit 540e3d82db
3 changed files with 124 additions and 60 deletions

View File

@ -20,6 +20,8 @@
#include "Val.hh"
#include <iostream>
namespace gr {
Val::Val( ) :
@ -43,21 +45,25 @@ Val::TypeEnum Val::Type() const
const Val& Val::operator[]( const std::string& key ) const
{
static const Val null ;
if ( Type() == object_type )
{
const Object& obj = As<Object>() ;
Object::const_iterator i = obj.find(key) ;
return i != obj.end() ? i->second : null ;
}
else
return null ;
const Object& obj = As<Object>() ;
Object::const_iterator i = obj.find(key) ;
if ( i != obj.end() )
return i->second ;
// shut off compiler warning
BOOST_THROW_EXCEPTION(Error() << NoKey_(key)) ;
throw ;
}
const Val& Val::operator[]( std::size_t index ) const
{
static const Val null ;
return Type() == array_type ? As<Array>().at(index) : null ;
const Array& ar = As<Array>() ;
if ( index < ar.size() )
return ar[index] ;
// shut off compiler warning
BOOST_THROW_EXCEPTION(Error() << OutOfRange_(index)) ;
throw ;
}
void Val::Add( const std::string& key, const Val& value )
@ -65,4 +71,22 @@ void Val::Add( const std::string& key, const Val& value )
As<Object>().insert( std::make_pair(key, value) ) ;
}
void Val::Swap( Val& val )
{
std::swap( m_base, val.m_base ) ;
}
} // end of namespace
namespace std
{
void swap( gr::Val& v1, gr::Val& v2 )
{
v1.Swap( v2 ) ;
}
ostream& operator<<( ostream& os, gr::Val::TypeEnum t )
{
return os << static_cast<int>(t) ;
}
}

View File

@ -20,11 +20,14 @@
#pragma once
#include "util/Exception.hh"
#include <cstddef>
#include <memory>
#include <vector>
#include <map>
#include <string>
#include <iosfwd>
namespace gr {
@ -33,10 +36,20 @@ class Val
public :
enum TypeEnum { null_type, bool_type, double_type, int_type, object_type, array_type, string_type } ;
struct Error : virtual Exception {} ;
typedef boost::error_info<struct SrcType, TypeEnum> SrcType_ ;
typedef boost::error_info<struct DestType, TypeEnum> DestType_ ;
typedef boost::error_info<struct NoKey, std::string> NoKey_ ;
typedef boost::error_info<struct OutOfRange,std::size_t> OutOfRange_ ;
private :
template <typename T>
struct Type2Enum ;
template <typename T>
struct SupportType ;
public :
typedef std::vector<Val> Array ;
typedef std::map<std::string, Val> Object ;
@ -46,8 +59,28 @@ public :
~Val() ;
template <typename T>
Val( const T& t ) ;
explicit Val( const T& t )
{
Assign(t) ;
}
template <typename T>
Val& Assign( const T& t ) ;
void Swap( Val& val ) ;
Val& operator=( const Val& val )
{
Val tmp(val) ;
Swap(tmp) ;
return *this ;
}
template <typename T>
Val& operator=( const T& t )
{
return Assign(t) ;
}
template <typename T>
const T& As() const ;
@ -85,47 +118,27 @@ private :
static int EndArray( void *ctx ) ;
} ;
template <>
struct Val::Type2Enum<void>
{
static const TypeEnum type = null_type ;
} ;
template <> struct Val::Type2Enum<void> { static const TypeEnum type = null_type ; } ;
template <> struct Val::Type2Enum<long long> { static const TypeEnum type = int_type ; } ;
template <> struct Val::Type2Enum<bool> { static const TypeEnum type = bool_type ; } ;
template <> struct Val::Type2Enum<double> { static const TypeEnum type = double_type ;} ;
template <> struct Val::Type2Enum<std::string> { static const TypeEnum type = string_type ; } ;
template <> struct Val::Type2Enum<Val::Array> { static const TypeEnum type = array_type ; } ;
template <> struct Val::Type2Enum<Val::Object> { static const TypeEnum type = object_type ; } ;
template <>
struct Val::Type2Enum<int>
{
static const TypeEnum type = int_type ;
} ;
template <> struct Val::SupportType<int> { typedef long long Type ; } ;
template <> struct Val::SupportType<unsigned> { typedef long long Type ; } ;
template <> struct Val::SupportType<long> { typedef long long Type ; } ;
template <> struct Val::SupportType<unsigned long> { typedef long long Type ; } ;
template <> struct Val::SupportType<short> { typedef long long Type ; } ;
template <> struct Val::SupportType<unsigned short> { typedef long long Type ; } ;
template <>
struct Val::Type2Enum<bool>
{
static const TypeEnum type = bool_type ;
} ;
template <>
struct Val::Type2Enum<double>
{
static const TypeEnum type = double_type ;
} ;
template <>
struct Val::Type2Enum<std::string>
{
static const TypeEnum type = string_type ;
} ;
template <>
struct Val::Type2Enum<Val::Array>
{
static const TypeEnum type = array_type ;
} ;
template <>
struct Val::Type2Enum<Val::Object>
{
static const TypeEnum type = object_type ;
} ;
template <> struct Val::SupportType<bool> { typedef bool Type ; } ;
template <> struct Val::SupportType<double> { typedef double Type ; } ;
template <> struct Val::SupportType<std::string> { typedef std::string Type ; } ;
template <> struct Val::SupportType<const char*> { typedef std::string Type ; } ;
template <> struct Val::SupportType<Val::Array> { typedef Val::Array Type ; } ;
template <> struct Val::SupportType<Val::Object> { typedef Val::Object Type ; } ;
struct Val::Base
{
@ -135,7 +148,7 @@ struct Val::Base
} ;
template <typename T>
struct Val::Impl : public Base
struct Val::Impl : public Base
{
T val ;
Impl( const T& t ) : val(t) {}
@ -151,23 +164,44 @@ struct Val::Impl<void> : public Base
} ;
template <typename T>
Val::Val( const T& t ) :
m_base( new Impl<T>(t) )
Val& Val::Assign( const T& t )
{
m_base.reset( new Impl<typename SupportType<T>::Type>(t) ) ;
return *this ;
}
template <typename T>
const T& Val::As() const
{
const Impl<T> *impl = &dynamic_cast<const Impl<T>&>( *m_base ) ;
return impl->val ;
try
{
const Impl<T> *impl = &dynamic_cast<const Impl<T>&>( *m_base ) ;
return impl->val ;
}
catch ( std::exception& e )
{
TypeEnum dest = Type2Enum<T>::type ;
BOOST_THROW_EXCEPTION(
Error() << SrcType_(Type()) << DestType_(dest)
) ;
}
}
template <typename T>
T& Val::As()
{
Impl<T> *impl = &dynamic_cast<Impl<T>&>( *m_base ) ;
return impl->val ;
try
{
Impl<T> *impl = &dynamic_cast<Impl<T>&>( *m_base ) ;
return impl->val ;
}
catch ( std::exception& e )
{
TypeEnum dest = Type2Enum<T>::type ;
BOOST_THROW_EXCEPTION(
Error() << SrcType_(Type()) << DestType_(dest)
) ;
}
}
template <typename T>
@ -178,3 +212,8 @@ bool Val::Is() const
} // end of namespace
namespace std
{
void swap( gr::Val& v1, gr::Val& v2 ) ;
ostream& operator<<( ostream& os, gr::Val::TypeEnum t ) ;
}

View File

@ -38,14 +38,15 @@ BOOST_AUTO_TEST_CASE( TestSimpleTypes )
BOOST_CHECK( null.Is<void>() ) ;
Val i( 100 ) ;
BOOST_CHECK_EQUAL( i.As<int>(), 100 ) ;
BOOST_CHECK_EQUAL( i.As<long long>(), 100 ) ;
BOOST_CHECK_EQUAL( i.Type(), Val::int_type ) ;
}
BOOST_AUTO_TEST_CASE( TestMap )
{
Val obj ;
Val obj(( Val::Object() )) ;
obj.Add( "key", Val( std::string("value") ) ) ;
BOOST_CHECK_EQUAL( obj["key"].Type(), Val::string_type ) ;
BOOST_CHECK_EQUAL( obj["key"].As<std::string>(), "value" ) ;
}