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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 // Inform rapidjson that assert will throw
44 #ifndef CEREAL_RAPIDJSON_ASSERT_THROWS
45 #define CEREAL_RAPIDJSON_ASSERT_THROWS
46 #endif // CEREAL_RAPIDJSON_ASSERT_THROWS
47 
48 // Override rapidjson assertions to throw exceptions by default
49 #ifndef CEREAL_RAPIDJSON_ASSERT
50 #define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
51  throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
52 #endif // RAPIDJSON_ASSERT
53 
54 // Enable support for parsing of nan, inf, -inf
55 #ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
56 #define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
57 #endif
58 
59 // Enable support for parsing of nan, inf, -inf
60 #ifndef CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
61 #define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
62 #endif
63 
64 #include "cereal/external/rapidjson/prettywriter.h"
65 #include "cereal/external/rapidjson/ostreamwrapper.h"
66 #include "cereal/external/rapidjson/istreamwrapper.h"
67 #include "cereal/external/rapidjson/document.h"
68 #include "cereal/external/base64.hpp"
69 
70 #include <limits>
71 #include <sstream>
72 #include <stack>
73 #include <vector>
74 #include <string>
75 
76 namespace cereal
77 {
78  // ######################################################################
80 
106  class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
107  {
108  enum class NodeType { StartObject, InObject, StartArray, InArray };
109 
110  using WriteStream = CEREAL_RAPIDJSON_NAMESPACE::OStreamWrapper;
111  using JSONWriter = CEREAL_RAPIDJSON_NAMESPACE::PrettyWriter<WriteStream>;
112 
113  public:
116 
119  class Options
120  {
121  public:
123  static Options Default(){ return Options(); }
124 
126  static Options NoIndent(){ return Options( JSONWriter::kDefaultMaxDecimalPlaces, IndentChar::space, 0 ); }
127 
129  enum class IndentChar : char
130  {
131  space = ' ',
132  tab = '\t',
133  newline = '\n',
134  carriage_return = '\r'
135  };
136 
138 
142  explicit Options( int precision = JSONWriter::kDefaultMaxDecimalPlaces,
143  IndentChar indentChar = IndentChar::space,
144  unsigned int indentLength = 4 ) :
145  itsPrecision( precision ),
146  itsIndentChar( static_cast<char>(indentChar) ),
147  itsIndentLength( indentLength ) { }
148 
149  private:
150  friend class JSONOutputArchive;
151  int itsPrecision;
152  char itsIndentChar;
153  unsigned int itsIndentLength;
154  };
155 
157 
160  JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
162  itsWriteStream(stream),
163  itsWriter(itsWriteStream),
164  itsNextName(nullptr)
165  {
166  itsWriter.SetMaxDecimalPlaces( options.itsPrecision );
167  itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
168  itsNameCounter.push(0);
169  itsNodeStack.push(NodeType::StartObject);
170  }
171 
174  {
175  if (itsNodeStack.top() == NodeType::InObject)
176  itsWriter.EndObject();
177  else if (itsNodeStack.top() == NodeType::InArray)
178  itsWriter.EndArray();
179  }
180 
182 
184  void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
185  {
186  setNextName( name );
187  writeName();
188 
189  auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
190  saveValue( base64string );
191  };
192 
194 
197 
200 
204  void startNode()
205  {
206  writeName();
207  itsNodeStack.push(NodeType::StartObject);
208  itsNameCounter.push(0);
209  }
210 
212  void finishNode()
213  {
214  // if we ended up serializing an empty object or array, writeName
215  // will never have been called - so start and then immediately end
216  // the object/array.
217  //
218  // We'll also end any object/arrays we happen to be in
219  switch(itsNodeStack.top())
220  {
221  case NodeType::StartArray:
222  itsWriter.StartArray();
223  // fall through
224  case NodeType::InArray:
225  itsWriter.EndArray();
226  break;
227  case NodeType::StartObject:
228  itsWriter.StartObject();
229  // fall through
230  case NodeType::InObject:
231  itsWriter.EndObject();
232  break;
233  }
234 
235  itsNodeStack.pop();
236  itsNameCounter.pop();
237  }
238 
240  void setNextName( const char * name )
241  {
242  itsNextName = name;
243  }
244 
246  void saveValue(bool b) { itsWriter.Bool(b); }
248  void saveValue(int i) { itsWriter.Int(i); }
250  void saveValue(unsigned u) { itsWriter.Uint(u); }
252  void saveValue(int64_t i64) { itsWriter.Int64(i64); }
254  void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
256  void saveValue(double d) { itsWriter.Double(d); }
258  void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<CEREAL_RAPIDJSON_NAMESPACE::SizeType>( s.size() )); }
260  void saveValue(char const * s) { itsWriter.String(s); }
262  void saveValue(std::nullptr_t) { itsWriter.Null(); }
263 
264  private:
265  // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
266  // special overloads to handle these cases.
267 
269  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
270  std::is_signed<T>::value> = traits::sfinae> inline
271  void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
272 
274  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
275  std::is_signed<T>::value> = traits::sfinae> inline
276  void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
277 
279  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
280  std::is_unsigned<T>::value> = traits::sfinae> inline
281  void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
282 
284  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
285  std::is_unsigned<T>::value> = traits::sfinae> inline
286  void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
287 
288  public:
289 #if defined(_MSC_VER) && _MSC_VER < 1916
290  void saveValue( unsigned long lu ){ saveLong( lu ); };
292 #else // _MSC_VER
293  template <class T, traits::EnableIf<std::is_same<T, long>::value,
295  !std::is_same<T, int>::value,
296  !std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
297  void saveValue( T t ){ saveLong( t ); }
298 
300  template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
301  !std::is_same<T, unsigned>::value,
302  !std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
303  void saveValue( T t ){ saveLong( t ); }
304 #endif // _MSC_VER
305 
307 
308  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
309  !std::is_same<T, long>::value,
310  !std::is_same<T, unsigned long>::value,
311  !std::is_same<T, std::int64_t>::value,
312  !std::is_same<T, std::uint64_t>::value,
313  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
314  void saveValue(T const & t)
315  {
316  std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
317  ss << t;
318  saveValue( ss.str() );
319  }
320 
322 
334  void writeName()
335  {
336  NodeType const & nodeType = itsNodeStack.top();
337 
338  // Start up either an object or an array, depending on state
339  if(nodeType == NodeType::StartArray)
340  {
341  itsWriter.StartArray();
342  itsNodeStack.top() = NodeType::InArray;
343  }
344  else if(nodeType == NodeType::StartObject)
345  {
346  itsNodeStack.top() = NodeType::InObject;
347  itsWriter.StartObject();
348  }
349 
350  // Array types do not output names
351  if(nodeType == NodeType::InArray) return;
352 
353  if(itsNextName == nullptr)
354  {
355  std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
356  saveValue(name);
357  }
358  else
359  {
360  saveValue(itsNextName);
361  itsNextName = nullptr;
362  }
363  }
364 
366  void makeArray()
367  {
368  itsNodeStack.top() = NodeType::StartArray;
369  }
370 
372 
373  private:
374  WriteStream itsWriteStream;
375  JSONWriter itsWriter;
376  char const * itsNextName;
377  std::stack<uint32_t> itsNameCounter;
378  std::stack<NodeType> itsNodeStack;
379  }; // JSONOutputArchive
380 
381  // ######################################################################
383 
419  class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
420  {
421  private:
422  using ReadStream = CEREAL_RAPIDJSON_NAMESPACE::IStreamWrapper;
423  typedef CEREAL_RAPIDJSON_NAMESPACE::GenericValue<CEREAL_RAPIDJSON_NAMESPACE::UTF8<>> JSONValue;
424  typedef JSONValue::ConstMemberIterator MemberIterator;
425  typedef JSONValue::ConstValueIterator ValueIterator;
426  typedef CEREAL_RAPIDJSON_NAMESPACE::Document::GenericValue GenericValue;
427 
428  public:
431 
434 
435  JSONInputArchive(std::istream & stream) :
437  itsNextName( nullptr ),
438  itsReadStream(stream)
439  {
440  itsDocument.ParseStream<>(itsReadStream);
441  if (itsDocument.IsArray())
442  itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End());
443  else
444  itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
445  }
446 
447  ~JSONInputArchive() CEREAL_NOEXCEPT = default;
448 
450 
455  void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
456  {
457  itsNextName = name;
458 
459  std::string encoded;
460  loadValue( encoded );
461  auto decoded = base64::decode( encoded );
462 
463  if( size != decoded.size() )
464  throw Exception("Decoded binary data size does not match specified size");
465 
466  std::memcpy( data, decoded.data(), decoded.size() );
467  itsNextName = nullptr;
468  };
469 
470  private:
472 
475 
478 
480  class Iterator
481  {
482  public:
483  Iterator() : itsIndex( 0 ), itsType(Null_) {}
484 
485  Iterator(MemberIterator begin, MemberIterator end) :
486  itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Member)
487  {
488  if( itsSize == 0 )
489  itsType = Null_;
490  }
491 
492  Iterator(ValueIterator begin, ValueIterator end) :
493  itsValueItBegin(begin), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Value)
494  {
495  if( itsSize == 0 )
496  itsType = Null_;
497  }
498 
500  Iterator & operator++()
501  {
502  ++itsIndex;
503  return *this;
504  }
505 
507  GenericValue const & value()
508  {
509  if( itsIndex >= itsSize )
510  throw cereal::Exception("No more objects in input");
511 
512  switch(itsType)
513  {
514  case Value : return itsValueItBegin[itsIndex];
515  case Member: return itsMemberItBegin[itsIndex].value;
516  default: throw cereal::Exception("JSONInputArchive internal error: null or empty iterator to object or array!");
517  }
518  }
519 
521  const char * name() const
522  {
523  if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
524  return itsMemberItBegin[itsIndex].name.GetString();
525  else
526  return nullptr;
527  }
528 
530 
531  inline void search( const char * searchName )
532  {
533  const auto len = std::strlen( searchName );
534  size_t index = 0;
535  for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
536  {
537  const auto currentName = it->name.GetString();
538  if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
539  ( std::strlen( currentName ) == len ) )
540  {
541  itsIndex = index;
542  return;
543  }
544  }
545 
546  throw Exception("JSON Parsing failed - provided NVP (" + std::string(searchName) + ") not found");
547  }
548 
549  private:
550  MemberIterator itsMemberItBegin, itsMemberItEnd;
551  ValueIterator itsValueItBegin;
552  size_t itsIndex, itsSize;
553  enum Type {Value, Member, Null_} itsType;
554  };
555 
557 
565  inline void search()
566  {
567  // store pointer to itsNextName locally and reset to nullptr in case search() throws
568  auto localNextName = itsNextName;
569  itsNextName = nullptr;
570 
571  // The name an NVP provided with setNextName()
572  if( localNextName )
573  {
574  // The actual name of the current node
575  auto const actualName = itsIteratorStack.back().name();
576 
577  // Do a search if we don't see a name coming up, or if the names don't match
578  if( !actualName || std::strcmp( localNextName, actualName ) != 0 )
579  itsIteratorStack.back().search( localNextName );
580  }
581  }
582 
583  public:
585 
594  void startNode()
595  {
596  search();
597 
598  if(itsIteratorStack.back().value().IsArray())
599  itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
600  else
601  itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
602  }
603 
605  void finishNode()
606  {
607  itsIteratorStack.pop_back();
608  ++itsIteratorStack.back();
609  }
610 
612 
613  const char * getNodeName() const
614  {
615  return itsIteratorStack.back().name();
616  }
617 
619  void setNextName( const char * name )
620  {
621  itsNextName = name;
622  }
623 
625  template <class T, traits::EnableIf<std::is_signed<T>::value,
626  sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
627  void loadValue(T & val)
628  {
629  search();
630 
631  val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
632  ++itsIteratorStack.back();
633  }
634 
636  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
637  sizeof(T) < sizeof(uint64_t),
638  !std::is_same<bool, T>::value> = traits::sfinae> inline
639  void loadValue(T & val)
640  {
641  search();
642 
643  val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
644  ++itsIteratorStack.back();
645  }
646 
648  void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool(); ++itsIteratorStack.back(); }
650  void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
652  void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
654  void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
656  void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
658  void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
660  void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); }
661 
662  // Special cases to handle various flavors of long, which tend to conflict with
663  // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
664  #ifndef _MSC_VER
665  private:
667  template <class T> inline
668  typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
669  loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
670 
672  template <class T> inline
673  typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
674  loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
675 
677  template <class T> inline
678  typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
679  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
680 
682  template <class T> inline
683  typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
684  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
685 
686  public:
688  template <class T> inline
689  typename std::enable_if<std::is_same<T, long>::value &&
690  sizeof(T) >= sizeof(std::int64_t) &&
691  !std::is_same<T, std::int64_t>::value, void>::type
692  loadValue( T & t ){ loadLong(t); }
693 
695  template <class T> inline
696  typename std::enable_if<std::is_same<T, unsigned long>::value &&
697  sizeof(T) >= sizeof(std::uint64_t) &&
698  !std::is_same<T, std::uint64_t>::value, void>::type
699  loadValue( T & t ){ loadLong(t); }
700  #endif // _MSC_VER
701 
702  private:
704  void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
706  void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
708  void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
709 
710  public:
712  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
713  !std::is_same<T, long>::value,
714  !std::is_same<T, unsigned long>::value,
715  !std::is_same<T, std::int64_t>::value,
716  !std::is_same<T, std::uint64_t>::value,
717  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
718  inline void loadValue(T & val)
719  {
720  std::string encoded;
721  loadValue( encoded );
722  stringToNumber( encoded, val );
723  }
724 
726  void loadSize(size_type & size)
727  {
728  if (itsIteratorStack.size() == 1)
729  size = itsDocument.Size();
730  else
731  size = (itsIteratorStack.rbegin() + 1)->value().Size();
732  }
733 
735 
736  private:
737  const char * itsNextName;
738  ReadStream itsReadStream;
739  std::vector<Iterator> itsIteratorStack;
740  CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument;
741  };
742 
743  // ######################################################################
744  // JSONArchive prologue and epilogue functions
745  // ######################################################################
746 
747  // ######################################################################
749 
750  template <class T> inline
752  { }
753 
755  template <class T> inline
757  { }
758 
759  // ######################################################################
761 
762  template <class T> inline
764  { }
765 
767 
768  template <class T> inline
770  { }
771 
772  // ######################################################################
774 
775  template <class T> inline
777  { }
778 
780  template <class T> inline
782  { }
783 
784  // ######################################################################
786 
787  template <class T> inline
789  { }
790 
792 
793  template <class T> inline
795  { }
796 
797  // ######################################################################
799 
801  template <class T> inline
802  void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
803  {
804  ar.makeArray();
805  }
806 
808  template <class T> inline
810  { }
811 
812  // ######################################################################
814 
815  template <class T> inline
817  { }
818 
820  template <class T> inline
822  { }
823 
824  // ######################################################################
826 
830  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
831  !traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value,
832  !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
833  inline void prologue( JSONOutputArchive & ar, T const & )
834  {
835  ar.startNode();
836  }
837 
839  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
840  !traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value,
841  !traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
842  inline void prologue( JSONInputArchive & ar, T const & )
843  {
844  ar.startNode();
845  }
846 
847  // ######################################################################
849 
852  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
853  !traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value,
854  !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
855  inline void epilogue( JSONOutputArchive & ar, T const & )
856  {
857  ar.finishNode();
858  }
859 
861  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
862  !traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value,
863  !traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
864  inline void epilogue( JSONInputArchive & ar, T const & )
865  {
866  ar.finishNode();
867  }
868 
869  // ######################################################################
871  inline
872  void prologue( JSONOutputArchive & ar, std::nullptr_t const & )
873  {
874  ar.writeName();
875  }
876 
878  inline
879  void prologue( JSONInputArchive &, std::nullptr_t const & )
880  { }
881 
882  // ######################################################################
884  inline
885  void epilogue( JSONOutputArchive &, std::nullptr_t const & )
886  { }
887 
889  inline
890  void epilogue( JSONInputArchive &, std::nullptr_t const & )
891  { }
892 
893  // ######################################################################
895  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
896  void prologue( JSONOutputArchive & ar, T const & )
897  {
898  ar.writeName();
899  }
900 
902  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
903  void prologue( JSONInputArchive &, T const & )
904  { }
905 
906  // ######################################################################
908  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
909  void epilogue( JSONOutputArchive &, T const & )
910  { }
911 
913  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
914  void epilogue( JSONInputArchive &, T const & )
915  { }
916 
917  // ######################################################################
919  template<class CharT, class Traits, class Alloc> inline
920  void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
921  {
922  ar.writeName();
923  }
924 
926  template<class CharT, class Traits, class Alloc> inline
927  void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
928  { }
929 
930  // ######################################################################
932  template<class CharT, class Traits, class Alloc> inline
933  void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
934  { }
935 
937  template<class CharT, class Traits, class Alloc> inline
938  void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
939  { }
940 
941  // ######################################################################
942  // Common JSONArchive serialization functions
943  // ######################################################################
945  template <class T> inline
947  {
948  ar.setNextName( t.name );
949  ar( t.value );
950  }
951 
952  template <class T> inline
953  void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t )
954  {
955  ar.setNextName( t.name );
956  ar( t.value );
957  }
958 
960  inline
961  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::nullptr_t const & t)
962  {
963  ar.saveValue( t );
964  }
965 
967  inline
968  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::nullptr_t & t)
969  {
970  ar.loadValue( t );
971  }
972 
974  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
976  {
977  ar.saveValue( t );
978  }
979 
981  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
983  {
984  ar.loadValue( t );
985  }
986 
988  template<class CharT, class Traits, class Alloc> inline
989  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
990  {
991  ar.saveValue( str );
992  }
993 
995  template<class CharT, class Traits, class Alloc> inline
996  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
997  {
998  ar.loadValue( str );
999  }
1000 
1001  // ######################################################################
1003  template <class T> inline
1005  {
1006  // nothing to do here, we don't explicitly save the size
1007  }
1008 
1010  template <class T> inline
1012  {
1013  ar.loadSize( st.size );
1014  }
1015 } // namespace cereal
1016 
1017 // register archives for polymorphic support
1020 
1021 // tie input and output archives together
1023 
1024 #endif // CEREAL_ARCHIVES_JSON_HPP_
cereal::InputArchive
The base input archive class.
Definition: cereal.hpp:710
cereal::JSONInputArchive::loadValue
::type loadValue(T &t)
Loads a value from the current node - small signed overload.
Definition: json.hpp:699
cereal::prologue
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:751
cereal::JSONInputArchive::loadSize
void loadSize(size_type &size)
Loads the size for a SizeTag.
Definition: json.hpp:726
cereal::JSONOutputArchive::saveValue
void saveValue(T t)
Serialize a long if it would not be caught otherwise.
Definition: json.hpp:297
cereal::JSONOutputArchive::saveValue
void saveValue(T const &t)
Save exotic arithmetic as strings to current node.
Definition: json.hpp:314
cereal::JSONOutputArchive::saveValue
void saveValue(char const *s)
Saves a const char * to the current node.
Definition: json.hpp:260
cereal::JSONOutputArchive::Options::IndentChar
IndentChar
The character to use for indenting.
Definition: json.hpp:129
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:455
cereal::JSONOutputArchive::finishNode
void finishNode()
Designates the most recently added node as finished.
Definition: json.hpp:212
cereal::JSONOutputArchive::saveValue
void saveValue(bool b)
Saves a bool to the current node.
Definition: json.hpp:246
cereal::JSONOutputArchive::Options
A class containing various advanced options for the JSON archive.
Definition: json.hpp:119
cereal::JSONOutputArchive::~JSONOutputArchive
~JSONOutputArchive() CEREAL_NOEXCEPT
Destructor, flushes the JSON.
Definition: json.hpp:173
cereal::JSONOutputArchive::saveValue
void saveValue(int64_t i64)
Saves an int64 to the current node.
Definition: json.hpp:252
cereal::JSONOutputArchive::startNode
void startNode()
Starts a new node in the JSON output.
Definition: json.hpp:204
cereal::JSONOutputArchive
An output archive designed to save data to JSON.
Definition: json.hpp:106
cereal::JSONOutputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:240
cereal::JSONOutputArchive::saveValue
void saveValue(uint64_t u64)
Saves a uint64 to the current node.
Definition: json.hpp:254
cereal::JSONOutputArchive::Options::Options
Options(int precision=JSONWriter::kDefaultMaxDecimalPlaces, IndentChar indentChar=IndentChar::space, unsigned int indentLength=4)
Specify specific options for the JSONOutputArchive.
Definition: json.hpp:142
cereal::JSONOutputArchive::JSONOutputArchive
JSONOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream.
Definition: json.hpp:160
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
cereal::JSONOutputArchive::Options::Default
static Options Default()
Default options.
Definition: json.hpp:123
cereal::JSONInputArchive::finishNode
void finishNode()
Finishes the most recently started node.
Definition: json.hpp:605
CEREAL_REGISTER_ARCHIVE
#define CEREAL_REGISTER_ARCHIVE(Archive)
Registers a specific Archive type with cereal.
Definition: cereal.hpp:195
cereal::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:139
cereal::traits::TextArchive
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1321
cereal::OutputArchive
The base output archive class.
Definition: cereal.hpp:318
cereal::JSONOutputArchive::writeName
void writeName()
Write the name of the upcoming node and prepare object/array state.
Definition: json.hpp:334
cereal::JSONInputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:619
cereal::JSONInputArchive::loadValue
void loadValue(T &val)
Loads a value from the current node - long double and long long overloads.
Definition: json.hpp:718
CEREAL_SAVE_FUNCTION_NAME
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:92
cereal::JSONInputArchive::JSONInputArchive
JSONInputArchive(std::istream &stream)
Construct, reading from the provided stream.
Definition: json.hpp:435
cereal::JSONOutputArchive::saveValue
void saveValue(std::string const &s)
Saves a string to the current node.
Definition: json.hpp:258
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::JSONInputArchive::startNode
void startNode()
Starts a new node, going into its proper iterator.
Definition: json.hpp:594
CEREAL_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
cereal::JSONInputArchive
An input archive designed to load data from JSON.
Definition: json.hpp:419
cereal::JSONInputArchive::getNodeName
const char * getNodeName() const
Retrieves the current node name.
Definition: json.hpp:613
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:184
cereal::JSONOutputArchive::saveValue
void saveValue(std::nullptr_t)
Saves a nullptr to the current node.
Definition: json.hpp:262
cereal::RapidJSONException
An exception thrown when rapidjson fails an internal assertion.
Definition: json.hpp:39
cereal::epilogue
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:763
EnableIf
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
cereal::JSONOutputArchive::saveValue
void saveValue(int i)
Saves an int to the current node.
Definition: json.hpp:248
cereal::JSONOutputArchive::makeArray
void makeArray()
Designates that the current node should be output as an array, not an object.
Definition: json.hpp:366
cereal.hpp
Main cereal functionality.
cereal::SizeTag
A wrapper around size metadata.
Definition: helpers.hpp:312
cereal::Exception
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
cereal::JSONOutputArchive::saveValue
void saveValue(unsigned u)
Saves a uint to the current node.
Definition: json.hpp:250
cereal::DeferredData
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
cereal::JSONOutputArchive::saveValue
void saveValue(double d)
Saves a double to the current node.
Definition: json.hpp:256
cereal::size_type
CEREAL_SIZE_TYPE size_type
The size type used by cereal.
Definition: helpers.hpp:61
cereal::JSONOutputArchive::Options::NoIndent
static Options NoIndent()
Default options with no indentation.
Definition: json.hpp:126
util.hpp
Internal misc utilities.