/* 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. */ #include "Val.hh" #include "JsonWriter.hh" #include "ValVisitor.hh" #include "util/StdStream.hh" #include #include namespace gr { const Val& Val::Null() { static const Val null( null_type ) ; return null ; } Val::Val( ) : m_base( new Impl ) { } Val::Val( TypeEnum type ) { switch ( type ) { case int_type: m_base.reset( new Impl ) ; break ; case bool_type: m_base.reset( new Impl ) ; break ; case double_type: m_base.reset( new Impl ) ; break ; case string_type: m_base.reset( new Impl ) ; break ; case array_type: m_base.reset( new Impl ) ; break ; case object_type: m_base.reset( new Impl ) ; break ; case null_type: default: m_base.reset( new Impl ) ; break ; } } Val::Val( const Val& v ) : m_base( v.m_base->Clone() ) { } Val::~Val() { } void Val::Swap( Val& val ) { std::swap( m_base, val.m_base ) ; } Val& Val::operator=( const Val& val ) { Val tmp(val) ; Swap(tmp) ; return *this ; } Val::TypeEnum Val::Type() const { return m_base->Type() ; } const Val& Val::operator[]( const std::string& key ) const { 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 ; } Val& Val::operator[]( const std::string& key ) { Object& obj = As() ; Object::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 { const Array& ar = As() ; if ( index < ar.size() ) return ar[index] ; // shut off compiler warning BOOST_THROW_EXCEPTION(Error() << OutOfRange_(index)) ; throw ; } std::string Val::Str() const { if ( Type() == int_type ) { char buf[40]; sprintf( buf, "%lld", As() ); return std::string( buf ); } return As() ; } Val::operator std::string() const { return As() ; } int Val::Int() const { if ( Type() == string_type ) return std::atoi( As().c_str() ); return static_cast(As()) ; } unsigned long long Val::U64() const { if ( Type() == string_type ) return strtoull( As().c_str(), NULL, 10 ); return static_cast(As()) ; } double Val::Double() const { if ( Type() == string_type ) return std::atof( As().c_str() ); return As() ; } bool Val::Bool() const { return As() ; } const Val::Array& Val::AsArray() const { return As() ; } Val::Array& Val::AsArray() { return As() ; } const Val::Object& Val::AsObject() const { return As() ; } Val::Object& Val::AsObject() { return As() ; } bool Val::Has( const std::string& key ) const { const Object& obj = As() ; return obj.find(key) != obj.end() ; } bool Val::Del( const std::string& key ) { Object& obj = As() ; return obj.erase(key) > 0 ; } Val& Val::Item( const std::string& key ) { return As()[key]; } bool Val::Get( const std::string& key, Val& val ) const { const Object& obj = As() ; Object::const_iterator i = obj.find(key) ; if ( i != obj.end() ) { val = i->second ; return true ; } else return false ; } void Val::Add( const std::string& key, const Val& value ) { As().insert( std::make_pair(key, value) ) ; } void Val::Set( const std::string& key, const Val& value ) { Object& obj = As(); Object::iterator i = obj.find(key); if (i == obj.end()) obj.insert(std::make_pair(key, value)); else i->second = value; } void Val::Add( const Val& json ) { As().push_back( json ) ; } void Val::Visit( ValVisitor *visitor ) const { switch ( Type() ) { case null_type: visitor->VisitNull() ; break ; case int_type: visitor->Visit( As() ) ; break ; case double_type: visitor->Visit( As() ) ; break ; case string_type: visitor->Visit( As() ) ; break ; case bool_type: visitor->Visit( As() ) ; break ; case object_type: { visitor->StartObject() ; const Object& obj = As() ; for ( Object::const_iterator i = obj.begin() ; i != obj.end() ; ++i ) { visitor->VisitKey( i->first ) ; i->second.Visit( visitor ) ; } visitor->EndObject() ; break ; } case array_type: { visitor->StartArray() ; const Array& arr = As() ; for ( Array::const_iterator i = arr.begin() ; i != arr.end() ; ++i ) i->Visit( visitor ) ; visitor->EndArray() ; break ; } } } void Val::Select( const Object& obj, const std::string& key, std::vector& result ) const { Object::const_iterator i = obj.find(key) ; if ( i != obj.end() ) result.push_back(i->second) ; } /** If \a this is an array of objects, this function returns all values of the objects in the array with the key \a key. If \a this is an object, just return the value with the key \a key. */ std::vector Val::Select( const std::string& key ) const { std::vector result ; if ( Is() ) Select( As(), key, result ) ; else if ( Is() ) { const Array& array = As() ; for ( Array::const_iterator i = array.begin() ; i != array.end() ; ++i ) { if ( i->Is() ) Select( i->As(), key, result ) ; } } return result ; } std::ostream& operator<<( std::ostream& os, const Val& val ) { StdStream ss( os.rdbuf() ) ; JsonWriter wr( &ss ) ; val.Visit( &wr ) ; return os ; } } // 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) ; } }