MIRA
XMLSerializer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_XMLSERIALIZER_H_
48 #define _MIRA_XMLSERIALIZER_H_
49 
50 #include <iostream>
51 #include <list>
52 #include <algorithm>
53 #include <vector>
54 
55 #ifndef Q_MOC_RUN
56 #include <boost/algorithm/string.hpp>
57 #include <boost/range/algorithm.hpp>
58 #include <boost/range/algorithm_ext/erase.hpp>
59 #endif
60 
64 
65 #include <xml/XMLDom.h>
66 
67 namespace mira {
68 
70 
72 namespace Private {
73 
74 inline std::string replaceSpaces(const std::string& s)
75 {
76  return boost::replace_all_copy(s, " ", "_");
77 }
78 
79 inline std::string replaceSpecialChars(const std::string& s)
80 {
81  std::string result = boost::replace_all_copy(s, " ", "_");
82  boost::remove_erase_if(result, boost::is_any_of("[]"));
83  return result;
84 }
85 
86 } // namespace
87 
89 
121 
122 class XMLSerializer : public Serializer<XMLSerializer>
123 {
125 
126 public:
128 
131  {
132  STANDARD = 0x00,
133  NO_COMMENTS = 0x01,
134  COMPRESSED = 0x02,
135  };
136 
137  MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) // generate logical operators for enum values
138 
139 
146  mRoot(iXmlDom.root()), mNode(iXmlDom.root()), mOutputFormat(format)
147  {
148  }
149 
157  mRoot(iRoot), mNode(iRoot), mOutputFormat(format)
158  {
159  }
160 
162 
163  template <typename T>
164  VersionType version(VersionType version, const T* caller = NULL)
165  {
166  return this->version<T>(version, false);
167  }
168 
169  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
171  {
172  // add version - backward compatible variant if no caller type provided
173  return versionLegacy(version);
174  }
175 
176  template <typename T>
178  {
179  return this->version<T>(version, true);
180  }
181 
182 private:
183 
184  template <typename T>
185  VersionType version(VersionType version, bool acceptDesiredVersion)
186  {
187  version = this->template queryDesiredClassVersion<T>(version, acceptDesiredVersion);
188 
189  int vf = this->forcedSerializeVersion();
190  if ((vf == 0) || (vf == 1))
191  return versionLegacy(version);
192 
193  // add version
194  mNode.add_child("version").add_attribute("type", typeName<T>())
195  .add_content(toString((int)version));
196  return version;
197  }
198 
199  VersionType versionLegacy(VersionType version)
200  {
201  mNode.add_attribute("version", toString((int)version) );
202  return version;
203  }
204 
205 public:
206 
207  template<typename T>
208  void atomic(T& member)
209  {
210  const ReflectMemberMeta& meta = getCurrentMemberMeta();
211  if (mOutputFormat & COMPRESSED)
212  mNode.add_attribute(Private::replaceSpecialChars(meta.id), toString(member,12));
213  else
214  {
215  if(!(mOutputFormat & NO_COMMENTS) && meta.comment!=NULL && strlen(meta.comment)>0)
216  mNode.add_comment(meta.comment);
217  mNode.add_child(Private::replaceSpaces(meta.name)).add_content(toString(member,12));
218  }
219  }
220 
221  template<typename T>
222  void object(T& member)
223  {
224  const ReflectMemberMeta& meta = getCurrentMemberMeta();
225 
226  // create a new node
227  if(!(mOutputFormat & NO_COMMENTS) && meta.comment!=NULL && strlen(meta.comment)>0)
228  mNode.add_comment(meta.comment);
229  XMLDom::iterator i = mNode.add_child(Private::replaceSpaces(meta.name));
230 
231  // enter the new node
232  mNode = i;
233 
234  if(!mPointerClass.empty()) {
235  mNode.add_attribute("class", mPointerClass);
236  mPointerClass.clear();
237  }
238 
240 
241  // leave the node
242  mNode = mNode.parent();
243  assert(mNode!=mRoot.end());
244 
245  }
246 
247  // Stores a reference to a previously serialized object using the "ref" attribute.
248  void pointerReference(int referencedObjectID) {
249  const char* name = getCurrentMemberMeta().name;
250  mNode.add_child(Private::replaceSpaces(name)).add_attribute("ref", this->getHumanReadableFullID(referencedObjectID));
251  }
252 
253  // Stores the class type the "class" attribute.
254  void pointerWithClassType(const std::string& type) {
255  mPointerClass = type;
256  //mNode.add_attribute("class", type);
257  }
258 
259  // Stores a NULL pointer using the "nullptr" attribute.
260  void pointerNull() {
261  const char* name = getCurrentMemberMeta().name;
262  mNode.add_child(Private::replaceSpaces(name)).add_attribute("nullptr", "true");
263  }
264 
265 public:
266 
268  XMLDom::iterator getNode() { return mNode; }
269 
270 private:
271 
273  XMLDom::iterator mRoot;
274 
275  // iterator to the current node
276  XMLDom::iterator mNode;
277 
278  std::string mPointerClass;
279 
280  OutputFormat mOutputFormat;
281 
282 };
283 
285 
315 {
317 public:
318 
323  XMLDeserializer(const XMLDom& iXmlDom) :
324  mRoot(iXmlDom.root()), mNode(iXmlDom.root())
325  {
326  }
327 
333  mRoot(iRoot), mNode(iRoot)
334  {
335  }
336 
337 
340  template <typename T>
341  void deserialize(const std::string& name, T& value)
342  {
343  mDeserializeFromThisNode=false;
344  mNextFindIteratorStack.clear();
345  pushFindStack();
346  // since we deserialize just an element of root we must not add all children from root
347  mUnprocessedChildren.emplace();
348  try {
349  Base::deserialize(name,value);
350  } catch (Exception& ex) {
351  MIRA_RETHROW(ex, "in tag starting at: " << mNode.uri() << "(" << mNode.line() << ")");
352  }
353  popFindStack();
354  popUnprocessedChildren();
355  }
356 
361  template <typename T>
362  void deserializeFromNode(const char* name, T& value)
363  {
364  mDeserializeFromThisNode=true;
365  mNextFindIteratorStack.clear();
366  pushFindStack();
367  pushUnprocessedChildren(mNode);
368  try {
369  Base::deserialize(name,value);
370  } catch (Exception& ex) {
371  MIRA_RETHROW(ex, "in tag starting at: " << mNode.uri()
372  << "(" << mNode.line() << ")");
373  }
374  popFindStack();
375  popUnprocessedChildren();
376  }
377 
379 
380  template <typename T>
381  VersionType version(VersionType expectedVersion, const T* caller = NULL)
382  {
383  // obtain version
384 
385  int vf = this->forcedDeserializeVersion();
386  if ((vf == 0) || (vf == 1))
387  return versionLegacy(expectedVersion);
388 
389  std::string type = typeName<T>();
390  for (int n = 0; true; ++n) {
391  XMLDom::const_sibling_iterator versionNode = mNode.find("version", n);
392  if (versionNode == mNode.cend()) {
393  if (mNode.has_attribute("version")) {
394  MIRA_LOG(WARNING) << "Failed finding version for type '" << type << "', "
395  "but read an anonymous version attribute instead. "
396  "Please update your config xml ("
397  << mNode.uri() << " , line " << mNode.line() << ").";
398 
399  VersionType version = mNode.get_attribute<int>("version");
400  checkVersion<T>(version, expectedVersion);
401  return version;
402  }
403  return 0;
404  }
405 
406  markChildAsProcessed(versionNode);
407 
408  // 'version' elements without 'type' attribute are ignored here, allowing
409  // to still use 'version' as part of the actual data
410  if (versionNode.get_attribute<std::string>("type", "") == type) {
411  VersionType version = fromString<int>(*versionNode.content_begin());
412  checkVersion<T>(version, expectedVersion);
413  return version;
414  }
415  }
416  }
417 
418  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
419  VersionType version(VersionType expectedVersion))
420  {
421  // obtain version - backward compatible variant if no caller type provided
422  return versionLegacy(expectedVersion);
423  }
424 
425  template <typename T>
426  VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T* caller = NULL)
427  {
428  return this->version<T>(expectedVersion);
429  }
430 
431 private:
432 
433  VersionType versionLegacy(VersionType expectedVersion)
434  {
435  VersionType version = mNode.get_attribute<int>("version", 0);
436  checkVersion<void>(version, expectedVersion);
437  return version;
438  }
439 
440  template <typename T>
441  void checkVersion(VersionType version, VersionType expectedVersion)
442  {
443  if (version > expectedVersion) {
444  MIRA_LOG(WARNING) << "Trying to deserialize XML data of a newer version (" << (int)version <<
445  ") of type " << typeName<T>() << " into an older version (" << (int)expectedVersion << ").";
446  }
447  }
448 
449 public:
450 
451  template<typename T>
452  void atomic(T& member)
453  {
454  Base::atomic(member);
455 
456  if(mAtomicFromAttribute.empty())
457  member = fromString<T>(*mNode.content_begin());
458  else // try to get the value from the attribute
459  // (which should exists, since this is checked in invokeMemberOverwrite)
460  member = mNode.get_attribute<T>(mAtomicFromAttribute); //uses fromString<T> internally
461  }
462 
463  void beginTag(const ReflectMemberMeta& meta)
464  {
465  if(meta.name!=NULL) {
466  if(!mAtomicFromAttribute.empty()) {
467  MIRA_THROW(XIO, "Cannot deserialize '" << mAtomicFromAttribute <<
468  "' from an attribute as it is a complex type, that "
469  "must be stored as an XML node.");
470  }
471 
472  XMLDom::const_iterator i = findNext(Private::replaceSpaces(meta.name));
473  if(i!=mNode.end()) {
474  // found it, so set it as current node
475  mNode = i;
476  } else {
477  // node not found
478  MIRA_THROW(XMemberNotFound, "Node '"
479  << Private::replaceSpaces(meta.name)
480  << "' is missing"); // hence we have to abort with an exception
481  }
482  pushFindStack();
483  pushUnprocessedChildren(mNode);
484  }
485  }
486 
487  void endTag(const ReflectMemberMeta& meta)
488  {
489  if(meta.name!=NULL) {
490  assert(mNode!=mRoot); // we will never go above the root node.
491  popFindStack();
492  popUnprocessedChildren();
493  markChildAsProcessed(mNode);
494  mNode = mNode.parent();
495  assert(mNode!=mRoot.end());
496  }
497  }
498 
499  /*
500  * Overwrites Deserializer::pointer.
501  * This method checks, if there is a pointer reference specified
502  * (the ref attribute is present). If so, it reads the referenced full id
503  * of the previously stored object and uses resolveReference() to get the
504  * pointer to that previously deserialized object.
505  * Otherwise it calls pointer() of the Deserializer base class to
506  * deserialize the full object.
507  */
508  template<typename T>
509  void pointer(T* &pointer)
510  {
511  // do we have a null pointer?
512  if(fromString<bool>(mNode.get_attribute<std::string>("nullptr", "false"))) {
513  pointer = NULL;
514  return;
515  }
516 
517  // do we have a reference?
518  std::string ref = mNode.get_attribute<std::string>("ref","");
519  if(ref.size()>0) {
520  // we have a reference, so resolve it
521  pointer = resolveReference<T>(ref);
522  return;
523  }
524 
525  // we have a "normal" pointer, so deserialize it
526  Base::pointer(pointer);
527  }
528 
529  std::string pointerClassType()
530  {
531  return mNode.get_attribute<std::string>("class","");
532  }
533 
534  // hijack the invokeOverwrite method for adding a starting and closing tag
535  // around the serialized data
536  template<typename T>
537  void invokeMemberOverwrite(T& member, const ReflectMemberMeta& meta)
538  {
539  bool fromThisNode = mDeserializeFromThisNode;
540  bool fromAttribute = false;
541 
542  if(!fromThisNode) {
543  try {
544  beginTag(meta);
545  } catch(XMemberNotFound& ex) {
546  // member of value not found, if it is an atomic type
547  // we can still try to get the value from an attribute with
548  // the same name
549  // (however, the following reserved attributes are
550  // not allowed: version, nullptr, ref, class)
551  std::string id = Private::replaceSpecialChars(meta.id);
552  try {
553  if(id!="version" &&
554  id!="nullptr" &&
555  id!="ref" &&
556  id!="class")
557  {
558  // check if the attribute exists
559  if(!mNode.has_attribute(id)) {
560  MIRA_THROW(XMemberNotFound, "Node (or attribute) '" << id <<
561  "' is missing");
562  }
563  mAtomicFromAttribute = id;
564  fromAttribute = true;
565  } else {
566  // otherwise rethrow the exception since we cannot do anything
567  throw;
568  }
569  }
570  catch(Exception& ex) {
571  MIRA_RETHROW(ex, "in tag starting at: " << mNode.uri() << "(" << mNode.line() << ")");
572  }
573 
574  }
575  }
576 
577  mDeserializeFromThisNode=false;
578 
579  try {
580  Base::invokeMemberOverwrite(member, meta);
581  } catch(...) {
582  // make sure our find stack is correctly unwound and the correct
583  // node in the XML file is maintained if an exception
584  // is thrown somewhere in our child nodes (fixes #536)
585  mAtomicFromAttribute.clear();
586  if(!fromThisNode && !fromAttribute) {
587  endTag(meta); // finish this tag and ...
588  rewindFindIterator(meta.getName()); // ... 'undo' read so we can re-try in a handler and ...
589  }
590  throw; // ... rethrow
591  }
592 
593  // hm, this cleanup code is a duplicate of the above cleanup
594  // code in the event of an exception
595  mAtomicFromAttribute.clear();
596  if(!fromThisNode && !fromAttribute)
597  endTag(meta);
598  }
599 
600 public: // accessors for special serialize/deserialize methods below
601 
602  XMLDom::const_iterator getNode() { return mNode; }
603 
604 private:
605 
608 
611 
612  bool mDeserializeFromThisNode;
613 
619  std::string mAtomicFromAttribute;
620 
621 private:
622  // Necessary to allow multiple nodes with the same name.
623  // Here we store the iterators of previous searches for
624  // a certain nodes, the next search will then continue
625  // after the previous found iterator.
626  // Those iterators must be stored in a stack for each
627  // level of the XML tree.
628  typedef std::map<std::string, XMLDom::const_iterator> NextFindIteratorMap;
629  std::list<NextFindIteratorMap> mNextFindIteratorStack;
630 
631  XMLDom::const_iterator findNext(const std::string& name)
632  {
633  assert(mNextFindIteratorStack.size()>=1);
634  NextFindIteratorMap& m = mNextFindIteratorStack.back();
635 
636  XMLDom::const_iterator i = mNode.end();
637  XMLDom::const_iterator j = mNode.begin();
638 
639  // check if we have searched for the name already
640  NextFindIteratorMap::iterator p = m.find(name);
641  if(p!=m.end()) {
642  // we already searched for name
643  // so continue search from successor of previous find
644  j = p->second;
645  ++j;
646  }
647  i = find(j, mNode.end(), name);
648 
649  // if we found something, save the position for next search
650  if(i!=mNode.end())
651  m[name] = i;
652 
653  return i;
654  }
655 
656  // is called when we enter a new node
657  void pushFindStack()
658  {
659  mNextFindIteratorStack.push_back(NextFindIteratorMap());
660  }
661 
662  // is called when we leave a node
663  void popFindStack()
664  {
665  mNextFindIteratorStack.pop_back();
666  }
667 
668  void rewindFindIterator(const std::string& name)
669  {
670  assert(mNextFindIteratorStack.size()>=1);
671  NextFindIteratorMap& m = mNextFindIteratorStack.back();
672 
673  NextFindIteratorMap::iterator p = m.find(name);
674  if(p==m.end())
675  return;
676 
677  if (m[name] == mNode.begin())
678  m.erase(name);
679  else
680  --(m[name]);
681  }
682 
683  std::stack<std::vector<XMLDom::const_iterator>> mUnprocessedChildren;
684 
685  void pushUnprocessedChildren(XMLDom::const_iterator parent)
686  {
687  std::vector<XMLDom::const_iterator> children;
688  for (auto it = parent.begin(); it != parent.end(); ++it) {
689  children.push_back(it);
690  }
691  mUnprocessedChildren.push(std::move(children));
692  }
693 
694  void popUnprocessedChildren()
695  {
696  auto& unprocessedChildren = mUnprocessedChildren.top();
697  for (auto& child : unprocessedChildren) {
698  constexpr static auto mayBeIgnoredAttr = "__may_be_ignored__";
699  if (child.get_attribute(mayBeIgnoredAttr, false)) {
700  continue;
701  }
702  MIRA_LOG(ERROR) << "XML tag " << *child << " (originating from " << child.uri() << ":" << child.line()
703  << ") is not used during deserialization";
704  }
705  mUnprocessedChildren.pop();
706  }
707 
708  void markChildAsProcessed(XMLDom::const_iterator child)
709  {
710  auto& unprocessedChildren = mUnprocessedChildren.top();
711  auto it = std::remove(unprocessedChildren.begin(), unprocessedChildren.end(), child);
712  unprocessedChildren.erase(it, unprocessedChildren.end());
713  }
714 
715 public:
717  {
718  auto& unprocessedChildren = mUnprocessedChildren.top();
719  unprocessedChildren.clear();
720  }
721 };
722 
724 
725 // specializations for STL containers
726 
727 namespace serialization { // our private namespace
728 
730 
738 template<typename Collection>
739 struct ReflectCollectionCount<XMLSerializer, Collection>
740 {
741  static void reflect(XMLSerializer& r, uint32& ioCount)
742  {
743  // do nothing
744  }
745 };
746 
747 template<typename Collection, bool HasKeyType = true, bool HasMappedType = true>
748 struct CheckKeyCount
749 {
750  static void check(XMLDom::const_iterator node, uint32 itemCount)
751  {
752  // nothing to do here if Collection is not a map (default)
753  }
754 };
755 
756 // if Collection has a definition for key_type and mapped_type (other than void), assume it is a map
757 // -> expect a <key> tag for each <item> tag
758 // (key_type alone is not sufficient as it also exists e.g. in std::set)
759 template<typename Collection>
760 struct CheckKeyCount<Collection,
761  (bool)!std::is_void_v<typename Collection::key_type>,
762  (bool)!std::is_void_v<typename Collection::mapped_type>>
763 {
764  struct IsKey {
765  bool operator()(const XMLDom::Attribute& attr) {
766  return boost::algorithm::starts_with(attr.first, "key");
767  }
768  };
769 
770  static void check(XMLDom::const_iterator node, uint32 itemCount)
771  {
772  uint32 keyCount = (uint32)std::count(node.begin(), node.end(), "key");
773 
774  if (keyCount == 0) {
775  // there might be attributes instead
776  keyCount = (uint32)std::count_if(node.attribute_cbegin(), node.attribute_cend(),
777  IsKey());
778  }
779  if (keyCount != itemCount) {
780  MIRA_THROW(XIO, "Node for map (or map-like collection) has " << keyCount
781  << " <key> tags and " << itemCount << " <item> tags.");
782  }
783  }
784 };
785 
792 template<typename Collection>
793 struct ReflectCollectionCount<XMLDeserializer, Collection>
794 {
795  struct IsItem {
796  bool operator()(const XMLDom::Attribute& attr) {
797  return boost::algorithm::starts_with(attr.first, "item");
798  }
799  };
800 
801  static void reflect(XMLDeserializer& r, uint32& ioCount)
802  {
803  XMLDom::const_iterator node = r.getNode();
804 
805  // count the "item" nodes
806  ioCount = (uint32)std::count(node.begin(), node.end(), "item");
807 
808  if (ioCount == 0) {
809  // there might be attributes instead
810  ioCount = (uint32)std::count_if(node.attribute_cbegin(), node.attribute_cend(),
811  IsItem());
812  }
813 
814  CheckKeyCount<Collection>::check(node, ioCount);
815  }
816 };
817 
818 template<typename Reflector, typename Container> struct ReflectReadMapItems;
819 
824 template<typename Container>
825 struct ReflectReadMapItems<XMLSerializer, Container>
826 {
827  typedef typename Container::value_type value_type;
828  typedef typename Container::key_type key_type;
829 
830  static void reflect(XMLSerializer& r, Container& c)
831  {
832  // store each item
833  int id=0;
834  foreach(value_type& p, c)
835  {
836  key_type& nonconstkey = const_cast<key_type&>(p.first);
837  // no tracking on this one, see ReflectReadMapPair
838  MIRA_MEMBER_WITH_ID(r, "key", "key["+toString(id)+"]", nonconstkey, "",
840 
841  // the values can be reflected/deserialized with tracking
842  MIRA_PROPERTY_WITH_ID(r, "item", "item["+toString(id)+"]", p.second, "");
843 
844  ++id;
845  }
846  }
847 };
848 
849 template<typename Reflector, typename Container> struct ReflectWriteMapItems;
850 
855 template<typename Container>
856 struct ReflectWriteMapItems<XMLDeserializer, Container>
857 {
858  typedef typename Container::iterator iterator;
859  typedef typename Container::value_type value_type;
860  typedef typename Container::key_type key_type;
861  typedef typename Container::mapped_type mapped_type;
862 
863  static void reflect(XMLDeserializer& r, Container& c, uint32 count)
864  {
865  iterator hint = c.begin();
866 
867  // reflect key
868  key_type key;
869 
870  for(uint32 id=0; id<count; ++id) {
871 
872  if(IsPointerOrSharedPointer<key_type>::value) {
873  MIRA_MEMBER_WITH_ID(r, "key", "key["+toString(id)+"]", key, "");
874  } else {
875  // we have to deserialize the key to a temp object, cannot restore references to it !!!
876  MIRA_MEMBER_WITH_ID(r, "key", "key["+toString(id)+"]", key, "", REFLECT_CTRLFLAG_TEMP_TRACKING);
877  }
878 
879  // insert a dummy value with the key
880  iterator it = c.insert(hint, value_type(key, mapped_type()));
881  hint = it; // the iterator will be insertion hint for next element
882 
883  // reflect the value directly into the map item
884  // the values can be reflected/deserialized with tracking
885  MIRA_PROPERTY_WITH_ID(r, "item", "item["+toString(id)+"]", it->second, "");
886  }
887  }
888 };
889 
891 
892 } // namespace
893 
895 
897 
898 } // namespace
899 
900 #endif
This object can use object tracking internally, but the object tracking system&#39;s state remains unchan...
Definition: ReflectControlFlags.h:82
T get_attribute(const std::string &name) const
Return an attribute value cast to a given type.
Definition: XMLDom.h:719
Provides type trait that indicates whether a type is a pointer type or a shared pointer.
A STL conform DOM reader/writer for XML.
Container::iterator iterator
Definition: StlCollections.h:393
void object(T &member)
Is called for each complex object.
Definition: RecursiveMemberReflector.h:321
A STL conform wrapper for libxml2 to read XML files as DOM.
Definition: XMLDom.h:74
std::string getName() const
Definition: ReflectMemberMeta.h:82
const_sibling_iterator end() const
Get the const end node sibling_iterator.
Definition: XMLDom.h:628
MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)", VersionType version(VersionType expectedVersion))
Definition: XMLSerializer.h:418
Contains the Serializer template, a base class for all serializers.
std::string pointerClassType()
Definition: XMLSerializer.h:529
#define MIRA_PROPERTY_WITH_ID(reflector, name, id, var,...)
Definition: ReflectorInterface.h:1009
typename ReflectorInterface< XMLSerializer >::AcceptDesiredVersion AcceptDesiredVersion
Definition: AbstractReflector.h:195
void deserialize(const std::string &name, T &value)
overwritten from Deserializer, to handle exceptions and to add additional information about file name...
Definition: XMLSerializer.h:341
Definition: XMLSerializer.h:122
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:883
OutputFormat format
Definition: XMLSerializer.h:145
const std::string & getHumanReadableFullID(int objectID) const
Returns the full human readable object id / name for the given internal objectID. ...
Definition: Serializer.h:465
XMLDom::iterator getNode()
Accessor for special serialize/deserialize methods below.
Definition: XMLSerializer.h:268
VersionType version(VersionType version, AcceptDesiredVersion, const T *caller=NULL)
Definition: XMLSerializer.h:177
Is a special reflector that is used for serialization.
Definition: Serializer.h:126
XMLDeserializer(const XMLDom::const_iterator &iRoot)
Create a new XML deserialization on top of the passed XMLDom iterator node.
Definition: XMLSerializer.h:332
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
STL namespace.
uint32_t uint32
Definition: Types.h:64
#define MIRA_RETHROW(ex, msg)
Macro for rethrowing an exception with file and line information and for adding additional informatio...
Definition: Exception.h:144
No comments are written to output document.
Definition: XMLSerializer.h:133
Stores meta information for each member.
Definition: ReflectMemberMeta.h:64
const_content_iterator content_begin() const
Get the const iterator to the first content.
Definition: XMLDom.h:643
const char * name
The name (as specified in the XML file).
Definition: ReflectMemberMeta.h:67
sibling_iterator end()
Get the end node sibling_iterator.
VersionType version(VersionType version, const T *caller=NULL)
Definition: XMLSerializer.h:164
uint8 VersionType
Definition: ReflectorInterface.h:72
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
std::string toString(const T &value, int precision=-1)
Converts any data type to string (the data type must support the stream << operator).
Definition: ToString.h:252
Const sibling_iterator for iterating over xml nodes that have the same parent (siblings) ...
Definition: XMLDom.h:763
Serializer for serializing objects in XML format.
Definition: XMLSerializer.h:120
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:479
XMLDom::sibling_iterator & add_content(const std::string &content)
Add content to this node.
static void reflect(Reflector &r, uint32 &ioCount)
Definition: ReflectCollection.h:71
std::pair< std::string, std::string > Attribute
An XML attribute.
Definition: XMLDom.h:87
static void reflect(Reflector &r, Container &c)
Definition: StlCollections.h:343
static void reflect(Reflector &r, Container &c, uint32 count)
Definition: StlCollections.h:395
XMLDom::sibling_iterator & add_attribute(const Attribute &attribute)
Add an attribute to this node.
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
Default format.
Definition: XMLSerializer.h:132
Contains base class for all deserializers.
void endTag(const ReflectMemberMeta &meta)
Definition: XMLSerializer.h:487
void markAllChildrenAsProcessed()
Definition: XMLSerializer.h:716
Container::value_type value_type
Definition: StlCollections.h:341
OutputFormat
Flags for XML output format.
Definition: XMLSerializer.h:130
const_sibling_iterator begin() const
Get the const sibling_iterator to the first sub node.
Definition: XMLDom.h:602
void pointerNull()
Definition: XMLSerializer.h:260
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
Definition: XMLSerializer.h:537
const_sibling_iterator cend() const
Get the const end node sibling_iterator.
XMLDom::sibling_iterator & add_comment(const std::string &comment)
Add a comment to this node.
void pointer(T *&pointer)
Definition: XMLSerializer.h:509
Iterator for iterating over xml nodes that have the same parent (sibligs)
Definition: XMLDom.h:850
const char * comment
Additional user comments.
Definition: ReflectMemberMeta.h:76
void object(T &member)
Definition: XMLSerializer.h:222
Base class for exceptions.
Definition: Exception.h:195
Base::VersionType VersionType
Definition: Serializer.h:154
serialization::VersionType VersionType
Definition: XMLSerializer.h:378
VersionType version(VersionType expectedVersion, const T *caller=NULL)
Definition: XMLSerializer.h:381
typename ReflectorInterface< XMLSerializer >::VersionType VersionType
Definition: AbstractReflector.h:165
static int forcedSerializeVersion()
Returns either the version number from value of environment variable &#39;MIRA_FORCE_SERIALIZE_VERSION&#39;, or -1 (= do not force a version).
Definition: Serializer.h:145
void pointerWithClassType(const std::string &type)
Definition: XMLSerializer.h:254
const_sibling_iterator const_iterator
Definition: XMLDom.h:1205
Definition: LoggingCore.h:76
void atomic(T &member)
Definition: XMLSerializer.h:452
sibling_iterator parent()
Get the parent node sibling_iterator for this node.
VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T *caller=NULL)
Definition: XMLSerializer.h:426
#define MIRA_MEMBER_WITH_ID(reflector, name, id, var,...)
Macro that should be used to reflect a member if a manually specified ID is used. ...
Definition: ReflectorInterface.h:1003
atomic members are written as attributes instead of childs
Definition: XMLSerializer.h:134
void deserializeFromNode(const char *name, T &value)
In contrast to the deserialize() method this method will use the node that was specified in the const...
Definition: XMLSerializer.h:362
XMLDom::sibling_iterator add_child(const std::string &name, const NameSpace &ns=NameSpace())
Add a sub node to this node.
void atomic(T &member)
Definition: XMLSerializer.h:208
XMLDeserializer(const XMLDom &iXmlDom)
Create a new XML deserialization on top of the passed XMLDom document.
Definition: XMLSerializer.h:323
MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)", VersionType version(VersionType version))
Definition: XMLSerializer.h:169
Definition: LoggingCore.h:75
void beginTag(const ReflectMemberMeta &meta)
Definition: XMLSerializer.h:463
MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) XMLSerializer(XMLDom &iXmlDom
Create a new XML serialization on top of the passed XMLDom document.
const char * id
The id (used for containers where the name is identical, in all other cases the id usually is equal t...
Definition: ReflectMemberMeta.h:73
void pointerReference(int referencedObjectID)
Definition: XMLSerializer.h:248
bool fromString< bool >(const std::string &str)
Specialization for bool.
Definition: ToString.h:386
XMLDom::const_iterator getNode()
Definition: XMLSerializer.h:602
XMLSerializerTag Tag
Definition: XMLSerializer.h:127
Deserializer for serializing objects from XML format.
Definition: XMLSerializer.h:314
const_sibling_iterator find(const std::string &name, std::size_t nth=0) const
Find the nth subnode with a given name.