bool Importer::traverse(NodeHandler *handler, void *n, void *c, Core::BaseObject *target) { xmlNodePtr node = reinterpret_cast<xmlNodePtr>(n); xmlNodePtr childs = reinterpret_cast<xmlNodePtr>(c); ChildList remaining; TagSet mandatory; handler->init(target, n, mandatory); bool result = true; for ( xmlNodePtr child = childs; child != NULL; child = child->next ) { if ( child->type != XML_ELEMENT_NODE ) continue; handler->propagate(NULL, false, true); try { handler->get(target, child); } catch ( std::exception &e ) { if ( handler->isOptional ) SEISCOMP_WARNING("(optional) %s.%s: %s", node->name, child->name, e.what()); else throw e; } if ( !handler->isOptional ) mandatory.erase((const char*)child->name); if ( handler->object == NULL && handler->isAnyType ) { if ( _any.get(target, child) ) { handler->object = _any.object; handler->childHandler = _any.childHandler; handler->newInstance = _any.newInstance; } } Core::BaseObject *newTarget = handler->object; MemberNodeHandler *memberHandler = handler->memberHandler; NodeHandler *childHandler = handler->childHandler; bool newInstance = handler->newInstance; bool optional = handler->isOptional; if ( newTarget ) { if ( childHandler == NULL ) { childHandler = _typemap->getHandler(newTarget->className()); if ( childHandler == NULL ) { SEISCOMP_WARNING("No class handler for %s", newTarget->className()); if ( newInstance ) delete newTarget; handler->object = NULL; newTarget = NULL; childHandler = &_none; } } } else childHandler = &_none; try { if ( traverse(childHandler, child, child->children, handler->object) ) { if ( newTarget && newInstance && !memberHandler ) remaining.push_back(newTarget); } else { if ( newTarget && newInstance ) delete newTarget; newTarget = NULL; if ( optional ) SEISCOMP_INFO("Invalid %s element: ignoring", child->name); else { SEISCOMP_WARNING("%s is not optional within %s", child->name, node->name); result = false; } } } catch ( std::exception &e ) { SEISCOMP_WARNING("%s: %s", child->name, e.what()); if ( newTarget ) { if ( newInstance ) delete newTarget; if ( !optional ) { SEISCOMP_WARNING("%s is not optional within %s", child->name, node->name); result = false; } else SEISCOMP_WARNING("%s: ignoring optional member %s: invalid", node->name, child->name); newTarget = NULL; } } if ( memberHandler ) { if ( !memberHandler->finalize(target, newTarget) ) { if ( newTarget && newInstance ) remaining.push_back(newTarget); } } } handler->finalize(target, &remaining); if ( target != NULL ) { for ( ChildList::iterator it = remaining.begin(); it != remaining.end(); ++it ) if ( *it != NULL ) delete *it; } else { for ( ChildList::iterator it = remaining.begin(); it != remaining.end(); ++it ) { if ( *it != NULL ) { if ( _result == NULL ) _result = *it; else delete *it; } } } if ( !mandatory.empty() ) { std::string attribs; for ( TagSet::iterator it = mandatory.begin(); it != mandatory.end(); ++it ) { if ( it != mandatory.begin() ) attribs += ", "; attribs += *it; } SEISCOMP_WARNING("%s: missing mandatory attribute%s: %s", node->name, mandatory.size() == 1?"":"s", attribs.c_str()); return false; } return result; }
bool TagSet::includes(const TagSet& t) const { //return !empty() && std::includes( this->begin(), this->end(), t.begin(), t.end()); if (t.empty()) return true; if (empty()) { // An empty TagSet satisfies the conditions only if either : // t is also empty (already handled) // t only includes negative tags if (*t.rbegin() <= Tag(0)) return true; // t includes the "0" tag if (t.count(Tag(0)) > 0) return true; // otherwise the TagSet t does not "include" empty sets return false; } #if 1 // Simple but not optimal version for (sofa::helper::set<Tag>::const_iterator first2 = t.begin(), last2 = t.end(); first2 != last2; ++first2) { Tag t2 = *first2; if (t2 == Tag(0)) continue; // tag "0" is used to indicate that we should include objects without any tag if (!t2.negative()) { if (this->count(t2) == 0) return false; // tag not found in this } else { if (this->count(-t2) > 0) return false; // tag found in this } } return true; #else // First test : no negative tag from t should appear as positive in this if (t.begin()->negative()) { sofa::helper::set<Tag>::const_reverse_iterator first1, last1; sofa::helper::set<Tag>::const_iterator first2, last2; first1 = this->rbegin(); last1 = this->rend(); first2 = t.begin(); last2 = t.end(); for (; first2 != last2; ++first1) { if (first1 == last1) break; // no more tags in this Tag t1 = *first1; if (t1.negative()) break; // no more positive tags in this Tag t2 = *first2; if (!t2.negative()) break; // no more negative tags in t if (-t1 == t2) return false; // found an excluded tag if (!(-t1 < t2)) ++first2; } } // Second test : all positive tags from t should appear as positive in this if (!t.rbegin()->negative()) { sofa::helper::set<Tag>::const_iterator first1, last1; sofa::helper::set<Tag>::const_iterator first2, last2; first1 = this->lower_bound(Tag(0)); last1 = this->end(); first2 = t.lower_bound(Tag(0)); last2 = t.end(); //for(; first1 != last1 && first1->negative(); ++first1); // skip negative tags in this //for(; first2 != last2 && first2->negative(); ++first2); // skip negative tags in t for (; first2 != last2; ++first1) { if (first1 == last1) return false; // no more positive tags in this Tag t1 = *first1; Tag t2 = *first2; if (t2 < t1) return false; // tag not found if (!(t1 < t2)) ++first2; } } return true; // all tests passed #endif }
bool TagSet::includes(const TagSet& t) const { return !empty() && std::includes( this->begin(), this->end(), t.begin(), t.end()); }