diff --git a/libgrive/src/drive2/Val.cc b/libgrive/src/drive2/Val.cc index 9c99c20..a36512b 100644 --- a/libgrive/src/drive2/Val.cc +++ b/libgrive/src/drive2/Val.cc @@ -20,6 +20,8 @@ #include "Val.hh" +#include + 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::const_iterator i = obj.find(key) ; - return i != obj.end() ? i->second : null ; - } - else - return null ; + const Object& obj = As() ; + 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().at(index) : null ; + const Array& ar = As() ; + 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().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(t) ; + } +} diff --git a/libgrive/src/drive2/Val.hh b/libgrive/src/drive2/Val.hh index 9daa4d2..1fae9d5 100644 --- a/libgrive/src/drive2/Val.hh +++ b/libgrive/src/drive2/Val.hh @@ -20,11 +20,14 @@ #pragma once +#include "util/Exception.hh" + #include #include #include #include #include +#include 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 SrcType_ ; + typedef boost::error_info DestType_ ; + typedef boost::error_info NoKey_ ; + typedef boost::error_info OutOfRange_ ; + private : template struct Type2Enum ; + template + struct SupportType ; + +public : typedef std::vector Array ; typedef std::map Object ; @@ -46,8 +59,28 @@ public : ~Val() ; template - Val( const T& t ) ; + explicit Val( const T& t ) + { + Assign(t) ; + } + + template + Val& Assign( const T& t ) ; + void Swap( Val& val ) ; + Val& operator=( const Val& val ) + { + Val tmp(val) ; + Swap(tmp) ; + return *this ; + } + + template + Val& operator=( const T& t ) + { + return Assign(t) ; + } + template const T& As() const ; @@ -85,47 +118,27 @@ private : static int EndArray( void *ctx ) ; } ; -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = null_type ; -} ; +template <> struct Val::Type2Enum { static const TypeEnum type = null_type ; } ; +template <> struct Val::Type2Enum { static const TypeEnum type = int_type ; } ; +template <> struct Val::Type2Enum { static const TypeEnum type = bool_type ; } ; +template <> struct Val::Type2Enum { static const TypeEnum type = double_type ;} ; +template <> struct Val::Type2Enum { static const TypeEnum type = string_type ; } ; +template <> struct Val::Type2Enum { static const TypeEnum type = array_type ; } ; +template <> struct Val::Type2Enum { static const TypeEnum type = object_type ; } ; -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = int_type ; -} ; +template <> struct Val::SupportType { typedef long long Type ; } ; +template <> struct Val::SupportType { typedef long long Type ; } ; +template <> struct Val::SupportType { typedef long long Type ; } ; +template <> struct Val::SupportType { typedef long long Type ; } ; +template <> struct Val::SupportType { typedef long long Type ; } ; +template <> struct Val::SupportType { typedef long long Type ; } ; -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = bool_type ; -} ; - -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = double_type ; -} ; - -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = string_type ; -} ; - -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = array_type ; -} ; - -template <> -struct Val::Type2Enum -{ - static const TypeEnum type = object_type ; -} ; +template <> struct Val::SupportType { typedef bool Type ; } ; +template <> struct Val::SupportType { typedef double Type ; } ; +template <> struct Val::SupportType { typedef std::string Type ; } ; +template <> struct Val::SupportType { typedef std::string Type ; } ; +template <> struct Val::SupportType { typedef Val::Array Type ; } ; +template <> struct Val::SupportType { typedef Val::Object Type ; } ; struct Val::Base { @@ -135,7 +148,7 @@ struct Val::Base } ; template -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 : public Base } ; template -Val::Val( const T& t ) : - m_base( new Impl(t) ) +Val& Val::Assign( const T& t ) { + m_base.reset( new Impl::Type>(t) ) ; + return *this ; } template const T& Val::As() const { - const Impl *impl = &dynamic_cast&>( *m_base ) ; - return impl->val ; + try + { + const Impl *impl = &dynamic_cast&>( *m_base ) ; + return impl->val ; + } + catch ( std::exception& e ) + { + TypeEnum dest = Type2Enum::type ; + BOOST_THROW_EXCEPTION( + Error() << SrcType_(Type()) << DestType_(dest) + ) ; + } } template T& Val::As() { - Impl *impl = &dynamic_cast&>( *m_base ) ; - return impl->val ; + try + { + Impl *impl = &dynamic_cast&>( *m_base ) ; + return impl->val ; + } + catch ( std::exception& e ) + { + TypeEnum dest = Type2Enum::type ; + BOOST_THROW_EXCEPTION( + Error() << SrcType_(Type()) << DestType_(dest) + ) ; + } } template @@ -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 ) ; +} diff --git a/libgrive/test/btest/ValTest.cc b/libgrive/test/btest/ValTest.cc index aecb0a1..cf4d49f 100644 --- a/libgrive/test/btest/ValTest.cc +++ b/libgrive/test/btest/ValTest.cc @@ -38,14 +38,15 @@ BOOST_AUTO_TEST_CASE( TestSimpleTypes ) BOOST_CHECK( null.Is() ) ; Val i( 100 ) ; - BOOST_CHECK_EQUAL( i.As(), 100 ) ; + BOOST_CHECK_EQUAL( i.As(), 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(), "value" ) ; }