mirror of https://github.com/vitalif/grive2
235 lines
6.5 KiB
C++
235 lines
6.5 KiB
C++
/*
|
|
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 <cstddef>
|
|
#include <iosfwd>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
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<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 ;
|
|
|
|
public :
|
|
Val() ;
|
|
Val( const Val& v ) ;
|
|
explicit Val( TypeEnum type ) ;
|
|
~Val() ;
|
|
|
|
static const Val& Null() ;
|
|
|
|
template <typename 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 ) ;
|
|
|
|
template <typename T>
|
|
Val& operator=( const T& t )
|
|
{
|
|
return Assign(t) ;
|
|
}
|
|
|
|
operator std::string() const ;
|
|
|
|
template <typename T>
|
|
const T& As() const ;
|
|
|
|
template <typename T>
|
|
T& As() ;
|
|
|
|
template <typename T>
|
|
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<Val> 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 <typename T>
|
|
struct Impl ;
|
|
|
|
std::auto_ptr<Base> m_base ;
|
|
|
|
private :
|
|
void Select( const Object& obj, const std::string& key, std::vector<Val>& result ) const ;
|
|
} ;
|
|
|
|
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::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::SupportType<long long> { typedef long long Type ; } ;
|
|
template <> struct Val::SupportType<unsigned long long> { typedef long long 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
|
|
{
|
|
virtual ~Base() {}
|
|
virtual Base* Clone() const = 0 ;
|
|
virtual TypeEnum Type() const = 0 ;
|
|
} ;
|
|
|
|
template <typename T>
|
|
struct Val::Impl : public Base
|
|
{
|
|
T val ;
|
|
Impl( ) : val() {}
|
|
Impl( const T& t ) : val(t) {}
|
|
Impl<T>* Clone() const { return new Impl<T>(val); }
|
|
TypeEnum Type() const { return Type2Enum<T>::type ; }
|
|
} ;
|
|
|
|
template <>
|
|
struct Val::Impl<void> : public Base
|
|
{
|
|
Impl<void>* Clone() const { return new Impl<void>; }
|
|
TypeEnum Type() const { return null_type ; }
|
|
} ;
|
|
|
|
template <typename 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.get() ) ;
|
|
if ( !impl )
|
|
{
|
|
TypeEnum dest = Type2Enum<T>::type ;
|
|
BOOST_THROW_EXCEPTION(
|
|
Error() << SrcType_( Type() ) << DestType_( dest )
|
|
) ;
|
|
}
|
|
return impl->val ;
|
|
}
|
|
|
|
template <typename T>
|
|
T& Val::As()
|
|
{
|
|
Impl<T> *impl = dynamic_cast<Impl<T> *>( m_base.get() ) ;
|
|
if ( !impl )
|
|
{
|
|
TypeEnum dest = Type2Enum<T>::type ;
|
|
BOOST_THROW_EXCEPTION(
|
|
Error() << SrcType_( Type() ) << DestType_( dest )
|
|
) ;
|
|
}
|
|
return impl->val ;
|
|
}
|
|
|
|
template <typename T>
|
|
bool Val::Is() const
|
|
{
|
|
return Type() == Type2Enum<T>::type ;
|
|
}
|
|
|
|
} // end of namespace
|
|
|
|
namespace std
|
|
{
|
|
void swap( gr::Val& v1, gr::Val& v2 ) ;
|
|
ostream& operator<<( ostream& os, gr::Val::TypeEnum t ) ;
|
|
}
|