cereal
A C++11 library for serialization
json.hpp
Go to the documentation of this file.
1 
3 /*
4  Copyright (c) 2014, Randolph Voorhies, Shane Grant
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions are met:
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14  * Neither the name of cereal nor the
15  names of its contributors may be used to endorse or promote products
16  derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
22  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #ifndef CEREAL_ARCHIVES_JSON_HPP_
30 #define CEREAL_ARCHIVES_JSON_HPP_
31 
32 #include <cereal/cereal.hpp>
33 #include <cereal/details/util.hpp>
34 
35 namespace cereal
36 {
38 
40  { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
41 }
42 
43 // Override rapidjson assertions to throw exceptions by default
44 #ifndef RAPIDJSON_ASSERT
45 #define RAPIDJSON_ASSERT(x) if(!(x)){ \
46  throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
47 #endif // RAPIDJSON_ASSERT
48 
49 #include <cereal/external/rapidjson/prettywriter.h>
50 #include <cereal/external/rapidjson/genericstream.h>
51 #include <cereal/external/rapidjson/reader.h>
52 #include <cereal/external/rapidjson/document.h>
53 #include <cereal/external/base64.hpp>
54 
55 #include <limits>
56 #include <sstream>
57 #include <stack>
58 #include <vector>
59 #include <string>
60 
61 namespace cereal
62 {
63  // ######################################################################
65 
88  class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
89  {
90  enum class NodeType { StartObject, InObject, StartArray, InArray };
91 
92  typedef rapidjson::GenericWriteStream WriteStream;
93  typedef rapidjson::PrettyWriter<WriteStream> JSONWriter;
94 
95  public:
98 
101  class Options
102  {
103  public:
105  static Options Default(){ return Options(); }
106 
108  static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, IndentChar::space, 0 ); }
109 
111  enum class IndentChar : char
112  {
113  space = ' ',
114  tab = '\t',
115  newline = '\n',
116  carriage_return = '\r'
117  };
118 
120 
124  explicit Options( int precision = std::numeric_limits<double>::max_digits10,
125  IndentChar indentChar = IndentChar::space,
126  unsigned int indentLength = 4 ) :
127  itsPrecision( precision ),
128  itsIndentChar( static_cast<char>(indentChar) ),
129  itsIndentLength( indentLength ) { }
130 
131  private:
132  friend class JSONOutputArchive;
133  int itsPrecision;
134  char itsIndentChar;
135  unsigned int itsIndentLength;
136  };
137 
139 
142  JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
144  itsWriteStream(stream),
145  itsWriter(itsWriteStream, options.itsPrecision),
146  itsNextName(nullptr)
147  {
148  itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
149  itsNameCounter.push(0);
150  itsNodeStack.push(NodeType::StartObject);
151  }
152 
155  {
156  if (itsNodeStack.top() == NodeType::InObject)
157  itsWriter.EndObject();
158  }
159 
161 
163  void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
164  {
165  setNextName( name );
166  writeName();
167 
168  auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
169  saveValue( base64string );
170  };
171 
173 
176 
179 
183  void startNode()
184  {
185  writeName();
186  itsNodeStack.push(NodeType::StartObject);
187  itsNameCounter.push(0);
188  }
189 
191  void finishNode()
192  {
193  // if we ended up serializing an empty object or array, writeName
194  // will never have been called - so start and then immediately end
195  // the object/array.
196  //
197  // We'll also end any object/arrays we happen to be in
198  switch(itsNodeStack.top())
199  {
200  case NodeType::StartArray:
201  itsWriter.StartArray();
202  case NodeType::InArray:
203  itsWriter.EndArray();
204  break;
205  case NodeType::StartObject:
206  itsWriter.StartObject();
207  case NodeType::InObject:
208  itsWriter.EndObject();
209  break;
210  }
211 
212  itsNodeStack.pop();
213  itsNameCounter.pop();
214  }
215 
217  void setNextName( const char * name )
218  {
219  itsNextName = name;
220  }
221 
223  void saveValue(bool b) { itsWriter.Bool_(b); }
225  void saveValue(int i) { itsWriter.Int(i); }
227  void saveValue(unsigned u) { itsWriter.Uint(u); }
229  void saveValue(int64_t i64) { itsWriter.Int64(i64); }
231  void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
233  void saveValue(double d) { itsWriter.Double(d); }
235  void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
237  void saveValue(char const * s) { itsWriter.String(s); }
238 
239  private:
240  // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
241  // special overloads to handle these cases.
242 
244  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
245  std::is_signed<T>::value> = traits::sfinae> inline
246  void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
247 
249  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
250  std::is_signed<T>::value> = traits::sfinae> inline
251  void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
252 
254  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
255  std::is_unsigned<T>::value> = traits::sfinae> inline
256  void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
257 
259  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
260  std::is_unsigned<T>::value> = traits::sfinae> inline
261  void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
262 
263  public:
264 #ifdef _MSC_VER
265  void saveValue( unsigned long lu ){ saveLong( lu ); };
267 #else // _MSC_VER
268  template <class T, traits::EnableIf<std::is_same<T, long>::value,
270  !std::is_same<T, std::int32_t>::value,
271  !std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
272  void saveValue( T t ){ saveLong( t ); }
273 
275  template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
276  !std::is_same<T, std::uint32_t>::value,
277  !std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
278  void saveValue( T t ){ saveLong( t ); }
279 #endif // _MSC_VER
280 
282 
283  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
284  !std::is_same<T, long>::value,
285  !std::is_same<T, unsigned long>::value,
286  !std::is_same<T, std::int64_t>::value,
287  !std::is_same<T, std::uint64_t>::value,
288  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
289  void saveValue(T const & t)
290  {
291  std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
292  ss << t;
293  saveValue( ss.str() );
294  }
295 
297 
309  void writeName()
310  {
311  NodeType const & nodeType = itsNodeStack.top();
312 
313  // Start up either an object or an array, depending on state
314  if(nodeType == NodeType::StartArray)
315  {
316  itsWriter.StartArray();
317  itsNodeStack.top() = NodeType::InArray;
318  }
319  else if(nodeType == NodeType::StartObject)
320  {
321  itsNodeStack.top() = NodeType::InObject;
322  itsWriter.StartObject();
323  }
324 
325  // Array types do not output names
326  if(nodeType == NodeType::InArray) return;
327 
328  if(itsNextName == nullptr)
329  {
330  std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
331  saveValue(name);
332  }
333  else
334  {
335  saveValue(itsNextName);
336  itsNextName = nullptr;
337  }
338  }
339 
341  void makeArray()
342  {
343  itsNodeStack.top() = NodeType::StartArray;
344  }
345 
347 
348  private:
349  WriteStream itsWriteStream;
350  JSONWriter itsWriter;
351  char const * itsNextName;
352  std::stack<uint32_t> itsNameCounter;
353  std::stack<NodeType> itsNodeStack;
354  }; // JSONOutputArchive
355 
356  // ######################################################################
358 
391  class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
392  {
393  private:
394  typedef rapidjson::GenericReadStream ReadStream;
395  typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
396  typedef JSONValue::ConstMemberIterator MemberIterator;
397  typedef JSONValue::ConstValueIterator ValueIterator;
398  typedef rapidjson::Document::GenericValue GenericValue;
399 
400  public:
403 
406 
407  JSONInputArchive(std::istream & stream) :
409  itsNextName( nullptr ),
410  itsReadStream(stream)
411  {
412  itsDocument.ParseStream<0>(itsReadStream);
413  itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
414  }
415 
417 
422  void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
423  {
424  itsNextName = name;
425 
426  std::string encoded;
427  loadValue( encoded );
428  auto decoded = base64::decode( encoded );
429 
430  if( size != decoded.size() )
431  throw Exception("Decoded binary data size does not match specified size");
432 
433  std::memcpy( data, decoded.data(), decoded.size() );
434  itsNextName = nullptr;
435  };
436 
437  private:
439 
442 
445 
447  class Iterator
448  {
449  public:
450  Iterator() : itsIndex( 0 ), itsType(Null_) {}
451 
452  Iterator(MemberIterator begin, MemberIterator end) :
453  itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
454  { }
455 
456  Iterator(ValueIterator begin, ValueIterator end) :
457  itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
458  { }
459 
461  Iterator & operator++()
462  {
463  ++itsIndex;
464  return *this;
465  }
466 
468  GenericValue const & value()
469  {
470  switch(itsType)
471  {
472  case Value : return itsValueItBegin[itsIndex];
473  case Member: return itsMemberItBegin[itsIndex].value;
474  default: throw cereal::Exception("Invalid Iterator Type!");
475  }
476  }
477 
479  const char * name() const
480  {
481  if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
482  return itsMemberItBegin[itsIndex].name.GetString();
483  else
484  return nullptr;
485  }
486 
488 
489  inline void search( const char * searchName )
490  {
491  const auto len = std::strlen( searchName );
492  size_t index = 0;
493  for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
494  {
495  const auto currentName = it->name.GetString();
496  if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
497  ( std::strlen( currentName ) == len ) )
498  {
499  itsIndex = index;
500  return;
501  }
502  }
503 
504  throw Exception("JSON Parsing failed - provided NVP not found");
505  }
506 
507  private:
508  MemberIterator itsMemberItBegin, itsMemberItEnd;
509  ValueIterator itsValueItBegin, itsValueItEnd;
510  size_t itsIndex;
511  enum Type {Value, Member, Null_} itsType;
512  };
513 
515 
523  inline void search()
524  {
525  // The name an NVP provided with setNextName()
526  if( itsNextName )
527  {
528  // The actual name of the current node
529  auto const actualName = itsIteratorStack.back().name();
530 
531  // Do a search if we don't see a name coming up, or if the names don't match
532  if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
533  itsIteratorStack.back().search( itsNextName );
534  }
535 
536  itsNextName = nullptr;
537  }
538 
539  public:
541 
550  void startNode()
551  {
552  search();
553 
554  if(itsIteratorStack.back().value().IsArray())
555  itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
556  else
557  itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
558  }
559 
561  void finishNode()
562  {
563  itsIteratorStack.pop_back();
564  ++itsIteratorStack.back();
565  }
566 
568 
569  const char * getNodeName() const
570  {
571  return itsIteratorStack.back().name();
572  }
573 
575  void setNextName( const char * name )
576  {
577  itsNextName = name;
578  }
579 
581  template <class T, traits::EnableIf<std::is_signed<T>::value,
582  sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
583  void loadValue(T & val)
584  {
585  search();
586 
587  val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
588  ++itsIteratorStack.back();
589  }
590 
592  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
593  sizeof(T) < sizeof(uint64_t),
594  !std::is_same<bool, T>::value> = traits::sfinae> inline
595  void loadValue(T & val)
596  {
597  search();
598 
599  val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
600  ++itsIteratorStack.back();
601  }
602 
604  void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); }
606  void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
608  void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
610  void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
612  void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
614  void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
615 
616  // Special cases to handle various flavors of long, which tend to conflict with
617  // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
618  #ifndef _MSC_VER
619  private:
621  template <class T> inline
622  typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
623  loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
624 
626  template <class T> inline
627  typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
628  loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
629 
631  template <class T> inline
632  typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
633  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
634 
636  template <class T> inline
637  typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
638  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
639 
640  public:
642  template <class T> inline
643  typename std::enable_if<std::is_same<T, long>::value &&
644  sizeof(T) >= sizeof(std::int64_t) &&
645  !std::is_same<T, std::int64_t>::value, void>::type
646  loadValue( T & t ){ loadLong(t); }
647 
649  template <class T> inline
650  typename std::enable_if<std::is_same<T, unsigned long>::value &&
651  sizeof(T) >= sizeof(std::uint64_t) &&
652  !std::is_same<T, std::uint64_t>::value, void>::type
653  loadValue( T & t ){ loadLong(t); }
654  #endif // _MSC_VER
655 
656  private:
658  void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
660  void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
662  void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
663 
664  public:
666  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
667  !std::is_same<T, long>::value,
668  !std::is_same<T, unsigned long>::value,
669  !std::is_same<T, std::int64_t>::value,
670  !std::is_same<T, std::uint64_t>::value,
671  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
672  inline void loadValue(T & val)
673  {
674  std::string encoded;
675  loadValue( encoded );
676  stringToNumber( encoded, val );
677  }
678 
680  void loadSize(size_type & size)
681  {
682  size = (itsIteratorStack.rbegin() + 1)->value().Size();
683  }
684 
686 
687  private:
688  const char * itsNextName;
689  ReadStream itsReadStream;
690  std::vector<Iterator> itsIteratorStack;
691  rapidjson::Document itsDocument;
692  };
693 
694  // ######################################################################
695  // JSONArchive prologue and epilogue functions
696  // ######################################################################
697 
698  // ######################################################################
700 
701  template <class T> inline
703  { }
704 
706  template <class T> inline
708  { }
709 
710  // ######################################################################
712 
713  template <class T> inline
715  { }
716 
718 
719  template <class T> inline
721  { }
722 
723  // ######################################################################
725 
727  template <class T> inline
728  void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
729  {
730  ar.makeArray();
731  }
732 
734  template <class T> inline
736  { }
737 
738  // ######################################################################
740 
741  template <class T> inline
743  { }
744 
746  template <class T> inline
748  { }
749 
750  // ######################################################################
752 
756  template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
759  inline void prologue( JSONOutputArchive & ar, T const & )
760  {
761  ar.startNode();
762  }
763 
765  template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
768  inline void prologue( JSONInputArchive & ar, T const & )
769  {
770  ar.startNode();
771  }
772 
773  // ######################################################################
775 
778  template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
781  inline void epilogue( JSONOutputArchive & ar, T const & )
782  {
783  ar.finishNode();
784  }
785 
787  template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
790  inline void epilogue( JSONInputArchive & ar, T const & )
791  {
792  ar.finishNode();
793  }
794 
795  // ######################################################################
797  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
798  void prologue( JSONOutputArchive & ar, T const & )
799  {
800  ar.writeName();
801  }
802 
804  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
805  void prologue( JSONInputArchive &, T const & )
806  { }
807 
808  // ######################################################################
810  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
811  void epilogue( JSONOutputArchive &, T const & )
812  { }
813 
815  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
816  void epilogue( JSONInputArchive &, T const & )
817  { }
818 
819  // ######################################################################
821  template<class CharT, class Traits, class Alloc> inline
822  void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
823  {
824  ar.writeName();
825  }
826 
828  template<class CharT, class Traits, class Alloc> inline
829  void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
830  { }
831 
832  // ######################################################################
834  template<class CharT, class Traits, class Alloc> inline
835  void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
836  { }
837 
839  template<class CharT, class Traits, class Alloc> inline
840  void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
841  { }
842 
843  // ######################################################################
844  // Common JSONArchive serialization functions
845  // ######################################################################
847  template <class T> inline
849  {
850  ar.setNextName( t.name );
851  ar( t.value );
852  }
853 
854  template <class T> inline
856  {
857  ar.setNextName( t.name );
858  ar( t.value );
859  }
860 
862  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
864  {
865  ar.saveValue( t );
866  }
867 
869  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
871  {
872  ar.loadValue( t );
873  }
874 
876  template<class CharT, class Traits, class Alloc> inline
877  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
878  {
879  ar.saveValue( str );
880  }
881 
883  template<class CharT, class Traits, class Alloc> inline
884  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
885  {
886  ar.loadValue( str );
887  }
888 
889  // ######################################################################
891  template <class T> inline
893  {
894  // nothing to do here, we don't explicitly save the size
895  }
896 
898  template <class T> inline
900  {
901  ar.loadSize( st.size );
902  }
903 } // namespace cereal
904 
905 // register archives for polymorphic support
908 
909 // tie input and output archives together
911 
912 #endif // CEREAL_ARCHIVES_JSON_HPP_
void saveValue(T t)
Serialize a long if it would not be caught otherwise.
Definition: json.hpp:272
static Options Default()
Default options.
Definition: json.hpp:105
void saveValue(int64_t i64)
Saves an int64 to the current node.
Definition: json.hpp:229
An exception thrown when rapidjson fails an internal assertion.
Definition: json.hpp:39
void startNode()
Starts a new node in the JSON output.
Definition: json.hpp:183
void saveValue(std::string const &s)
Saves a string to the current node.
Definition: json.hpp:235
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive)
Sets up traits that relate an input archive to an output archive.
Definition: traits.hpp:169
void saveValue(uint64_t u64)
Saves a uint64 to the current node.
Definition: json.hpp:231
void saveValue(int i)
Saves an int to the current node.
Definition: json.hpp:225
A wrapper around size metadata.
Definition: helpers.hpp:250
void finishNode()
Designates the most recently added node as finished.
Definition: json.hpp:191
A class containing various advanced options for the JSON archive.
Definition: json.hpp:101
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:702
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
void writeName()
Write the name of the upcoming node and prepare object/array state.
Definition: json.hpp:309
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1119
void saveValue(char const *s)
Saves a const char * to the current node.
Definition: json.hpp:237
void loadBinaryValue(void *data, size_t size, const char *name=nullptr)
Loads some binary data, encoded as a base64 string.
Definition: json.hpp:422
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1266
The base input archive class.
Definition: cereal.hpp:584
const char * getNodeName() const
Retrieves the current node name.
Definition: json.hpp:569
static Options NoIndent()
Default options with no indentation.
Definition: json.hpp:108
An output archive designed to save data to JSON.
Definition: json.hpp:88
void saveValue(double d)
Saves a double to the current node.
Definition: json.hpp:233
uint64_t size_type
The size type used by cereal.
Definition: helpers.hpp:59
Definition: access.hpp:39
An input archive designed to load data from JSON.
Definition: json.hpp:391
#define CEREAL_REGISTER_ARCHIVE(Archive)
Registers a specific Archive type with cereal.
Definition: cereal.hpp:141
void makeArray()
Designates that the current node should be output as an array, not an object.
Definition: json.hpp:341
void saveValue(T const &t)
Save exotic arithmetic as strings to current node.
Definition: json.hpp:289
Internal misc utilities.
Main cereal functionality.
For holding name value pairs.
Definition: helpers.hpp:135
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
JSONInputArchive(std::istream &stream)
Construct, reading from the provided stream.
Definition: json.hpp:407
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
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:217
void saveValue(unsigned u)
Saves a uint to the current node.
Definition: json.hpp:227
~JSONOutputArchive()
Destructor, flushes the JSON.
Definition: json.hpp:154
void finishNode()
Finishes the most recently started node.
Definition: json.hpp:561
The base output archive class.
Definition: cereal.hpp:234
void saveValue(bool b)
Saves a bool to the current node.
Definition: json.hpp:223
IndentChar
The character to use for indenting.
Definition: json.hpp:111
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:65
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
void loadSize(size_type &size)
Loads the size for a SizeTag.
Definition: json.hpp:680
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:714
void startNode()
Starts a new node, going into its proper iterator.
Definition: json.hpp:550
void loadValue(T &val)
Loads a value from the current node - long double and long long overloads.
Definition: json.hpp:672
JSONOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream.
Definition: json.hpp:142
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:575
::type loadValue(T &t)
Loads a value from the current node - small signed overload.
Definition: json.hpp:653
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48