using the new Json classes for bgrive

pull/40/head v0.3.0
Nestal Wan 2013-05-03 00:40:04 +08:00
parent 6ba04dcfba
commit 27817e835f
8 changed files with 116 additions and 41 deletions

View File

@ -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() )

View File

@ -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 ) ;

View File

@ -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 ;
}

View File

@ -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

View File

@ -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() ) ;

View File

@ -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 ; }

View File

@ -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

View File

@ -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