cereal
A C++11 library for serialization
xml.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_XML_HPP_
30 #define CEREAL_ARCHIVES_XML_HPP_
31 #include "cereal/cereal.hpp"
32 #include "cereal/details/util.hpp"
33 
34 #include "cereal/external/rapidxml/rapidxml.hpp"
35 #include "cereal/external/rapidxml/rapidxml_print.hpp"
36 #include "cereal/external/base64.hpp"
37 
38 #include <sstream>
39 #include <stack>
40 #include <vector>
41 #include <limits>
42 #include <string>
43 #include <cstring>
44 #include <cmath>
45 
46 namespace cereal
47 {
48  namespace xml_detail
49  {
50  #ifndef CEREAL_XML_STRING_VALUE
51 
54  #define CEREAL_XML_STRING_VALUE "cereal"
55  #endif // CEREAL_XML_STRING_VALUE
56 
58  static const char * CEREAL_XML_STRING = CEREAL_XML_STRING_VALUE;
59 
61  inline bool isWhitespace( char c )
62  {
63  return c == ' ' || c == '\t' || c == '\n' || c == '\r';
64  }
65  }
66 
67  // ######################################################################
69 
96  class XMLOutputArchive : public OutputArchive<XMLOutputArchive>, public traits::TextArchive
97  {
98  public:
101 
104 
106  class Options
107  {
108  public:
110  static Options Default(){ return Options(); }
111 
113 
117  explicit Options( int precision_ = std::numeric_limits<double>::max_digits10,
118  bool indent_ = true,
119  bool outputType_ = false,
120  bool sizeAttributes_ = true ) :
121  itsPrecision( precision_ ),
122  itsIndent( indent_ ),
123  itsOutputType( outputType_ ),
124  itsSizeAttributes( sizeAttributes_ )
125  { }
126 
137 
140  Options & precision( int value ){ itsPrecision = value; return * this; }
142  Options & indent( bool enable ){ itsIndent = enable; return *this; }
144  Options & outputType( bool enable ){ itsOutputType = enable; return *this; }
146  Options & sizeAttributes( bool enable ){ itsSizeAttributes = enable; return *this; }
147 
149 
150  private:
151  friend class XMLOutputArchive;
152  int itsPrecision;
153  bool itsIndent;
154  bool itsOutputType;
155  bool itsSizeAttributes;
156  };
157 
159 
163  XMLOutputArchive( std::ostream & stream, Options const & options = Options::Default() ) :
165  itsStream(stream),
166  itsOutputType( options.itsOutputType ),
167  itsIndent( options.itsIndent ),
168  itsSizeAttributes(options.itsSizeAttributes)
169  {
170  // rapidxml will delete all allocations when xml_document is cleared
171  auto node = itsXML.allocate_node( rapidxml::node_declaration );
172  node->append_attribute( itsXML.allocate_attribute( "version", "1.0" ) );
173  node->append_attribute( itsXML.allocate_attribute( "encoding", "utf-8" ) );
174  itsXML.append_node( node );
175 
176  // allocate root node
177  auto root = itsXML.allocate_node( rapidxml::node_element, xml_detail::CEREAL_XML_STRING );
178  itsXML.append_node( root );
179  itsNodes.emplace( root );
180 
181  // set attributes on the streams
182  itsStream << std::boolalpha;
183  itsStream.precision( options.itsPrecision );
184  itsOS << std::boolalpha;
185  itsOS.precision( options.itsPrecision );
186  }
187 
190  {
191  const int flags = itsIndent ? 0x0 : rapidxml::print_no_indenting;
192  rapidxml::print( itsStream, itsXML, flags );
193  itsXML.clear();
194  }
195 
197 
200  void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
201  {
202  itsNodes.top().name = name;
203 
204  startNode();
205 
206  auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
207  saveValue( base64string );
208 
209  if( itsOutputType )
210  itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
211 
212  finishNode();
213  }
214 
216 
219 
222 
227  void startNode()
228  {
229  // generate a name for this new node
230  const auto nameString = itsNodes.top().getValueName();
231 
232  // allocate strings for all of the data in the XML object
233  auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
234 
235  // insert into the XML
236  auto node = itsXML.allocate_node( rapidxml::node_element, namePtr, nullptr, nameString.size() );
237  itsNodes.top().node->append_node( node );
238  itsNodes.emplace( node );
239  }
240 
242  void finishNode()
243  {
244  itsNodes.pop();
245  }
246 
248  void setNextName( const char * name )
249  {
250  itsNodes.top().name = name;
251  }
252 
254 
257  template <class T> inline
258  void saveValue( T const & value )
259  {
260  itsOS.clear(); itsOS.seekp( 0, std::ios::beg );
261  itsOS << value << std::ends;
262 
263  auto strValue = itsOS.str();
264 
265  // itsOS.str() may contain data from previous calls after the first '\0' that was just inserted
266  // and this data is counted in the length call. We make sure to remove that section so that the
267  // whitespace validation is done properly
268  strValue.resize(std::strlen(strValue.c_str()));
269 
270  // If the first or last character is a whitespace, add xml:space attribute
271  const auto len = strValue.length();
272  if ( len > 0 && ( xml_detail::isWhitespace( strValue[0] ) || xml_detail::isWhitespace( strValue[len - 1] ) ) )
273  {
274  itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "xml:space", "preserve" ) );
275  }
276 
277  // allocate strings for all of the data in the XML object
278  auto dataPtr = itsXML.allocate_string(strValue.c_str(), strValue.length() + 1 );
279 
280  // insert into the XML
281  itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
282  }
283 
285  void saveValue( uint8_t const & value )
286  {
287  saveValue( static_cast<uint32_t>( value ) );
288  }
289 
291  void saveValue( int8_t const & value )
292  {
293  saveValue( static_cast<int32_t>( value ) );
294  }
295 
297  template <class T> inline
298  void insertType()
299  {
300  if( !itsOutputType )
301  return;
302 
303  // generate a name for this new node
304  const auto nameString = util::demangledName<T>();
305 
306  // allocate strings for all of the data in the XML object
307  auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
308 
309  itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) );
310  }
311 
313  void appendAttribute( const char * name, const char * value )
314  {
315  auto namePtr = itsXML.allocate_string( name );
316  auto valuePtr = itsXML.allocate_string( value );
317  itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) );
318  }
319 
320  bool hasSizeAttributes() const { return itsSizeAttributes; }
321 
322  protected:
324  struct NodeInfo
325  {
326  NodeInfo( rapidxml::xml_node<> * n = nullptr,
327  const char * nm = nullptr ) :
328  node( n ),
329  counter( 0 ),
330  name( nm )
331  { }
332 
333  rapidxml::xml_node<> * node;
334  size_t counter;
335  const char * name;
336 
338 
341  std::string getValueName()
342  {
343  if( name )
344  {
345  auto n = name;
346  name = nullptr;
347  return {n};
348  }
349  else
350  return "value" + std::to_string( counter++ ) + "\0";
351  }
352  }; // NodeInfo
353 
355 
356  private:
357  std::ostream & itsStream;
358  rapidxml::xml_document<> itsXML;
359  std::stack<NodeInfo> itsNodes;
360  std::ostringstream itsOS;
361  bool itsOutputType;
362  bool itsIndent;
363  bool itsSizeAttributes;
364  }; // XMLOutputArchive
365 
366  // ######################################################################
368 
405  class XMLInputArchive : public InputArchive<XMLInputArchive>, public traits::TextArchive
406  {
407  public:
410 
413 
417  XMLInputArchive( std::istream & stream ) :
418  InputArchive<XMLInputArchive>( this ),
419  itsData( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() )
420  {
421  try
422  {
423  itsData.push_back('\0'); // rapidxml will do terrible things without the data being null terminated
424  itsXML.parse<rapidxml::parse_trim_whitespace | rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
425  }
426  catch( rapidxml::parse_error const & )
427  {
428  //std::cerr << "-----Original-----" << std::endl;
429  //stream.seekg(0);
430  //std::cout << std::string( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() ) << std::endl;
431 
432  //std::cerr << "-----Error-----" << std::endl;
433  //std::cerr << e.what() << std::endl;
434  //std::cerr << e.where<char>() << std::endl;
435  throw Exception("XML Parsing failed - likely due to invalid characters or invalid naming");
436  }
437 
438  // Parse the root
439  auto root = itsXML.first_node( xml_detail::CEREAL_XML_STRING );
440  if( root == nullptr )
441  throw Exception("Could not detect cereal root node - likely due to empty or invalid input");
442  else
443  itsNodes.emplace( root );
444  }
445 
446  ~XMLInputArchive() CEREAL_NOEXCEPT = default;
447 
449 
454  void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
455  {
456  setNextName( name );
457  startNode();
458 
459  std::string encoded;
460  loadValue( encoded );
461 
462  auto decoded = base64::decode( encoded );
463 
464  if( size != decoded.size() )
465  throw Exception("Decoded binary data size does not match specified size");
466 
467  std::memcpy( data, decoded.data(), decoded.size() );
468 
469  finishNode();
470  }
471 
473 
476 
479 
488  void startNode()
489  {
490  auto next = itsNodes.top().child; // By default we would move to the next child node
491  auto const expectedName = itsNodes.top().name; // this is the expected name from the NVP, if provided
492 
493  // If we were given an NVP name, look for it in the current level of the document.
494  // We only need to do this if either we have exhausted the siblings of the current level or
495  // the NVP name does not match the name of the node we would normally read next
496  if( expectedName && ( next == nullptr || std::strcmp( next->name(), expectedName ) != 0 ) )
497  {
498  next = itsNodes.top().search( expectedName );
499 
500  if( next == nullptr )
501  throw Exception("XML Parsing failed - provided NVP (" + std::string(expectedName) + ") not found");
502  }
503 
504  itsNodes.emplace( next );
505  }
506 
508  void finishNode()
509  {
510  // remove current
511  itsNodes.pop();
512 
513  // advance parent
514  itsNodes.top().advance();
515 
516  // Reset name
517  itsNodes.top().name = nullptr;
518  }
519 
522  const char * getNodeName() const
523  {
524  return itsNodes.top().getChildName();
525  }
526 
528  void setNextName( const char * name )
529  {
530  itsNodes.top().name = name;
531  }
532 
534  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
535  std::is_same<T, bool>::value> = traits::sfinae> inline
536  void loadValue( T & value )
537  {
538  std::istringstream is( itsNodes.top().node->value() );
539  is.setf( std::ios::boolalpha );
540  is >> value;
541  }
542 
544  template <class T, traits::EnableIf<std::is_integral<T>::value,
545  !std::is_same<T, bool>::value,
546  sizeof(T) == sizeof(char)> = traits::sfinae> inline
547  void loadValue( T & value )
548  {
549  value = *reinterpret_cast<T*>( itsNodes.top().node->value() );
550  }
551 
553  void loadValue( int8_t & value )
554  {
555  int32_t val; loadValue( val ); value = static_cast<int8_t>( val );
556  }
557 
559  void loadValue( uint8_t & value )
560  {
561  uint32_t val; loadValue( val ); value = static_cast<uint8_t>( val );
562  }
563 
565  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
566  !std::is_same<T, bool>::value,
567  !std::is_same<T, char>::value,
568  !std::is_same<T, unsigned char>::value,
569  sizeof(T) < sizeof(long long)> = traits::sfinae> inline
570  void loadValue( T & value )
571  {
572  value = static_cast<T>( std::stoul( itsNodes.top().node->value() ) );
573  }
574 
576  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
577  !std::is_same<T, bool>::value,
578  sizeof(T) >= sizeof(long long)> = traits::sfinae> inline
579  void loadValue( T & value )
580  {
581  value = static_cast<T>( std::stoull( itsNodes.top().node->value() ) );
582  }
583 
585  template <class T, traits::EnableIf<std::is_signed<T>::value,
586  !std::is_same<T, char>::value,
587  sizeof(T) <= sizeof(int)> = traits::sfinae> inline
588  void loadValue( T & value )
589  {
590  value = static_cast<T>( std::stoi( itsNodes.top().node->value() ) );
591  }
592 
594  template <class T, traits::EnableIf<std::is_signed<T>::value,
595  (sizeof(T) > sizeof(int)),
596  sizeof(T) <= sizeof(long)> = traits::sfinae> inline
597  void loadValue( T & value )
598  {
599  value = static_cast<T>( std::stol( itsNodes.top().node->value() ) );
600  }
601 
603  template <class T, traits::EnableIf<std::is_signed<T>::value,
604  (sizeof(T) > sizeof(long)),
605  sizeof(T) <= sizeof(long long)> = traits::sfinae> inline
606  void loadValue( T & value )
607  {
608  value = static_cast<T>( std::stoll( itsNodes.top().node->value() ) );
609  }
610 
612  void loadValue( float & value )
613  {
614  try
615  {
616  value = std::stof( itsNodes.top().node->value() );
617  }
618  catch( std::out_of_range const & )
619  {
620  // special case for denormalized values
621  std::istringstream is( itsNodes.top().node->value() );
622  is >> value;
623  if( std::fpclassify( value ) != FP_SUBNORMAL )
624  throw;
625  }
626  }
627 
629  void loadValue( double & value )
630  {
631  try
632  {
633  value = std::stod( itsNodes.top().node->value() );
634  }
635  catch( std::out_of_range const & )
636  {
637  // special case for denormalized values
638  std::istringstream is( itsNodes.top().node->value() );
639  is >> value;
640  if( std::fpclassify( value ) != FP_SUBNORMAL )
641  throw;
642  }
643  }
644 
646  void loadValue( long double & value )
647  {
648  try
649  {
650  value = std::stold( itsNodes.top().node->value() );
651  }
652  catch( std::out_of_range const & )
653  {
654  // special case for denormalized values
655  std::istringstream is( itsNodes.top().node->value() );
656  is >> value;
657  if( std::fpclassify( value ) != FP_SUBNORMAL )
658  throw;
659  }
660  }
661 
663  template<class CharT, class Traits, class Alloc> inline
664  void loadValue( std::basic_string<CharT, Traits, Alloc> & str )
665  {
666  std::basic_istringstream<CharT, Traits> is( itsNodes.top().node->value() );
667 
668  str.assign( std::istreambuf_iterator<CharT, Traits>( is ),
669  std::istreambuf_iterator<CharT, Traits>() );
670  }
671 
673  template <class T> inline
674  void loadSize( T & value )
675  {
676  value = getNumChildren( itsNodes.top().node );
677  }
678 
679  protected:
681  static size_t getNumChildren( rapidxml::xml_node<> * node )
682  {
683  size_t size = 0;
684  node = node->first_node(); // get first child
685 
686  while( node != nullptr )
687  {
688  ++size;
689  node = node->next_sibling();
690  }
691 
692  return size;
693  }
694 
696 
698  struct NodeInfo
699  {
700  NodeInfo( rapidxml::xml_node<> * n = nullptr ) :
701  node( n ),
702  child( n->first_node() ),
704  name( nullptr )
705  { }
706 
708 
709  void advance()
710  {
711  if( size > 0 )
712  {
713  --size;
714  child = child->next_sibling();
715  }
716  }
717 
719 
721  rapidxml::xml_node<> * search( const char * searchName )
722  {
723  if( searchName )
724  {
725  size_t new_size = XMLInputArchive::getNumChildren( node );
726  const size_t name_size = rapidxml::internal::measure( searchName );
727 
728  for( auto new_child = node->first_node(); new_child != nullptr; new_child = new_child->next_sibling() )
729  {
730  if( rapidxml::internal::compare( new_child->name(), new_child->name_size(), searchName, name_size, true ) )
731  {
732  size = new_size;
733  child = new_child;
734 
735  return new_child;
736  }
737  --new_size;
738  }
739  }
740 
741  return nullptr;
742  }
743 
745  const char * getChildName() const
746  {
747  return child ? child->name() : nullptr;
748  }
749 
750  rapidxml::xml_node<> * node;
751  rapidxml::xml_node<> * child;
752  size_t size;
753  const char * name;
754  }; // NodeInfo
755 
757 
758  private:
759  std::vector<char> itsData;
760  rapidxml::xml_document<> itsXML;
761  std::stack<NodeInfo> itsNodes;
762  };
763 
764  // ######################################################################
765  // XMLArchive prologue and epilogue functions
766  // ######################################################################
767 
768  // ######################################################################
770 
771  template <class T> inline
773  { }
774 
776  template <class T> inline
778  { }
779 
780  // ######################################################################
782 
783  template <class T> inline
785  { }
786 
788  template <class T> inline
790  { }
791 
792  // ######################################################################
794 
795  template <class T> inline
797  { }
798 
800  template <class T> inline
802  { }
803 
804  // ######################################################################
806 
807  template <class T> inline
809  { }
810 
812 
813  template <class T> inline
815  { }
816 
817  // ######################################################################
819 
820  template <class T> inline
821  void prologue( XMLOutputArchive & ar, SizeTag<T> const & )
822  {
823  if (ar.hasSizeAttributes())
824  {
825  ar.appendAttribute("size", "dynamic");
826  }
827  }
828 
829  template <class T> inline
830  void prologue( XMLInputArchive &, SizeTag<T> const & )
831  { }
832 
834 
835  template <class T> inline
837  { }
838 
839  template <class T> inline
840  void epilogue( XMLInputArchive &, SizeTag<T> const & )
841  { }
842 
843  // ######################################################################
845 
849  template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
850  traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
851  void prologue( XMLOutputArchive & ar, T const & )
852  {
853  ar.startNode();
854  ar.insertType<T>();
855  }
856 
858  template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
859  traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
860  void prologue( XMLInputArchive & ar, T const & )
861  {
862  ar.startNode();
863  }
864 
865  // ######################################################################
867 
870  template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
871  traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
872  void epilogue( XMLOutputArchive & ar, T const & )
873  {
874  ar.finishNode();
875  }
876 
878  template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
879  traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
880  void epilogue( XMLInputArchive & ar, T const & )
881  {
882  ar.finishNode();
883  }
884 
885  // ######################################################################
886  // Common XMLArchive serialization functions
887  // ######################################################################
888 
890  template <class T> inline
892  {
893  ar.setNextName( t.name );
894  ar( t.value );
895  }
896 
898  template <class T> inline
900  {
901  ar.setNextName( t.name );
902  ar( t.value );
903  }
904 
905  // ######################################################################
907  template <class T> inline
909  { }
910 
912  template <class T> inline
914  {
915  ar.loadSize( st.size );
916  }
917 
918  // ######################################################################
920  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
922  {
923  ar.saveValue( t );
924  }
925 
927  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
929  {
930  ar.loadValue( t );
931  }
932 
933  // ######################################################################
935  template<class CharT, class Traits, class Alloc> inline
936  void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
937  {
938  ar.saveValue( str );
939  }
940 
942  template<class CharT, class Traits, class Alloc> inline
943  void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
944  {
945  ar.loadValue( str );
946  }
947 } // namespace cereal
948 
949 // register archives for polymorphic support
952 
953 // tie input and output archives together
955 
956 #endif // CEREAL_ARCHIVES_XML_HPP_
cereal::InputArchive
The base input archive class.
Definition: cereal.hpp:710
cereal::XMLOutputArchive::appendAttribute
void appendAttribute(const char *name, const char *value)
Appends an attribute to the current top level node.
Definition: xml.hpp:313
cereal::XMLInputArchive::loadValue
void loadValue(long double &value)
Loads a type best represented as a long double from the current top node.
Definition: xml.hpp:646
cereal::XMLInputArchive::NodeInfo::name
const char * name
The NVP name for next child node.
Definition: xml.hpp:753
cereal::XMLInputArchive::loadValue
void loadValue(uint8_t &value)
Load a uint8_t from the current top node (ensures we parse entire number)
Definition: xml.hpp:559
cereal::prologue
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:751
cereal::XMLOutputArchive::NodeInfo::getValueName
std::string getValueName()
Gets the name for the next child node created from this node.
Definition: xml.hpp:341
cereal::XMLInputArchive::loadValue
void loadValue(T &value)
Loads a bool from the current top node.
Definition: xml.hpp:536
cereal::XMLOutputArchive::Options::Options
Options(int precision_=std::numeric_limits< double >::max_digits10, bool indent_=true, bool outputType_=false, bool sizeAttributes_=true)
Specify specific options for the XMLOutputArchive.
Definition: xml.hpp:117
cereal::XMLInputArchive::NodeInfo::getChildName
const char * getChildName() const
Returns the actual name of the next child node, if it exists.
Definition: xml.hpp:745
cereal::XMLInputArchive::loadBinaryValue
void loadBinaryValue(void *data, size_t size, const char *name=nullptr)
Loads some binary data, encoded as a base64 string, optionally specified by some name.
Definition: xml.hpp:454
cereal::XMLInputArchive::XMLInputArchive
XMLInputArchive(std::istream &stream)
Construct, reading in from the provided stream.
Definition: xml.hpp:417
cereal::XMLInputArchive::NodeInfo::search
rapidxml::xml_node * search(const char *searchName)
Searches for a child with the given name in this node.
Definition: xml.hpp:721
CEREAL_XML_STRING_VALUE
#define CEREAL_XML_STRING_VALUE
The default name for the root node in a cereal xml archive.
Definition: xml.hpp:54
cereal::XMLOutputArchive::XMLOutputArchive
XMLOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream upon destruction.
Definition: xml.hpp:163
cereal::XMLOutputArchive::Options
A class containing various advanced options for the XML archive.
Definition: xml.hpp:106
cereal::XMLInputArchive::value
value
Loads a type best represented as an int from the current top node.
Definition: xml.hpp:639
cereal::XMLInputArchive::getNumChildren
static size_t getNumChildren(rapidxml::xml_node<> *node)
Gets the number of children (usually interpreted as size) for the specified node.
Definition: xml.hpp:681
cereal::XMLInputArchive::loadValue
void loadValue(std::basic_string< CharT, Traits, Alloc > &str)
Loads a string from the current node from the current top node.
Definition: xml.hpp:664
cereal::XMLInputArchive::getNodeName
const char * getNodeName() const
Definition: xml.hpp:522
cereal::XMLOutputArchive::Options::outputType
Options & outputType(bool enable)
Whether to output the type of each serialized object as an attribute.
Definition: xml.hpp:144
cereal::XMLInputArchive::NodeInfo
A struct that contains metadata about a node.
Definition: xml.hpp:698
cereal::XMLOutputArchive::Options::precision
Options & precision(int value)
Sets the precision used for floaing point numbers.
Definition: xml.hpp:140
cereal::XMLOutputArchive::saveValue
void saveValue(int8_t const &value)
Overload for int8_t prevents them from being serialized as characters.
Definition: xml.hpp:291
cereal::XMLOutputArchive::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: xml.hpp:200
cereal::XMLOutputArchive::NodeInfo
A struct that contains metadata about a node.
Definition: xml.hpp:324
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
cereal::XMLOutputArchive::saveValue
void saveValue(T const &value)
Saves some data, encoded as a string, into the current top level node.
Definition: xml.hpp:258
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::XMLOutputArchive::insertType
void insertType()
Causes the type to be appended as an attribute to the most recently made node if output type is set t...
Definition: xml.hpp:298
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::XMLInputArchive::finishNode
void finishNode()
Finishes reading the current node.
Definition: xml.hpp:508
cereal::XMLOutputArchive::NodeInfo::node
rapidxml::xml_node * node
A pointer to this node.
Definition: xml.hpp:333
cereal::XMLOutputArchive::finishNode
void finishNode()
Designates the most recently added node as finished.
Definition: xml.hpp:242
CEREAL_SAVE_FUNCTION_NAME
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:92
cereal::XMLInputArchive
An output archive designed to load data from XML.
Definition: xml.hpp:405
cereal::XMLInputArchive::NodeInfo::size
size_t size
The remaining number of children for this node.
Definition: xml.hpp:752
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::XMLInputArchive::loadSize
void loadSize(T &value)
Loads the size of the current top node.
Definition: xml.hpp:674
CEREAL_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
cereal::XMLInputArchive::NodeInfo::child
rapidxml::xml_node * child
A pointer to its current child.
Definition: xml.hpp:751
cereal::XMLOutputArchive::NodeInfo::name
const char * name
The name for the next child node.
Definition: xml.hpp:335
cereal::XMLOutputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: xml.hpp:248
cereal::epilogue
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:763
cereal::XMLInputArchive::NodeInfo::advance
void advance()
Advances to the next sibling node of the child.
Definition: xml.hpp:709
cereal::XMLInputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: xml.hpp:528
cereal::XMLOutputArchive::saveValue
void saveValue(uint8_t const &value)
Overload for uint8_t prevents them from being serialized as characters.
Definition: xml.hpp:285
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::XMLInputArchive::startNode
void startNode()
Prepares to start reading the next node.
Definition: xml.hpp:488
cereal::XMLOutputArchive::Options::sizeAttributes
Options & sizeAttributes(bool enable)
Whether dynamically sized containers (e.g. vector) output the size=dynamic attribute.
Definition: xml.hpp:146
cereal::DeferredData
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
cereal::XMLInputArchive::NodeInfo::node
rapidxml::xml_node * node
A pointer to this node.
Definition: xml.hpp:750
cereal::XMLInputArchive::loadValue
void loadValue(int8_t &value)
Load an int8_t from the current top node (ensures we parse entire number)
Definition: xml.hpp:553
cereal::xml_detail::isWhitespace
bool isWhitespace(char c)
Returns true if the character is whitespace.
Definition: xml.hpp:61
cereal::XMLOutputArchive::Options::indent
Options & indent(bool enable)
Whether to indent each line of XML.
Definition: xml.hpp:142
cereal::XMLOutputArchive::startNode
void startNode()
Creates a new node that is a child of the node at the top of the stack.
Definition: xml.hpp:227
cereal::XMLOutputArchive
An output archive designed to save data to XML.
Definition: xml.hpp:96
cereal::XMLOutputArchive::NodeInfo::counter
size_t counter
The counter for naming child nodes.
Definition: xml.hpp:334
util.hpp
Internal misc utilities.
cereal::XMLOutputArchive::Options::Default
static Options Default()
Default options.
Definition: xml.hpp:110
cereal::XMLOutputArchive::~XMLOutputArchive
~XMLOutputArchive() CEREAL_NOEXCEPT
Destructor, flushes the XML.
Definition: xml.hpp:189