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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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