Basic single level JSON reading works

This commit is contained in:
Randolph Voorhies
2013-07-08 15:00:25 -07:00
parent ae87460183
commit f0216012be
2 changed files with 174 additions and 144 deletions

View File

@@ -35,6 +35,7 @@
#include <cereal/external/rapidjson/prettywriter.h>
#include <cereal/external/rapidjson/genericstream.h>
#include <cereal/external/rapidjson/reader.h>
#include <cereal/external/rapidjson/document.h>
#include <cereal/external/base64.hpp>
#include <sstream>
@@ -74,16 +75,16 @@ namespace cereal
itsWriter.EndObject();
}
void saveValue(bool b) { itsWriter.Bool(b); }
void saveValue(int i) { itsWriter.Int(i); }
void saveValue(unsigned u) { itsWriter.Uint(u); }
void saveValue(int64_t i64) { itsWriter.Int64(i64); }
void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
void saveValue(double d) { itsWriter.Double(d); }
void saveValue(std::string const & s) { rawString(s); }
void saveValue(char const * s) { itsWriter.String(s); }
void saveNull() { itsWriter.Null(); }
void saveValue(bool b) { itsWriter.Bool(b); }
void saveValue(int i) { itsWriter.Int(i); }
void saveValue(unsigned u) { itsWriter.Uint(u); }
void saveValue(int64_t i64) { itsWriter.Int64(i64); }
void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
void saveValue(double d) { itsWriter.Double(d); }
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), s.size()); }
void saveValue(char const * s) { itsWriter.String(s); }
//! Write the name of the upcoming node
void writeName()
{
if(itsNextName == nullptr)
@@ -98,11 +99,6 @@ namespace cereal
}
}
void rawString(std::string const & s)
{
itsWriter.String(s.c_str(), s.size());
}
//! Creates a new node that is a child of the node at the top of the stack
/*! Nodes will be given a name that has either been pre-set by a name value pair,
or generated based upon a counter unique to the parent node.
@@ -163,47 +159,107 @@ namespace cereal
\ingroup Archives */
class JSONInputArchive : public InputArchive<JSONInputArchive>
{
//typedef rapidjson::GenericWriteStream WriteStream;
//typedef rapidjson::PrettyWriter<WriteStream> JSONWriter;
typedef rapidjson::GenericReadStream ReadStream;
typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
typedef JSONValue::ConstMemberIterator JSONIterator;
public:
//! Construct, outputting to the provided stream
/*! @param stream The stream to output to. Can be a stringstream, a file stream, or
even cout! */
JSONInputArchive(std::istream & ) :
InputArchive<JSONInputArchive>(this)
JSONInputArchive(std::istream & is) :
InputArchive<JSONInputArchive>(this),
itsReadStream(is)
{
itsDocument.ParseStream<0>(itsReadStream);
itsValueStack.push(itsDocument.MemberBegin());
}
void setNextName(char const * name)
{
itsNextName = name;
}
void startNode()
{
itsValueStack.push(itsValueStack.top()->value.MemberBegin());
}
void finishNode()
{
itsValueStack.pop();
++itsValueStack.top();
}
void loadValue(bool & val) { val = itsValueStack.top()->value.GetBool(); ++itsValueStack.top(); }
void loadValue(int & val) { val = itsValueStack.top()->value.GetInt(); ++itsValueStack.top(); }
void loadValue(unsigned & val) { val = itsValueStack.top()->value.GetUint(); ++itsValueStack.top(); }
void loadValue(int64_t & val) { val = itsValueStack.top()->value.GetInt64(); ++itsValueStack.top(); }
void loadValue(uint64_t & val) { val = itsValueStack.top()->value.GetUint64(); ++itsValueStack.top(); }
void loadValue(double & val) { val = itsValueStack.top()->value.GetDouble(); ++itsValueStack.top(); }
void loadValue(std::string & val) { val = itsValueStack.top()->value.GetString(); ++itsValueStack.top(); }
private:
char const * itsNextName;
ReadStream itsReadStream; //!< Rapidjson write stream
std::stack<JSONIterator> itsValueStack; //!< Stack of values
rapidjson::Document itsDocument; //!< Rapidjson document
};
// ######################################################################
// JSONArchive prologue and epilogue functions
// ######################################################################
// ######################################################################
//! Prologue for NVPs for JSON archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T>
void prologue( JSONOutputArchive &, NameValuePair<T> const & )
{ }
//! Prologue for NVPs for JSON archives
template <class T>
void prologue( JSONInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
//! Epilogue for NVPs for JSON archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T>
void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
{ }
//! Epilogue for NVPs for JSON archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T>
void epilogue( JSONInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
//! Prologue for SizeTags for JSON archives
/*! SizeTags are strictly ignored for JSON */
template <class T>
void prologue( JSONOutputArchive &, SizeTag<T> const & )
{ }
//! Prologue for SizeTags for JSON archives
template <class T>
void prologue( JSONInputArchive &, SizeTag<T> const & )
{ }
// ######################################################################
//! Epilogue for SizeTags for JSON archives
/*! SizeTags are strictly ignored for JSON */
template <class T>
void epilogue( JSONOutputArchive &, SizeTag<T> const & )
{ }
//! Epilogue for SizeTags for JSON archives
template <class T>
void epilogue( JSONInputArchive &, SizeTag<T> const & )
{ }
// ######################################################################
//! Prologue for all other types for JSON archives
/*! Starts a new node, named either automatically or by some NVP,
that may be given data by the type about to be archived */
@@ -214,6 +270,15 @@ namespace cereal
ar.startNode();
}
//! Prologue for all other types for JSON archives
template <class T>
typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
prologue( JSONInputArchive & ar, T const & data )
{
ar.startNode();
}
// ######################################################################
//! Epilogue for all other types other for JSON archives
/*! Finishes the node created in the prologue */
template <class T>
@@ -223,6 +288,16 @@ namespace cereal
ar.finishNode();
}
//! Epilogue for all other types other for JSON archives
template <class T>
typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
epilogue( JSONInputArchive & ar, T const & data )
{
ar.finishNode();
}
// ######################################################################
//! Prologue for arithmetic types for JSON archives
template <class T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
prologue( JSONOutputArchive & ar, T const & data )
@@ -230,23 +305,52 @@ namespace cereal
ar.writeName();
}
//! Prologue for arithmetic types for JSON archives
template <class T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
epilogue( JSONOutputArchive & ar, T const & data )
prologue( JSONInputArchive & ar, T const & data )
{
}
// ######################################################################
//! Epilogue for arithmetic types for JSON archives
template <class T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
epilogue( JSONOutputArchive & ar, T const & data )
{ }
//! Epilogue for arithmetic types for JSON archives
template <class T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
epilogue( JSONInputArchive & ar, T const & data )
{ }
// ######################################################################
//! Prologue for strings for JSON archives
template<class CharT, class Traits, class Alloc> inline
void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{
ar.writeName();
}
//! Prologue for strings for JSON archives
template<class CharT, class Traits, class Alloc> inline
void epilogue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
void prologue(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{
}
// ######################################################################
//! Epilogue for strings for JSON archives
template<class CharT, class Traits, class Alloc> inline
void epilogue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{ }
//! Epilogue for strings for JSON archives
template<class CharT, class Traits, class Alloc> inline
void epilogue(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{ }
// ######################################################################
// Common JSONArchive serialization functions
// ######################################################################
@@ -274,6 +378,14 @@ namespace cereal
ar.saveValue( t );
}
//! Loading arithmetic from JSON
template<class T> inline
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
load(JSONInputArchive & ar, T & t)
{
ar.loadValue( t );
}
//! saving string to JSON
template<class CharT, class Traits, class Alloc> inline
void save(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)

View File

@@ -37,6 +37,8 @@
#include <cereal/types/array.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/external/rapidjson/filestream.h>
#include <cxxabi.h>
#include <sstream>
#include <fstream>
@@ -44,48 +46,6 @@
#include <complex>
#include <iostream>
class Base
{
private:
friend class cereal::access;
template <class Archive>
void serialize( Archive & ar )
{
std::cout << "Base serialize" << std::endl;
ar( x );
}
int x;
};
class Derived : public Base
{
public:
template <class Archive>
void save( Archive & ar ) const
{
ar( cereal::virtual_base_class<Base>(this) );
std::cout << "Derived save" << std::endl;
ar( y );
}
template <class Archive>
void load( Archive & ar )
{
ar( cereal::virtual_base_class<Base>(this) );
std::cout << "Derived load" << std::endl;
ar( y );
}
int y;
};
namespace cereal
{
template <class Archive> struct specialize<Archive, Derived, cereal::specialization::member_load_save> {};
//template <class Archive> struct specialize<Archive, Derived, cereal::specialization::non_member_load_save> {};
}
// ###################################
struct Test1
{
@@ -209,52 +169,6 @@ struct Everything
}
};
struct EmptyStruct
{
template<class Archive>
void serialize(Archive & ar)
{
std::cout << "Side effects!" << std::endl;
};
};
struct NonEmptyStruct
{
int x, y, z;
};
struct NoDefaultCtor
{
NoDefaultCtor() = delete;
NoDefaultCtor(int x) : y(x)
{ }
int y;
template <class Archive>
void serialize( Archive & archive )
{
}
//template <class Archive>
//static NoDefaultCtor * load_and_allocate( Archive & ar )
//{
// return new NoDefaultCtor(5);
//}
};
namespace cereal
{
template <>
struct LoadAndAllocate<NoDefaultCtor>
{
template <class Archive>
static NoDefaultCtor * load_and_allocate( Archive & ar )
{
return new NoDefaultCtor(5);
}
};
}
struct SubFixture
{
@@ -302,53 +216,57 @@ struct Fixture
}
};
void foo(int t)
{
std::cout << "int" << std::endl;
}
void foo(unsigned int t)
{
std::cout << "unsigned int" << std::endl;
}
// ######################################################################
int main()
{
std::cout << std::boolalpha << std::endl;
{
cereal::JSONOutputArchive oar( std::cout );
std::ofstream os("file.json");
cereal::JSONOutputArchive oar( os );
Fixture fixture;
oar( CEREAL_NVP(fixture) );
std::vector<double> vecD = {1.23, 4.56, 7,89};
oar( CEREAL_NVP(vecD) );
bool b = true;
oar( cereal::make_nvp("coolean boolean", b) );
std::shared_ptr<std::string> sPtr = std::make_shared<std::string>("i'm a shared pointer");
oar( CEREAL_NVP(sPtr) );
int xxx[] = {-1, 95, 3};
oar.saveBinaryValue( xxx, sizeof(int)*3, "xxxbinary" );
oar.saveBinaryValue( xxx, sizeof(int)*3 );
int x = 10;
double y = 99;
oar(CEREAL_NVP(x));
oar(CEREAL_NVP(y));
}
std::cout << std::endl;
{
cereal::JSONInputArchive iar( std::cin );
Fixture fixture; fixture.change();
//iar( fixture );
std::vector<double> vecD;
//iar( vecD );
std::ifstream is("file.json");
std::string str((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
std::cout << "---------------------" << std::endl << str << std::endl << "---------------------" << std::endl;
}
{
std::ifstream is("file.json");
cereal::JSONInputArchive iar( is );
int x;
double y;
iar(CEREAL_NVP(x));
iar(CEREAL_NVP(y));
std::cout << x << " " << y << std::endl;
}
//{
// std::ifstream is("file.json");
// rapidjson::GenericReadStream itsReadStream(is);
// rapidjson::Document itsDocument;
// itsDocument.ParseStream<0>(itsReadStream);
//
// //FILE * f = std::fopen("file.json", "r");
// //rapidjson::FileStream filestream(f);
// //rapidjson::Document itsDocument;
// //itsDocument.ParseStream<0>(filestream);
// std::cout << itsDocument.IsObject() << std::endl;
// std::cout << itsDocument.HasMember("x") << std::endl;
// auto it = itsDocument.MemberBegin();
// std::cout << it->name.GetString() << std::endl;
// it->value.GetInt();
//}
return 0;
}