json.hpp
Go to the documentation of this file.
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_ARCHIVES_JSON_HPP_
#define CEREAL_ARCHIVES_JSON_HPP_
#include <cereal/cereal.hpp>
#include <cereal/details/util.hpp>
namespace cereal
{
struct RapidJSONException : Exception
{ RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
}
// Override rapidjson assertions to throw exceptions by default
#ifndef RAPIDJSON_ASSERT
#define RAPIDJSON_ASSERT(x) if(!(x)){ \
throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
#endif // RAPIDJSON_ASSERT
#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 <limits>
#include <sstream>
#include <stack>
#include <vector>
#include <string>
namespace cereal
{
// ######################################################################
class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
{
enum class NodeType { StartObject, InObject, StartArray, InArray };
typedef rapidjson::GenericWriteStream WriteStream;
typedef rapidjson::PrettyWriter<WriteStream> JSONWriter;
public:
class Options
{
public:
static Options Default(){ return Options(); }
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, IndentChar::space, 0 ); }
enum class IndentChar : char
{
space = ' ',
tab = '\t',
newline = '\n',
carriage_return = '\r'
};
explicit Options( int precision = std::numeric_limits<double>::max_digits10,
IndentChar indentChar = IndentChar::space,
unsigned int indentLength = 4 ) :
itsPrecision( precision ),
itsIndentChar( static_cast<char>(indentChar) ),
itsIndentLength( indentLength ) { }
private:
friend class JSONOutputArchive;
int itsPrecision;
char itsIndentChar;
unsigned int itsIndentLength;
};
JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
OutputArchive<JSONOutputArchive>(this),
itsWriteStream(stream),
itsWriter(itsWriteStream, options.itsPrecision),
itsNextName(nullptr)
{
itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
itsNameCounter.push(0);
itsNodeStack.push(NodeType::StartObject);
}
~JSONOutputArchive()
{
if (itsNodeStack.top() == NodeType::InObject)
itsWriter.EndObject();
}
void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
{
setNextName( name );
writeName();
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
saveValue( base64string );
};
void startNode()
{
writeName();
itsNodeStack.push(NodeType::StartObject);
itsNameCounter.push(0);
}
void finishNode()
{
// if we ended up serializing an empty object or array, writeName
// will never have been called - so start and then immediately end
// the object/array.
//
// We'll also end any object/arrays we happen to be in
switch(itsNodeStack.top())
{
case NodeType::StartArray:
itsWriter.StartArray();
case NodeType::InArray:
itsWriter.EndArray();
break;
case NodeType::StartObject:
itsWriter.StartObject();
case NodeType::InObject:
itsWriter.EndObject();
break;
}
itsNodeStack.pop();
itsNameCounter.pop();
}
void setNextName( const char * name )
{
itsNextName = name;
}
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(), static_cast<rapidjson::SizeType>( s.size() )); }
void saveValue(char const * s) { itsWriter.String(s); }
private:
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
// special overloads to handle these cases.
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
std::is_signed<T>::value> = traits::sfinae> inline
void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
std::is_signed<T>::value> = traits::sfinae> inline
void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
std::is_unsigned<T>::value> = traits::sfinae> inline
void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
std::is_unsigned<T>::value> = traits::sfinae> inline
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
public:
#ifdef _MSC_VER
void saveValue( unsigned long lu ){ saveLong( lu ); };
#else // _MSC_VER
template <class T, traits::EnableIf<std::is_same<T, long>::value,
!std::is_same<T, std::int32_t>::value,
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
void saveValue( T t ){ saveLong( t ); }
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
!std::is_same<T, std::uint32_t>::value,
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
void saveValue( T t ){ saveLong( t ); }
#endif // _MSC_VER
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
!std::is_same<T, long>::value,
!std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
void saveValue(T const & t)
{
std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
ss << t;
saveValue( ss.str() );
}
void writeName()
{
NodeType const & nodeType = itsNodeStack.top();
// Start up either an object or an array, depending on state
if(nodeType == NodeType::StartArray)
{
itsWriter.StartArray();
itsNodeStack.top() = NodeType::InArray;
}
else if(nodeType == NodeType::StartObject)
{
itsNodeStack.top() = NodeType::InObject;
itsWriter.StartObject();
}
// Array types do not output names
if(nodeType == NodeType::InArray) return;
if(itsNextName == nullptr)
{
std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
saveValue(name);
}
else
{
saveValue(itsNextName);
itsNextName = nullptr;
}
}
void makeArray()
{
itsNodeStack.top() = NodeType::StartArray;
}
private:
WriteStream itsWriteStream;
JSONWriter itsWriter;
char const * itsNextName;
std::stack<uint32_t> itsNameCounter;
std::stack<NodeType> itsNodeStack;
}; // JSONOutputArchive
// ######################################################################
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
{
private:
typedef rapidjson::GenericReadStream ReadStream;
typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
typedef JSONValue::ConstMemberIterator MemberIterator;
typedef JSONValue::ConstValueIterator ValueIterator;
typedef rapidjson::Document::GenericValue GenericValue;
public:
JSONInputArchive(std::istream & stream) :
InputArchive<JSONInputArchive>(this),
itsNextName( nullptr ),
itsReadStream(stream)
{
itsDocument.ParseStream<0>(itsReadStream);
itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
}
void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
{
itsNextName = name;
std::string encoded;
loadValue( encoded );
auto decoded = base64::decode( encoded );
if( size != decoded.size() )
throw Exception("Decoded binary data size does not match specified size");
std::memcpy( data, decoded.data(), decoded.size() );
itsNextName = nullptr;
};
private:
class Iterator
{
public:
Iterator() : itsIndex( 0 ), itsType(Null_) {}
Iterator(MemberIterator begin, MemberIterator end) :
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
{ }
Iterator(ValueIterator begin, ValueIterator end) :
itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
{ }
Iterator & operator++()
{
++itsIndex;
return *this;
}
GenericValue const & value()
{
switch(itsType)
{
case Value : return itsValueItBegin[itsIndex];
case Member: return itsMemberItBegin[itsIndex].value;
default: throw cereal::Exception("Invalid Iterator Type!");
}
}
const char * name() const
{
if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
return itsMemberItBegin[itsIndex].name.GetString();
else
return nullptr;
}
inline void search( const char * searchName )
{
const auto len = std::strlen( searchName );
size_t index = 0;
for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
{
const auto currentName = it->name.GetString();
if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
( std::strlen( currentName ) == len ) )
{
itsIndex = index;
return;
}
}
throw Exception("JSON Parsing failed - provided NVP not found");
}
private:
MemberIterator itsMemberItBegin, itsMemberItEnd;
ValueIterator itsValueItBegin, itsValueItEnd;
size_t itsIndex;
enum Type {Value, Member, Null_} itsType;
};
inline void search()
{
// The name an NVP provided with setNextName()
if( itsNextName )
{
// The actual name of the current node
auto const actualName = itsIteratorStack.back().name();
// Do a search if we don't see a name coming up, or if the names don't match
if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
itsIteratorStack.back().search( itsNextName );
}
itsNextName = nullptr;
}
public:
void startNode()
{
search();
if(itsIteratorStack.back().value().IsArray())
itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
else
itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
}
void finishNode()
{
itsIteratorStack.pop_back();
++itsIteratorStack.back();
}
const char * getNodeName() const
{
return itsIteratorStack.back().name();
}
void setNextName( const char * name )
{
itsNextName = name;
}
template <class T, traits::EnableIf<std::is_signed<T>::value,
sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
void loadValue(T & val)
{
search();
val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
++itsIteratorStack.back();
}
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
sizeof(T) < sizeof(uint64_t),
!std::is_same<bool, T>::value> = traits::sfinae> inline
void loadValue(T & val)
{
search();
val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
++itsIteratorStack.back();
}
void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); }
void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
// Special cases to handle various flavors of long, which tend to conflict with
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
#ifndef _MSC_VER
private:
template <class T> inline
typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
template <class T> inline
typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
template <class T> inline
typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
template <class T> inline
typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
public:
template <class T> inline
typename std::enable_if<std::is_same<T, long>::value &&
sizeof(T) >= sizeof(std::int64_t) &&
!std::is_same<T, std::int64_t>::value, void>::type
loadValue( T & t ){ loadLong(t); }
template <class T> inline
typename std::enable_if<std::is_same<T, unsigned long>::value &&
sizeof(T) >= sizeof(std::uint64_t) &&
!std::is_same<T, std::uint64_t>::value, void>::type
loadValue( T & t ){ loadLong(t); }
#endif // _MSC_VER
private:
void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
public:
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
!std::is_same<T, long>::value,
!std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
inline void loadValue(T & val)
{
std::string encoded;
loadValue( encoded );
stringToNumber( encoded, val );
}
void loadSize(size_type & size)
{
size = (itsIteratorStack.rbegin() + 1)->value().Size();
}
private:
const char * itsNextName;
ReadStream itsReadStream;
std::vector<Iterator> itsIteratorStack;
rapidjson::Document itsDocument;
};
// ######################################################################
// JSONArchive prologue and epilogue functions
// ######################################################################
// ######################################################################
template <class T> inline
void prologue( JSONOutputArchive &, NameValuePair<T> const & )
{ }
template <class T> inline
void prologue( JSONInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
template <class T> inline
void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
{ }
template <class T> inline
void epilogue( JSONInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
template <class T> inline
void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
{
ar.makeArray();
}
template <class T> inline
void prologue( JSONInputArchive &, SizeTag<T> const & )
{ }
// ######################################################################
template <class T> inline
void epilogue( JSONOutputArchive &, SizeTag<T> const & )
{ }
template <class T> inline
void epilogue( JSONInputArchive &, SizeTag<T> const & )
{ }
// ######################################################################
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
inline void prologue( JSONOutputArchive & ar, T const & )
{
ar.startNode();
}
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
inline void prologue( JSONInputArchive & ar, T const & )
{
ar.startNode();
}
// ######################################################################
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
inline void epilogue( JSONOutputArchive & ar, T const & )
{
ar.finishNode();
}
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
inline void epilogue( JSONInputArchive & ar, T const & )
{
ar.finishNode();
}
// ######################################################################
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void prologue( JSONOutputArchive & ar, T const & )
{
ar.writeName();
}
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void prologue( JSONInputArchive &, T const & )
{ }
// ######################################################################
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void epilogue( JSONOutputArchive &, T const & )
{ }
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void epilogue( JSONInputArchive &, T const & )
{ }
// ######################################################################
template<class CharT, class Traits, class Alloc> inline
void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
{
ar.writeName();
}
template<class CharT, class Traits, class Alloc> inline
void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
{ }
// ######################################################################
template<class CharT, class Traits, class Alloc> inline
void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
{ }
template<class CharT, class Traits, class Alloc> inline
void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
{ }
// ######################################################################
// Common JSONArchive serialization functions
// ######################################################################
template <class T> inline
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair<T> const & t )
{
ar.setNextName( t.name );
ar( t.value );
}
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t )
{
ar.setNextName( t.name );
ar( t.value );
}
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t)
{
ar.saveValue( t );
}
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t)
{
ar.loadValue( t );
}
template<class CharT, class Traits, class Alloc> inline
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{
ar.saveValue( str );
}
template<class CharT, class Traits, class Alloc> inline
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
{
ar.loadValue( str );
}
// ######################################################################
template <class T> inline
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag<T> const & )
{
// nothing to do here, we don't explicitly save the size
}
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag<T> & st )
{
ar.loadSize( st.size );
}
} // namespace cereal
// register archives for polymorphic support
CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
// tie input and output archives together
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive)
#endif // CEREAL_ARCHIVES_JSON_HPP_
cereal::JSONOutputArchive::saveValue
void saveValue(T t)
Serialize a long if it would not be caught otherwise.
Definition: json.hpp:272
cereal::JSONOutputArchive::Options::Default
static Options Default()
Default options.
Definition: json.hpp:105
cereal::JSONOutputArchive::saveValue
void saveValue(int64_t i64)
Saves an int64 to the current node.
Definition: json.hpp:229
cereal::RapidJSONException
An exception thrown when rapidjson fails an internal assertion.
Definition: json.hpp:39
cereal::JSONOutputArchive::startNode
void startNode()
Starts a new node in the JSON output.
Definition: json.hpp:183
cereal::JSONOutputArchive::saveValue
void saveValue(std::string const &s)
Saves a string to the current node.
Definition: json.hpp:235
CEREAL_SETUP_ARCHIVE_TRAITS
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive)
Sets up traits that relate an input archive to an output archive.
Definition: traits.hpp:169
cereal::JSONOutputArchive::saveValue
void saveValue(uint64_t u64)
Saves a uint64 to the current node.
Definition: json.hpp:231
cereal::JSONOutputArchive::saveValue
void saveValue(int i)
Saves an int to the current node.
Definition: json.hpp:225
cereal::SizeTag
A wrapper around size metadata.
Definition: helpers.hpp:250
cereal::JSONOutputArchive::finishNode
void finishNode()
Designates the most recently added node as finished.
Definition: json.hpp:191
cereal::JSONOutputArchive::Options
A class containing various advanced options for the JSON archive.
Definition: json.hpp:101
cereal::prologue
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:702
EnableIf
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
cereal::JSONOutputArchive::writeName
void writeName()
Write the name of the upcoming node and prepare object/array state.
Definition: json.hpp:309
cereal::traits::has_minimal_base_class_serialization
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1119
cereal::JSONOutputArchive::saveValue
void saveValue(char const *s)
Saves a const char * to the current node.
Definition: json.hpp:237
cereal::JSONInputArchive::loadBinaryValue
void loadBinaryValue(void *data, size_t size, const char *name=nullptr)
Loads some binary data, encoded as a base64 string.
Definition: json.hpp:422
cereal::traits::TextArchive
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1266
cereal::InputArchive
The base input archive class.
Definition: cereal.hpp:584
cereal::JSONInputArchive::getNodeName
const char * getNodeName() const
Retrieves the current node name.
Definition: json.hpp:569
cereal::JSONOutputArchive::Options::NoIndent
static Options NoIndent()
Default options with no indentation.
Definition: json.hpp:108
cereal::JSONOutputArchive
An output archive designed to save data to JSON.
Definition: json.hpp:88
cereal::JSONOutputArchive::saveValue
void saveValue(double d)
Saves a double to the current node.
Definition: json.hpp:233
cereal::size_type
uint64_t size_type
The size type used by cereal.
Definition: helpers.hpp:59
cereal::traits::has_minimal_input_serialization
Definition: traits.hpp:1002
cereal::traits::has_minimal_output_serialization
Definition: traits.hpp:990
cereal
Definition: access.hpp:39
cereal::JSONInputArchive
An input archive designed to load data from JSON.
Definition: json.hpp:391
CEREAL_REGISTER_ARCHIVE
#define CEREAL_REGISTER_ARCHIVE(Archive)
Registers a specific Archive type with cereal.
Definition: cereal.hpp:141
cereal::JSONOutputArchive::makeArray
void makeArray()
Designates that the current node should be output as an array, not an object.
Definition: json.hpp:341
cereal::JSONOutputArchive::saveValue
void saveValue(T const &t)
Save exotic arithmetic as strings to current node.
Definition: json.hpp:289
util.hpp
Internal misc utilities.
cereal.hpp
Main cereal functionality.
cereal::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:135
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
cereal::JSONInputArchive::JSONInputArchive
JSONInputArchive(std::istream &stream)
Construct, reading from the provided stream.
Definition: json.hpp:407
cereal::JSONOutputArchive::Options::Options
Options(int precision=std::numeric_limits< double >::max_digits10, IndentChar indentChar=IndentChar::space, unsigned int indentLength=4)
Specify specific options for the JSONOutputArchive.
Definition: json.hpp:124
cereal::JSONOutputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:217
cereal::JSONOutputArchive::saveValue
void saveValue(unsigned u)
Saves a uint to the current node.
Definition: json.hpp:227
cereal::JSONOutputArchive::~JSONOutputArchive
~JSONOutputArchive()
Destructor, flushes the JSON.
Definition: json.hpp:154
cereal::JSONInputArchive::finishNode
void finishNode()
Finishes the most recently started node.
Definition: json.hpp:561
cereal::OutputArchive
The base output archive class.
Definition: cereal.hpp:234
cereal::JSONOutputArchive::saveValue
void saveValue(bool b)
Saves a bool to the current node.
Definition: json.hpp:223
cereal::JSONOutputArchive::Options::IndentChar
IndentChar
The character to use for indenting.
Definition: json.hpp:111
CEREAL_SAVE_FUNCTION_NAME
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:65
cereal::JSONOutputArchive::saveBinaryValue
void saveBinaryValue(const void *data, size_t size, const char *name=nullptr)
Saves some binary data, encoded as a base64 string, with an optional name.
Definition: json.hpp:163
cereal::JSONInputArchive::loadSize
void loadSize(size_type &size)
Loads the size for a SizeTag.
Definition: json.hpp:680
cereal::epilogue
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:714
cereal::JSONInputArchive::startNode
void startNode()
Starts a new node, going into its proper iterator.
Definition: json.hpp:550
cereal::JSONInputArchive::loadValue
void loadValue(T &val)
Loads a value from the current node - long double and long long overloads.
Definition: json.hpp:672
cereal::JSONOutputArchive::JSONOutputArchive
JSONOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream.
Definition: json.hpp:142
cereal::JSONInputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:575
cereal::JSONInputArchive::loadValue
::type loadValue(T &t)
Loads a value from the current node - small signed overload.
Definition: json.hpp:653
cereal::Exception
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48