47 #ifndef _MIRA_XMLSERIALIZER_H_ 48 #define _MIRA_XMLSERIALIZER_H_ 56 #include <boost/algorithm/string.hpp> 57 #include <boost/range/algorithm.hpp> 58 #include <boost/range/algorithm_ext/erase.hpp> 74 inline std::string replaceSpaces(
const std::string& s)
76 return boost::replace_all_copy(s,
" ",
"_");
79 inline std::string replaceSpecialChars(
const std::string& s)
81 std::string result = boost::replace_all_copy(s,
" ",
"_");
82 boost::remove_erase_if(result, boost::is_any_of(
"[]"));
146 mRoot(iXmlDom.root()), mNode(iXmlDom.root()), mOutputFormat(
format)
157 mRoot(iRoot), mNode(iRoot), mOutputFormat(
format)
163 template <
typename T>
166 return this->version<T>(
version,
false);
176 template <
typename T>
179 return this->version<T>(
version,
true);
184 template <
typename T>
187 version = this->
template queryDesiredClassVersion<T>(
version, acceptDesiredVersion);
190 if ((vf == 0) || (vf == 1))
234 if(!mPointerClass.empty()) {
236 mPointerClass.clear();
243 assert(mNode!=mRoot.
end());
255 mPointerClass =
type;
278 std::string mPointerClass;
324 mRoot(iXmlDom.root()), mNode(iXmlDom.root())
333 mRoot(iRoot), mNode(iRoot)
340 template <
typename T>
343 mDeserializeFromThisNode=
false;
344 mNextFindIteratorStack.clear();
347 mUnprocessedChildren.emplace();
349 Base::deserialize(name,value);
351 MIRA_RETHROW(ex,
"in tag starting at: " << mNode.uri() <<
"(" << mNode.line() <<
")");
354 popUnprocessedChildren();
361 template <
typename T>
364 mDeserializeFromThisNode=
true;
365 mNextFindIteratorStack.clear();
367 pushUnprocessedChildren(mNode);
369 Base::deserialize(name,value);
372 <<
"(" << mNode.line() <<
")");
375 popUnprocessedChildren();
380 template <
typename T>
385 int vf = this->forcedDeserializeVersion();
386 if ((vf == 0) || (vf == 1))
387 return versionLegacy(expectedVersion);
389 std::string
type = typeName<T>();
390 for (
int n = 0;
true; ++n) {
392 if (versionNode == mNode.
cend()) {
393 if (mNode.has_attribute(
"version")) {
395 "but read an anonymous version attribute instead. " 396 "Please update your config xml (" 397 << mNode.uri() <<
" , line " << mNode.line() <<
").";
399 VersionType version = mNode.get_attribute<
int>(
"version");
400 checkVersion<T>(version, expectedVersion);
406 markChildAsProcessed(versionNode);
412 checkVersion<T>(version, expectedVersion);
422 return versionLegacy(expectedVersion);
425 template <
typename T>
428 return this->version<T>(expectedVersion);
435 VersionType version = mNode.get_attribute<
int>(
"version", 0);
436 checkVersion<void>(version, expectedVersion);
440 template <
typename T>
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 <<
").";
454 Base::atomic(member);
456 if(mAtomicFromAttribute.empty())
457 member = fromString<T>(*mNode.content_begin());
460 member = mNode.get_attribute<T>(mAtomicFromAttribute);
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.");
479 << Private::replaceSpaces(meta.
name)
483 pushUnprocessedChildren(mNode);
489 if(meta.
name!=NULL) {
490 assert(mNode!=mRoot);
492 popUnprocessedChildren();
493 markChildAsProcessed(mNode);
494 mNode = mNode.parent();
495 assert(mNode!=mRoot.end());
512 if(
fromString<bool>(mNode.get_attribute<std::string>(
"nullptr",
"false"))) {
518 std::string ref = mNode.get_attribute<std::string>(
"ref",
"");
521 pointer = resolveReference<T>(ref);
526 Base::pointer(pointer);
531 return mNode.get_attribute<std::string>(
"class",
"");
539 bool fromThisNode = mDeserializeFromThisNode;
540 bool fromAttribute =
false;
545 }
catch(XMemberNotFound& ex) {
551 std::string
id = Private::replaceSpecialChars(meta.
id);
559 if(!mNode.has_attribute(
id)) {
560 MIRA_THROW(XMemberNotFound,
"Node (or attribute) '" <<
id <<
563 mAtomicFromAttribute = id;
564 fromAttribute =
true;
571 MIRA_RETHROW(ex,
"in tag starting at: " << mNode.uri() <<
"(" << mNode.line() <<
")");
577 mDeserializeFromThisNode=
false;
580 Base::invokeMemberOverwrite(member, meta);
585 mAtomicFromAttribute.clear();
586 if(!fromThisNode && !fromAttribute) {
588 rewindFindIterator(meta.
getName());
595 mAtomicFromAttribute.clear();
596 if(!fromThisNode && !fromAttribute)
612 bool mDeserializeFromThisNode;
619 std::string mAtomicFromAttribute;
628 typedef std::map<std::string, XMLDom::const_iterator> NextFindIteratorMap;
629 std::list<NextFindIteratorMap> mNextFindIteratorStack;
633 assert(mNextFindIteratorStack.size()>=1);
634 NextFindIteratorMap& m = mNextFindIteratorStack.back();
640 NextFindIteratorMap::iterator p = m.
find(name);
647 i = find(j, mNode.
end(), name);
659 mNextFindIteratorStack.push_back(NextFindIteratorMap());
665 mNextFindIteratorStack.pop_back();
668 void rewindFindIterator(
const std::string& name)
670 assert(mNextFindIteratorStack.size()>=1);
671 NextFindIteratorMap& m = mNextFindIteratorStack.back();
673 NextFindIteratorMap::iterator p = m.find(name);
677 if (m[name] == mNode.
begin())
683 std::stack<std::vector<XMLDom::const_iterator>> mUnprocessedChildren;
687 std::vector<XMLDom::const_iterator> children;
688 for (
auto it = parent.begin(); it != parent.end(); ++it) {
689 children.push_back(it);
691 mUnprocessedChildren.push(std::move(children));
694 void popUnprocessedChildren()
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)) {
702 MIRA_LOG(
ERROR) <<
"XML tag " << *child <<
" (originating from " << child.uri() <<
":" << child.line()
703 <<
") is not used during deserialization";
705 mUnprocessedChildren.pop();
710 auto& unprocessedChildren = mUnprocessedChildren.top();
711 auto it = std::remove(unprocessedChildren.begin(), unprocessedChildren.end(), child);
712 unprocessedChildren.erase(it, unprocessedChildren.end());
718 auto& unprocessedChildren = mUnprocessedChildren.top();
719 unprocessedChildren.clear();
727 namespace serialization {
738 template<
typename Collection>
739 struct ReflectCollectionCount<XMLSerializer, Collection>
747 template<
typename Collection,
bool HasKeyType = true,
bool HasMappedType = true>
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>>
766 return boost::algorithm::starts_with(attr.first,
"key");
772 uint32 keyCount = (
uint32)std::count(node.begin(), node.end(),
"key");
776 keyCount = (
uint32)std::count_if(node.attribute_cbegin(), node.attribute_cend(),
779 if (keyCount != itemCount) {
780 MIRA_THROW(XIO,
"Node for map (or map-like collection) has " << keyCount
781 <<
" <key> tags and " << itemCount <<
" <item> tags.");
792 template<
typename Collection>
793 struct ReflectCollectionCount<XMLDeserializer, Collection>
797 return boost::algorithm::starts_with(attr.first,
"item");
806 ioCount = (
uint32)std::count(node.begin(), node.end(),
"item");
810 ioCount = (
uint32)std::count_if(node.attribute_cbegin(), node.attribute_cend(),
814 CheckKeyCount<Collection>::check(node, ioCount);
818 template<
typename Reflector,
typename Container>
struct ReflectReadMapItems;
824 template<
typename Container>
825 struct ReflectReadMapItems<XMLSerializer, Container>
827 typedef typename Container::value_type
value_type;
828 typedef typename Container::key_type key_type;
830 static void reflect(XMLSerializer& r, Container& c)
836 key_type& nonconstkey =
const_cast<key_type&
>(p.first);
849 template<
typename Reflector,
typename Container>
struct ReflectWriteMapItems;
855 template<
typename Container>
856 struct ReflectWriteMapItems<XMLDeserializer, Container>
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;
863 static void reflect(XMLDeserializer& r, Container& c,
uint32 count)
870 for(
uint32 id=0;
id<count; ++id) {
872 if(IsPointerOrSharedPointer<key_type>::value) {
880 iterator it = c.insert(hint, value_type(key, mapped_type()));
This object can use object tracking internally, but the object tracking system'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
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
#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
const_content_iterator content_begin() const
Get the const iterator to the first content.
Definition: XMLDom.h:643
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
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 'MIRA_FORCE_SERIALIZE_VERSION', 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.
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.