mirror of https://github.com/vitalif/grive2
parent
6ba04dcfba
commit
27817e835f
|
@ -22,9 +22,12 @@
|
|||
|
||||
#include "CommonUri.hh"
|
||||
#include "Feed.hh"
|
||||
#include "protocol/Json.hh"
|
||||
#include "json/Val.hh"
|
||||
#include "util/Exception.hh"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
|
@ -74,8 +77,8 @@ void Drive::NewResource( http::Agent *agent, Feed& items )
|
|||
|
||||
while ( items.Next( agent ) )
|
||||
{
|
||||
std::vector<Json> item_json = items.Content()["items"].AsArray() ;
|
||||
for ( std::vector<Json>::iterator i = item_json.begin() ; i != item_json.end() ; ++i )
|
||||
std::vector<Val> item_json = items.Content()["items"].AsArray() ;
|
||||
for ( std::vector<Val>::iterator i = item_json.begin() ; i != item_json.end() ; ++i )
|
||||
NewResource( *i ) ;
|
||||
}
|
||||
}
|
||||
|
@ -89,16 +92,19 @@ Resource* Drive::NewResource( http::Agent *agent, const std::string& id )
|
|||
return NewResource( feed.Content() ) ;
|
||||
}
|
||||
|
||||
Resource* Drive::NewResource( const Json& item )
|
||||
Resource* Drive::NewResource( const Val& item )
|
||||
{
|
||||
// assume resource is directly under root
|
||||
std::string parent_id = m_root != 0 ? m_root->ID() : "" ;
|
||||
|
||||
Json parents ;
|
||||
Val parents ;
|
||||
if ( item.Get( "parents", parents ) )
|
||||
{
|
||||
std::vector<Val> pids_val = parents.Select( "id" ) ;
|
||||
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
|
||||
if ( !pids.empty() )
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace http
|
|||
class Agent ;
|
||||
}
|
||||
|
||||
class Json ;
|
||||
class Val ;
|
||||
|
||||
namespace v2 {
|
||||
|
||||
|
@ -76,7 +76,7 @@ public :
|
|||
const Resource* Parent( const Resource *child ) const ;
|
||||
|
||||
private :
|
||||
Resource* NewResource( const Json& item ) ;
|
||||
Resource* NewResource( const Val& item ) ;
|
||||
Resource* NewResource( http::Agent *agent, const std::string& id ) ;
|
||||
void NewResource( http::Agent *agent, Feed& items ) ;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "http/Agent.hh"
|
||||
#include "http/Header.hh"
|
||||
#include "protocol/JsonResponse.hh"
|
||||
#include "json/ValResponse.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -31,22 +31,22 @@ Feed::Feed( const std::string& base ) :
|
|||
m_base( base )
|
||||
{
|
||||
// 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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
Json url ;
|
||||
Val url ;
|
||||
if ( !m_content.Get("nextLink", url) )
|
||||
return false ;
|
||||
|
||||
http::JsonResponse out ;
|
||||
http::ValResponse out ;
|
||||
try
|
||||
{
|
||||
agent->Get( url.Str(), &out, http::Header() ) ;
|
||||
|
@ -61,7 +61,7 @@ bool Feed::Next( http::Agent *agent )
|
|||
return true ;
|
||||
}
|
||||
|
||||
Json Feed::Content() const
|
||||
Val Feed::Content() const
|
||||
{
|
||||
return m_content ;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "protocol/Json.hh"
|
||||
#include "json/Val.hh"
|
||||
#include "util/Exception.hh"
|
||||
|
||||
#include <string>
|
||||
|
@ -32,7 +32,7 @@ namespace http
|
|||
class Header ;
|
||||
}
|
||||
|
||||
class Json ;
|
||||
class Val ;
|
||||
|
||||
namespace v2 {
|
||||
|
||||
|
@ -40,7 +40,7 @@ class Feed
|
|||
{
|
||||
public :
|
||||
// exception info
|
||||
typedef boost::error_info<struct DriveFeed, Json> DriveFeed_ ;
|
||||
typedef boost::error_info<struct DriveFeed, Val> DriveFeed_ ;
|
||||
|
||||
public :
|
||||
Feed( const std::string& base ) ;
|
||||
|
@ -49,11 +49,11 @@ public :
|
|||
|
||||
bool Next( http::Agent *agent ) ;
|
||||
|
||||
Json Content() const ;
|
||||
Val Content() const ;
|
||||
|
||||
private :
|
||||
std::string m_base ;
|
||||
Json m_content ;
|
||||
Val m_content ;
|
||||
} ;
|
||||
|
||||
} } // end of namespace gr::v2
|
||||
|
|
|
@ -27,9 +27,30 @@
|
|||
|
||||
namespace gr {
|
||||
|
||||
Val::Val( ) :
|
||||
m_base( new Impl<void> )
|
||||
const Val& Val::Null()
|
||||
{
|
||||
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 ) :
|
||||
|
@ -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 )
|
||||
{
|
||||
StdStream ss( os.rdbuf() ) ;
|
||||
|
|
|
@ -58,8 +58,11 @@ public :
|
|||
public :
|
||||
Val() ;
|
||||
Val( const Val& v ) ;
|
||||
explicit Val( TypeEnum type ) ;
|
||||
~Val() ;
|
||||
|
||||
static const Val& Null() ;
|
||||
|
||||
template <typename T>
|
||||
explicit Val( const T& t )
|
||||
{
|
||||
|
@ -110,19 +113,22 @@ public :
|
|||
void Add( const Val& json ) ;
|
||||
Val FindInArray( const std::string& key, const std::string& value ) 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 ) ;
|
||||
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 ; } ;
|
||||
|
@ -160,6 +166,7 @@ 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 ; }
|
||||
|
|
|
@ -60,37 +60,41 @@ void ValBuilder::VisitNull()
|
|||
void ValBuilder::Build( const Val& t )
|
||||
{
|
||||
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 ) ;
|
||||
}
|
||||
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) ) ;
|
||||
|
||||
else
|
||||
{
|
||||
Val::Object& obj = m_ctx.top().As<Val::Object>() ;
|
||||
obj.insert( std::make_pair( m_key->As<std::string>(), t ) ) ;
|
||||
m_key.reset() ;
|
||||
Val::Object& obj = m_ctx.top().val.As<Val::Object>() ;
|
||||
obj.insert( std::make_pair( m_ctx.top().key.Str(), t ) ) ;
|
||||
m_ctx.top().key = Val::Null() ;
|
||||
}
|
||||
}
|
||||
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 )
|
||||
{
|
||||
m_key.reset( new Val(t) ) ;
|
||||
m_ctx.top().key = t ;
|
||||
}
|
||||
|
||||
void ValBuilder::StartArray()
|
||||
{
|
||||
m_ctx.push( Val( Val::Array() ) ) ;
|
||||
Level l = { Val::Null(), Val(Val::Array()) } ;
|
||||
m_ctx.push(l) ;
|
||||
}
|
||||
|
||||
void ValBuilder::EndArray()
|
||||
|
@ -100,11 +104,13 @@ void ValBuilder::EndArray()
|
|||
|
||||
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
|
||||
Val current ;
|
||||
current.Swap( m_ctx.top() ) ;
|
||||
current.Swap( m_ctx.top().val ) ;
|
||||
m_ctx.pop() ;
|
||||
|
||||
Build(current) ;
|
||||
|
@ -113,7 +119,8 @@ void ValBuilder::End( Val::TypeEnum type )
|
|||
|
||||
void ValBuilder::StartObject()
|
||||
{
|
||||
m_ctx.push( Val( Val::Object() ) ) ;
|
||||
Level l = { Val::Null(), Val( Val::Object() ) } ;
|
||||
m_ctx.push(l) ;
|
||||
}
|
||||
|
||||
void ValBuilder::EndObject()
|
||||
|
@ -124,7 +131,7 @@ void ValBuilder::EndObject()
|
|||
Val ValBuilder::Result() const
|
||||
{
|
||||
assert( m_ctx.size() == 1U ) ;
|
||||
return m_ctx.top() ;
|
||||
return m_ctx.top().val ;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -61,8 +61,13 @@ private :
|
|||
void End( Val::TypeEnum type ) ;
|
||||
|
||||
private :
|
||||
std::stack<Val> m_ctx ;
|
||||
std::auto_ptr<Val> m_key ;
|
||||
struct Level
|
||||
{
|
||||
Val key ;
|
||||
Val val ;
|
||||
} ;
|
||||
|
||||
std::stack<Level> m_ctx ;
|
||||
} ;
|
||||
|
||||
} // end of namespace
|
||||
|
|
Loading…
Reference in New Issue