mirror of https://github.com/vitalif/grive2
parent
6ba04dcfba
commit
27817e835f
|
@ -22,9 +22,12 @@
|
||||||
|
|
||||||
#include "CommonUri.hh"
|
#include "CommonUri.hh"
|
||||||
#include "Feed.hh"
|
#include "Feed.hh"
|
||||||
#include "protocol/Json.hh"
|
#include "json/Val.hh"
|
||||||
#include "util/Exception.hh"
|
#include "util/Exception.hh"
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
@ -74,8 +77,8 @@ void Drive::NewResource( http::Agent *agent, Feed& items )
|
||||||
|
|
||||||
while ( items.Next( agent ) )
|
while ( items.Next( agent ) )
|
||||||
{
|
{
|
||||||
std::vector<Json> item_json = items.Content()["items"].AsArray() ;
|
std::vector<Val> item_json = items.Content()["items"].AsArray() ;
|
||||||
for ( std::vector<Json>::iterator i = item_json.begin() ; i != item_json.end() ; ++i )
|
for ( std::vector<Val>::iterator i = item_json.begin() ; i != item_json.end() ; ++i )
|
||||||
NewResource( *i ) ;
|
NewResource( *i ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,16 +92,19 @@ Resource* Drive::NewResource( http::Agent *agent, const std::string& id )
|
||||||
return NewResource( feed.Content() ) ;
|
return NewResource( feed.Content() ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource* Drive::NewResource( const Json& item )
|
Resource* Drive::NewResource( const Val& item )
|
||||||
{
|
{
|
||||||
// assume resource is directly under root
|
// assume resource is directly under root
|
||||||
std::string parent_id = m_root != 0 ? m_root->ID() : "" ;
|
std::string parent_id = m_root != 0 ? m_root->ID() : "" ;
|
||||||
|
|
||||||
Json parents ;
|
Val parents ;
|
||||||
if ( item.Get( "parents", parents ) )
|
if ( item.Get( "parents", parents ) )
|
||||||
{
|
{
|
||||||
|
std::vector<Val> pids_val = parents.Select( "id" ) ;
|
||||||
std::vector<std::string> pids ;
|
std::vector<std::string> pids ;
|
||||||
parents.Select<std::string>( "id", std::back_inserter(pids) ) ;
|
std::transform( pids_val.begin(), pids_val.end(),
|
||||||
|
std::back_inserter( pids ),
|
||||||
|
boost::bind( &Val::Str, _1 ) ) ;
|
||||||
|
|
||||||
// only the first parent counts
|
// only the first parent counts
|
||||||
if ( !pids.empty() )
|
if ( !pids.empty() )
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace http
|
||||||
class Agent ;
|
class Agent ;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Json ;
|
class Val ;
|
||||||
|
|
||||||
namespace v2 {
|
namespace v2 {
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public :
|
||||||
const Resource* Parent( const Resource *child ) const ;
|
const Resource* Parent( const Resource *child ) const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
Resource* NewResource( const Json& item ) ;
|
Resource* NewResource( const Val& item ) ;
|
||||||
Resource* NewResource( http::Agent *agent, const std::string& id ) ;
|
Resource* NewResource( http::Agent *agent, const std::string& id ) ;
|
||||||
void NewResource( http::Agent *agent, Feed& items ) ;
|
void NewResource( http::Agent *agent, Feed& items ) ;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include "http/Agent.hh"
|
#include "http/Agent.hh"
|
||||||
#include "http/Header.hh"
|
#include "http/Header.hh"
|
||||||
#include "protocol/JsonResponse.hh"
|
#include "json/ValResponse.hh"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -31,22 +31,22 @@ Feed::Feed( const std::string& base ) :
|
||||||
m_base( base )
|
m_base( base )
|
||||||
{
|
{
|
||||||
// Next() will grab this link
|
// Next() will grab this link
|
||||||
m_content.Add( "nextLink", Json(base) ) ;
|
m_content.Add( "nextLink", Val(base) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::Query( const std::string& field, const std::string& value )
|
void Feed::Query( const std::string& field, const std::string& value )
|
||||||
{
|
{
|
||||||
std::string url = m_content["nextLink"].Str() ;
|
std::string url = m_content["nextLink"].Str() ;
|
||||||
m_content.Add( "nextLink", Json( url + "?q=" + field + "+%3d+%27" + value + "%27" ) ) ;
|
m_content.Add( "nextLink", Val( url + "?q=" + field + "+%3d+%27" + value + "%27" ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Feed::Next( http::Agent *agent )
|
bool Feed::Next( http::Agent *agent )
|
||||||
{
|
{
|
||||||
Json url ;
|
Val url ;
|
||||||
if ( !m_content.Get("nextLink", url) )
|
if ( !m_content.Get("nextLink", url) )
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
http::JsonResponse out ;
|
http::ValResponse out ;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
agent->Get( url.Str(), &out, http::Header() ) ;
|
agent->Get( url.Str(), &out, http::Header() ) ;
|
||||||
|
@ -61,7 +61,7 @@ bool Feed::Next( http::Agent *agent )
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json Feed::Content() const
|
Val Feed::Content() const
|
||||||
{
|
{
|
||||||
return m_content ;
|
return m_content ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "protocol/Json.hh"
|
#include "json/Val.hh"
|
||||||
#include "util/Exception.hh"
|
#include "util/Exception.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -32,7 +32,7 @@ namespace http
|
||||||
class Header ;
|
class Header ;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Json ;
|
class Val ;
|
||||||
|
|
||||||
namespace v2 {
|
namespace v2 {
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class Feed
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
// exception info
|
// exception info
|
||||||
typedef boost::error_info<struct DriveFeed, Json> DriveFeed_ ;
|
typedef boost::error_info<struct DriveFeed, Val> DriveFeed_ ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
Feed( const std::string& base ) ;
|
Feed( const std::string& base ) ;
|
||||||
|
@ -49,11 +49,11 @@ public :
|
||||||
|
|
||||||
bool Next( http::Agent *agent ) ;
|
bool Next( http::Agent *agent ) ;
|
||||||
|
|
||||||
Json Content() const ;
|
Val Content() const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
std::string m_base ;
|
std::string m_base ;
|
||||||
Json m_content ;
|
Val m_content ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
} } // end of namespace gr::v2
|
} } // end of namespace gr::v2
|
||||||
|
|
|
@ -27,9 +27,30 @@
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
Val::Val( ) :
|
const Val& Val::Null()
|
||||||
m_base( new Impl<void> )
|
|
||||||
{
|
{
|
||||||
|
static const Val null( null_type ) ;
|
||||||
|
return null ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Val::Val( ) :
|
||||||
|
m_base( new Impl<Object> )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Val::Val( TypeEnum type )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case int_type: m_base.reset( new Impl<long long> ) ; break ;
|
||||||
|
case bool_type: m_base.reset( new Impl<bool> ) ; break ;
|
||||||
|
case double_type: m_base.reset( new Impl<double> ) ; break ;
|
||||||
|
case string_type: m_base.reset( new Impl<std::string> ) ; break ;
|
||||||
|
case array_type: m_base.reset( new Impl<Array> ) ; break ;
|
||||||
|
case object_type: m_base.reset( new Impl<Object> ) ; break ;
|
||||||
|
case null_type:
|
||||||
|
default: m_base.reset( new Impl<void> ) ; break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Val::Val( const Val& v ) :
|
Val::Val( const Val& v ) :
|
||||||
|
@ -174,6 +195,35 @@ void Val::Visit( ValVisitor *visitor ) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Val::Select( const Object& obj, const std::string& key, std::vector<Val>& 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> Val::Select( const std::string& key ) const
|
||||||
|
{
|
||||||
|
std::vector<Val> result ;
|
||||||
|
if ( Is<Object>() )
|
||||||
|
Select( As<Object>(), key, result ) ;
|
||||||
|
|
||||||
|
else if ( Is<Array>() )
|
||||||
|
{
|
||||||
|
const Array& array = As<Array>() ;
|
||||||
|
for ( Array::const_iterator i = array.begin() ; i != array.end() ; ++i )
|
||||||
|
{
|
||||||
|
if ( i->Is<Object>() )
|
||||||
|
Select( i->As<Object>(), key, result ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result ;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<( std::ostream& os, const Val& val )
|
std::ostream& operator<<( std::ostream& os, const Val& val )
|
||||||
{
|
{
|
||||||
StdStream ss( os.rdbuf() ) ;
|
StdStream ss( os.rdbuf() ) ;
|
||||||
|
|
|
@ -58,8 +58,11 @@ public :
|
||||||
public :
|
public :
|
||||||
Val() ;
|
Val() ;
|
||||||
Val( const Val& v ) ;
|
Val( const Val& v ) ;
|
||||||
|
explicit Val( TypeEnum type ) ;
|
||||||
~Val() ;
|
~Val() ;
|
||||||
|
|
||||||
|
static const Val& Null() ;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit Val( const T& t )
|
explicit Val( const T& t )
|
||||||
{
|
{
|
||||||
|
@ -110,19 +113,22 @@ public :
|
||||||
void Add( const Val& json ) ;
|
void Add( const Val& json ) ;
|
||||||
Val FindInArray( const std::string& key, const std::string& value ) const ;
|
Val FindInArray( const std::string& key, const std::string& value ) const ;
|
||||||
bool FindInArray( const std::string& key, const std::string& value, Val& result ) const ;
|
bool FindInArray( const std::string& key, const std::string& value, Val& result ) const ;
|
||||||
|
|
||||||
|
std::vector<Val> Select( const std::string& key ) const ;
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream& os, const Val& val ) ;
|
friend std::ostream& operator<<( std::ostream& os, const Val& val ) ;
|
||||||
void Visit( ValVisitor *visitor ) const ;
|
void Visit( ValVisitor *visitor ) const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
struct Base ;
|
struct Base ;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Impl ;
|
struct Impl ;
|
||||||
|
|
||||||
std::auto_ptr<Base> m_base ;
|
std::auto_ptr<Base> m_base ;
|
||||||
|
|
||||||
private :
|
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<void> { static const TypeEnum type = null_type ; } ;
|
||||||
|
@ -160,6 +166,7 @@ template <typename T>
|
||||||
struct Val::Impl : public Base
|
struct Val::Impl : public Base
|
||||||
{
|
{
|
||||||
T val ;
|
T val ;
|
||||||
|
Impl( ) : val() {}
|
||||||
Impl( const T& t ) : val(t) {}
|
Impl( const T& t ) : val(t) {}
|
||||||
Impl<T>* Clone() const { return new Impl<T>(val); }
|
Impl<T>* Clone() const { return new Impl<T>(val); }
|
||||||
TypeEnum Type() const { return Type2Enum<T>::type ; }
|
TypeEnum Type() const { return Type2Enum<T>::type ; }
|
||||||
|
|
|
@ -60,37 +60,41 @@ void ValBuilder::VisitNull()
|
||||||
void ValBuilder::Build( const Val& t )
|
void ValBuilder::Build( const Val& t )
|
||||||
{
|
{
|
||||||
if ( m_ctx.empty() )
|
if ( m_ctx.empty() )
|
||||||
m_ctx.push( t ) ;
|
|
||||||
|
|
||||||
else if ( m_ctx.top().Is<Val::Array>() )
|
|
||||||
{
|
{
|
||||||
Val::Array& ar = m_ctx.top().As<Val::Array>() ;
|
Level l = { Val::Null(), t } ;
|
||||||
|
m_ctx.push( l ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( m_ctx.top().val.Is<Val::Array>() )
|
||||||
|
{
|
||||||
|
Val::Array& ar = m_ctx.top().val.As<Val::Array>() ;
|
||||||
ar.push_back( t ) ;
|
ar.push_back( t ) ;
|
||||||
}
|
}
|
||||||
else if ( m_ctx.top().Is<Val::Object>() )
|
else if ( m_ctx.top().val.Is<Val::Object>() )
|
||||||
{
|
{
|
||||||
if ( m_key.get() == 0 )
|
if ( !m_ctx.top().key.Is<std::string>() )
|
||||||
BOOST_THROW_EXCEPTION( Error() << NoKey_(t) ) ;
|
BOOST_THROW_EXCEPTION( Error() << NoKey_(t) ) ;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Val::Object& obj = m_ctx.top().As<Val::Object>() ;
|
Val::Object& obj = m_ctx.top().val.As<Val::Object>() ;
|
||||||
obj.insert( std::make_pair( m_key->As<std::string>(), t ) ) ;
|
obj.insert( std::make_pair( m_ctx.top().key.Str(), t ) ) ;
|
||||||
m_key.reset() ;
|
m_ctx.top().key = Val::Null() ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
BOOST_THROW_EXCEPTION( Error() << Unexpected_(m_ctx.top()) ) ;
|
BOOST_THROW_EXCEPTION( Error() << Unexpected_(m_ctx.top().val) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValBuilder::VisitKey( const std::string& t )
|
void ValBuilder::VisitKey( const std::string& t )
|
||||||
{
|
{
|
||||||
m_key.reset( new Val(t) ) ;
|
m_ctx.top().key = t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValBuilder::StartArray()
|
void ValBuilder::StartArray()
|
||||||
{
|
{
|
||||||
m_ctx.push( Val( Val::Array() ) ) ;
|
Level l = { Val::Null(), Val(Val::Array()) } ;
|
||||||
|
m_ctx.push(l) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValBuilder::EndArray()
|
void ValBuilder::EndArray()
|
||||||
|
@ -100,11 +104,13 @@ void ValBuilder::EndArray()
|
||||||
|
|
||||||
void ValBuilder::End( Val::TypeEnum type )
|
void ValBuilder::End( Val::TypeEnum type )
|
||||||
{
|
{
|
||||||
if ( m_ctx.top().Type() == type )
|
if ( m_ctx.top().val.Type() == type )
|
||||||
{
|
{
|
||||||
|
assert( m_ctx.top().key.Is<void>() ) ;
|
||||||
|
|
||||||
// get top Val from stack
|
// get top Val from stack
|
||||||
Val current ;
|
Val current ;
|
||||||
current.Swap( m_ctx.top() ) ;
|
current.Swap( m_ctx.top().val ) ;
|
||||||
m_ctx.pop() ;
|
m_ctx.pop() ;
|
||||||
|
|
||||||
Build(current) ;
|
Build(current) ;
|
||||||
|
@ -113,7 +119,8 @@ void ValBuilder::End( Val::TypeEnum type )
|
||||||
|
|
||||||
void ValBuilder::StartObject()
|
void ValBuilder::StartObject()
|
||||||
{
|
{
|
||||||
m_ctx.push( Val( Val::Object() ) ) ;
|
Level l = { Val::Null(), Val( Val::Object() ) } ;
|
||||||
|
m_ctx.push(l) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValBuilder::EndObject()
|
void ValBuilder::EndObject()
|
||||||
|
@ -124,7 +131,7 @@ void ValBuilder::EndObject()
|
||||||
Val ValBuilder::Result() const
|
Val ValBuilder::Result() const
|
||||||
{
|
{
|
||||||
assert( m_ctx.size() == 1U ) ;
|
assert( m_ctx.size() == 1U ) ;
|
||||||
return m_ctx.top() ;
|
return m_ctx.top().val ;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
|
@ -61,8 +61,13 @@ private :
|
||||||
void End( Val::TypeEnum type ) ;
|
void End( Val::TypeEnum type ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
std::stack<Val> m_ctx ;
|
struct Level
|
||||||
std::auto_ptr<Val> m_key ;
|
{
|
||||||
|
Val key ;
|
||||||
|
Val val ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
std::stack<Level> m_ctx ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
Loading…
Reference in New Issue