Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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;
}