/* grive: an GPL program to sync a local directory with Google Drive Copyright (C) 2013 Wan Wai Ho This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "util/Exception.hh" #include #include #include #include #include #include namespace gr { class ValVisitor ; 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 ; public : Val() ; Val( const Val& v ) ; explicit Val( TypeEnum type ) ; ~Val() ; static const Val& Null() ; template explicit Val( const T& t ) { Assign(t) ; } template Val& Assign( const T& t ) ; void Swap( Val& val ) ; Val& operator=( const Val& val ) ; template Val& operator=( const T& t ) { return Assign(t) ; } operator std::string() const ; template const T& As() const ; template T& As() ; template bool Is() const ; TypeEnum Type() const ; // shortcuts for As<>() std::string Str() const ; int Int() const ; unsigned long long U64() const ; double Double() const ; bool Bool() const ; const Array& AsArray() const ; Array& AsArray() ; const Object& AsObject() const ; Object& AsObject() ; // shortcuts for objects Val& operator[]( const std::string& key ) ; // get updatable ref or throw const Val& operator[]( const std::string& key ) const ; // get const ref or throw Val& Item( const std::string& key ) ; // insert if not exists and get bool Has( const std::string& key ) const ; // check if exists bool Get( const std::string& key, Val& val ) const ; // get or return false void Add( const std::string& key, const Val& val ) ; // insert or do nothing void Set( const std::string& key, const Val& val ) ; // insert or update bool Del( const std::string& key ); // delete or do nothing // shortcuts for array (and array of objects) const Val& operator[]( std::size_t index ) const ; void Add( const Val& json ) ; std::vector Select( const std::string& key ) const ; friend std::ostream& operator<<( std::ostream& os, const Val& val ) ; void Visit( ValVisitor *visitor ) const ; private : struct Base ; template struct Impl ; std::auto_ptr m_base ; private : void Select( const Object& obj, const std::string& key, std::vector& result ) const ; } ; 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::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::SupportType { typedef long long Type ; } ; template <> struct Val::SupportType { typedef long long 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 { virtual ~Base() {} virtual Base* Clone() const = 0 ; virtual TypeEnum Type() const = 0 ; } ; template struct Val::Impl : public Base { T val ; Impl( ) : val() {} Impl( const T& t ) : val(t) {} Impl* Clone() const { return new Impl(val); } TypeEnum Type() const { return Type2Enum::type ; } } ; template <> struct Val::Impl : public Base { Impl* Clone() const { return new Impl; } TypeEnum Type() const { return null_type ; } } ; template Val& Val::Assign( const T& t ) { m_base.reset( new Impl::Type>(t) ) ; return *this ; } template const T& Val::As() const { try { const Impl *impl = dynamic_cast *>( m_base.get() ) ; return impl->val ; } catch ( std::exception& e ) { TypeEnum dest = Type2Enum::type ; BOOST_THROW_EXCEPTION( Error() << SrcType_(Type()) << DestType_(dest) ) ; } } template T& Val::As() { try { Impl *impl = dynamic_cast *>( m_base.get() ) ; return impl->val ; } catch ( std::exception& e ) { TypeEnum dest = Type2Enum::type ; BOOST_THROW_EXCEPTION( Error() << SrcType_(Type()) << DestType_(dest) ) ; } } template bool Val::Is() const { return Type() == Type2Enum::type ; } } // end of namespace namespace std { void swap( gr::Val& v1, gr::Val& v2 ) ; ostream& operator<<( ostream& os, gr::Val::TypeEnum t ) ; }