| /*
|
| * Copyright 2006 Sony Computer Entertainment Inc.
|
| *
|
| * Licensed under the MIT Open Source License, for details please see license.txt or the website
|
| * http://www.opensource.org/licenses/mit-license.php
|
| *
|
| */ |
| |
| #include <iomanip> |
| #include <dae/daeElement.h> |
| #include <dae/daeArray.h> |
| #include <dae/daeMetaAttribute.h> |
| #include <dae/daeMetaElementAttribute.h> |
| #include <dae/daeMetaElement.h> |
| #include <dae/daeDatabase.h> |
| #include <dae/daeErrorHandler.h> |
| #include <dae/daeURI.h> |
| #include <dae/domAny.h> |
| #include <dae/daeUtils.h> |
| |
| using namespace std; |
| |
| daeElement* daeElement::simpleAdd(daeString name, int index) { |
| if (daeElementRef elt = _meta->create(name)) |
| return add(elt, index); |
| return NULL; |
| } |
| |
| daeElement* daeElement::add(daeString names_, int index) { |
| list<string> names; |
| cdom::tokenize(names_, " ", names); |
| cdom::tokenIter iter = names.begin(); |
| daeElement* root = simpleAdd(iter->c_str(), index); |
| if (!root) |
| return NULL; |
| |
| iter++; |
| daeElement* elt = root; |
| for (; iter != names.end(); iter++) { |
| elt = elt->simpleAdd(iter->c_str()); |
| if (!elt) { |
| removeChildElement(root); |
| return NULL; |
| } |
| } |
| |
| return elt; |
| } |
| |
| daeElement* daeElement::add(daeElement* elt, int index) { |
| if (!elt) |
| return NULL; |
| if (elt == this) |
| return this; |
| bool result = (index == -1 ? _meta->place(this, elt) : _meta->placeAt(index, this, elt)); |
| return result ? elt : NULL; |
| } |
| |
| daeElement* daeElement::addBefore(daeElement* elt, daeElement* index) { |
| if (!index || !elt || index->getParent() != this) |
| return NULL; |
| return _meta->placeBefore(index, this, elt) ? elt : NULL; |
| } |
| |
| daeElement* daeElement::addAfter(daeElement* elt, daeElement* index) { |
| if (!index || !elt || index->getParent() != this) |
| return NULL; |
| return _meta->placeAfter(index, this, elt) ? elt : NULL; |
| } |
| |
| daeElementRef |
| daeElement::createElement(daeString className) |
| { |
| daeElementRef elem = _meta->create(className); |
| // Bug #225 work around |
| // if ( elem != NULL) |
| // elem->ref(); // change premature delete into memory leak. |
| return elem; |
| } |
| |
| daeElement* daeElement::createAndPlace(daeString className) { |
| return add(className); |
| } |
| |
| daeElement* daeElement::createAndPlaceAt(daeInt index, daeString className) { |
| return add(className, index); |
| } |
| |
| daeBool daeElement::placeElement(daeElement* e) { |
| return add(e) != NULL; |
| } |
| |
| daeBool daeElement::placeElementAt(daeInt index, daeElement* e) { |
| return add(e, index) != NULL; |
| } |
| |
| daeBool daeElement::placeElementBefore( daeElement *marker, daeElement *element ) { |
| return addBefore(element, marker) != NULL; |
| } |
| |
| daeBool daeElement::placeElementAfter( daeElement *marker, daeElement *element ) { |
| return addAfter(element, marker) != NULL; |
| } |
| |
| daeInt daeElement::findLastIndexOf( daeString elementName ) { |
| if ( _meta->getContents() != NULL ) { |
| daeElementRefArray* contents = |
| (daeElementRefArray*)_meta->getContents()->getWritableMemory(this); |
| for ( int i = (int)contents->getCount()-1; i >= 0; --i ) { |
| if ( strcmp( contents->get(i)->getElementName(), elementName ) == 0 ) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| daeBool |
| daeElement::removeChildElement(daeElement* element) |
| { |
| // error traps |
| if(element==NULL) |
| return false; |
| if(element->_parent != this) |
| return false; |
| |
| return _meta->remove( this, element ); |
| } |
| |
| void daeElement::setDocument( daeDocument *c, bool notifyDocument ) { |
| if( _document == c ) |
| return; |
| |
| // Notify our parent document if necessary. |
| if ( _document != NULL && notifyDocument ) |
| _document->removeElement(this); |
| _document = c; |
| if ( _document != NULL && notifyDocument ) |
| _document->insertElement(this); |
| |
| // Notify our attributes |
| daeMetaAttributeRefArray& metaAttrs = getMeta()->getMetaAttributes(); |
| for (size_t i = 0; i < metaAttrs.getCount(); i++) |
| metaAttrs[i]->setDocument(this, c); |
| |
| // Notify our char data object |
| if (getCharDataObject()) |
| getCharDataObject()->setDocument(this, c); |
| |
| // Notify our children |
| daeElementRefArray ea; |
| getChildren( ea ); |
| for ( size_t x = 0; x < ea.getCount(); x++ ) { |
| // Since inserting and removing elements works recursively in the database, |
| // we don't need to notify it about inserts/removals as we process the |
| // children of this element. |
| ea[x]->setDocument( c, false ); |
| } |
| } |
| |
| void daeElement::deleteCMDataArray(daeTArray<daeCharArray*>& cmData) { |
| for (unsigned int i = 0; i < cmData.getCount(); i++) |
| delete cmData.get(i); |
| cmData.clear(); |
| } |
| |
| size_t daeElement::getAttributeCount() { |
| return getMeta()->getMetaAttributes().getCount(); |
| } |
| |
| namespace { |
| // A helper function to get the index of an attribute given the attribute name. |
| size_t getAttributeIndex(daeElement& el, daeString name) { |
| if (el.getMeta()) { |
| daeMetaAttributeRefArray& metaAttrs = el.getMeta()->getMetaAttributes(); |
| for (size_t i = 0; i < metaAttrs.getCount(); i++) |
| if (metaAttrs[i]->getName() && strcmp(metaAttrs[i]->getName(), name) == 0) |
| return i; |
| } |
| return (size_t)-1; |
| } |
| } |
| |
| daeMetaAttribute* daeElement::getAttributeObject(size_t i) { |
| daeMetaAttributeRefArray& attrs = getMeta()->getMetaAttributes(); |
| if (i >= attrs.getCount()) |
| return NULL; |
| return attrs[i]; |
| } |
| |
| daeMetaAttribute* daeElement::getAttributeObject(daeString name) { |
| return getAttributeObject(getAttributeIndex(*this, name)); |
| } |
| |
| std::string daeElement::getAttributeName(size_t i) { |
| if (daeMetaAttribute* attr = getAttributeObject(i)) |
| return (daeString)attr->getName(); |
| return ""; |
| } |
| |
| daeBool daeElement::hasAttribute(daeString name) { |
| return getAttributeObject(name) != 0; |
| } |
| |
| daeBool daeElement::isAttributeSet(daeString name) { |
| size_t i = getAttributeIndex(*this, name); |
| if (i != (size_t)-1) |
| return _validAttributeArray[i]; |
| return false; |
| } |
| |
| std::string daeElement::getAttribute(size_t i) { |
| std::string value; |
| getAttribute(i, value); |
| return value; |
| } |
| |
| void daeElement::getAttribute(size_t i, std::string& value) { |
| value = ""; |
| if (daeMetaAttribute* attr = getAttributeObject(i)) { |
| std::ostringstream buffer; |
| attr->memoryToString(this, buffer); |
| value = buffer.str(); |
| } |
| } |
| |
| std::string daeElement::getAttribute(daeString name) { |
| std::string value; |
| getAttribute(name, value); |
| return value; |
| } |
| |
| void daeElement::getAttribute(daeString name, std::string& value) { |
| getAttribute(getAttributeIndex(*this, name), value); |
| } |
| |
| daeElement::attr::attr() { } |
| daeElement::attr::attr(const std::string& name, const std::string& value) |
| : name(name), value(value) { } |
| |
| daeTArray<daeElement::attr> daeElement::getAttributes() { |
| daeTArray<daeElement::attr> attrs; |
| getAttributes(attrs); |
| return attrs; |
| } |
| |
| void daeElement::getAttributes(daeTArray<attr>& attrs) { |
| attrs.clear(); |
| for (size_t i = 0; i < getAttributeCount(); i++) { |
| std::string value; |
| getAttribute(i, value); |
| attrs.append(attr(getAttributeName(i), value)); |
| } |
| } |
| |
| daeBool daeElement::setAttribute(size_t i, daeString value) { |
| if (daeMetaAttribute* attr = getAttributeObject(i)) { |
| if (attr->getType()) { |
| attr->stringToMemory(this, value); |
| _validAttributeArray.set(i, true); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| daeBool daeElement::setAttribute(daeString name, daeString value) { |
| return setAttribute(getAttributeIndex(*this, name), value); |
| } |
| |
| // Deprecated |
| daeMemoryRef daeElement::getAttributeValue(daeString name) { |
| if (daeMetaAttribute* attr = getAttributeObject(name)) |
| return attr->get(this); |
| return NULL; |
| } |
| |
| daeMetaAttribute* daeElement::getCharDataObject() { |
| if (_meta) |
| return _meta->getValueAttribute(); |
| return NULL; |
| } |
| |
| daeBool daeElement::hasCharData() { |
| return getCharDataObject() != NULL; |
| } |
| |
| std::string daeElement::getCharData() { |
| std::string result; |
| getCharData(result); |
| return result; |
| } |
| |
| void daeElement::getCharData(std::string& data) { |
| data = ""; |
| if (daeMetaAttribute* charDataAttr = getCharDataObject()) { |
| std::ostringstream buffer; |
| charDataAttr->memoryToString(this, buffer); |
| data = buffer.str(); |
| } |
| } |
| |
| daeBool daeElement::setCharData(const std::string& data) { |
| if (daeMetaAttribute* charDataAttr = getCharDataObject()) { |
| charDataAttr->stringToMemory(this, data.c_str()); |
| return true; |
| } |
| return false; |
| } |
| |
| daeBool daeElement::hasValue() { |
| return hasCharData(); |
| } |
| |
| daeMemoryRef daeElement::getValuePointer() { |
| if (daeMetaAttribute* charDataAttr = getCharDataObject()) |
| return charDataAttr->get(this); |
| return NULL; |
| } |
| |
| void |
| daeElement::setup(daeMetaElement* meta) |
| { |
| if (_meta) |
| return; |
| _meta = meta; |
| daeMetaAttributeRefArray& attrs = meta->getMetaAttributes(); |
| int macnt = (int)attrs.getCount(); |
| |
| _validAttributeArray.setCount(macnt, false); |
| |
| for (int i = 0; i < macnt; i++) { |
| if (attrs[i]->getDefaultValue() != NULL) |
| attrs[i]->copyDefault(this); |
| } |
| |
| //set up the _CMData array if there is one |
| if ( _meta->getMetaCMData() != NULL ) |
| { |
| daeTArray< daeCharArray *> *CMData = (daeTArray< daeCharArray *>*)_meta->getMetaCMData()->getWritableMemory(this); |
| CMData->setCount( _meta->getNumChoices() ); |
| for ( unsigned int i = 0; i < _meta->getNumChoices(); i++ ) |
| { |
| CMData->set( i, new daeCharArray() ); |
| } |
| } |
| } |
| |
| void daeElement::init() { |
| _parent = NULL; |
| _document = NULL; |
| _meta = NULL; |
| _elementName = NULL; |
| _userData = NULL; |
| } |
| |
| daeElement::daeElement() { |
| init(); |
| } |
| |
| daeElement::daeElement(DAE& dae) { |
| init(); |
| } |
| |
| daeElement::~daeElement() |
| { |
| if (_elementName) { |
| delete[] _elementName; |
| _elementName = NULL; |
| } |
| } |
| |
| //function used until we clarify what's a type and what's a name for an element |
| daeString daeElement::getTypeName() const |
| { |
| return _meta->getName(); |
| } |
| daeString daeElement::getElementName() const |
| { |
| return _elementName ? _elementName : (daeString)_meta->getName(); |
| } |
| void daeElement::setElementName( daeString nm ) { |
| if ( nm == NULL ) { |
| if ( _elementName ) delete[] _elementName; |
| _elementName = NULL; |
| return; |
| } |
| if ( !_elementName ) _elementName = new daeChar[128]; |
| strcpy( (char*)_elementName, nm ); |
| } |
| |
| daeString daeElement::getID() const { |
| daeElement* this_ = const_cast<daeElement*>(this); |
| if (_meta) |
| if (daeMetaAttribute* idAttr = this_->getAttributeObject("id")) |
| return *(daeStringRef*)idAttr->get(this_); |
| return NULL; |
| } |
| |
| daeElementRefArray daeElement::getChildren() { |
| daeElementRefArray array; |
| getChildren(array); |
| return array; |
| } |
| |
| void daeElement::getChildren( daeElementRefArray &array ) { |
| _meta->getChildren( this, array ); |
| } |
| |
| daeSmartRef<daeElement> daeElement::clone(daeString idSuffix, daeString nameSuffix) { |
| // Use the meta object system to create a new instance of this element. We need to |
| // create a new meta if we're cloning a domAny object because domAnys never share meta objects. |
| // Ideally we'd be able to clone the _meta for domAny objects. Then we wouldn't need |
| // any additional special case code for cloning domAny. Unfortunately, we don't have a |
| // daeMetaElement::clone method. |
| bool any = typeID() == domAny::ID(); |
| daeElementRef ret = any ? domAny::registerElement(*getDAE())->create() : _meta->create(); |
| ret->setElementName( _elementName ); |
| |
| // Copy the attributes and character data. Requires special care for domAny. |
| if (any) { |
| domAny* thisAny = (domAny*)this; |
| domAny* retAny = (domAny*)ret.cast(); |
| for (daeUInt i = 0; i < (daeUInt)thisAny->getAttributeCount(); i++) |
| retAny->setAttribute(thisAny->getAttributeName(i), thisAny->getAttributeValue(i)); |
| retAny->setValue(thisAny->getValue()); |
| } else { |
| // Use the meta system to copy attributes |
| daeMetaAttributeRefArray &attrs = _meta->getMetaAttributes(); |
| for (unsigned int i = 0; i < attrs.getCount(); i++) { |
| attrs[i]->copy( ret, this ); |
| ret->_validAttributeArray[i] = _validAttributeArray[i]; |
| } |
| if (daeMetaAttribute* valueAttr = getCharDataObject()) |
| valueAttr->copy( ret, this ); |
| } |
| |
| daeElementRefArray children; |
| _meta->getChildren( this, children ); |
| for ( size_t x = 0; x < children.getCount(); x++ ) { |
| ret->placeElement( children.get(x)->clone( idSuffix, nameSuffix ) ); |
| } |
| |
| // Mangle the id |
| if (idSuffix) { |
| std::string id = ret->getAttribute("id"); |
| if (!id.empty()) |
| ret->setAttribute("id", (id + idSuffix).c_str()); |
| } |
| // Mangle the name |
| if (nameSuffix) { |
| std::string name = ret->getAttribute("name"); |
| if (!name.empty()) |
| ret->setAttribute("name", (name + nameSuffix).c_str()); |
| } |
| return ret; |
| } |
| |
| |
| // Element comparison |
| |
| namespace { // Utility functions |
| int getNecessaryColumnWidth(const vector<string>& tokens) { |
| int result = 0; |
| for (size_t i = 0; i < tokens.size(); i++) { |
| int tokenLength = int(tokens[i].length() > 0 ? tokens[i].length()+2 : 0); |
| result = max(tokenLength, result); |
| } |
| return result; |
| } |
| |
| string formatToken(const string& token) { |
| if (token.length() <= 50) |
| return token; |
| return token.substr(0, 47) + "..."; |
| } |
| } // namespace { |
| |
| daeElement::compareResult::compareResult() |
| : compareValue(0), |
| elt1(NULL), |
| elt2(NULL), |
| nameMismatch(false), |
| attrMismatch(""), |
| charDataMismatch(false), |
| childCountMismatch(false) { |
| } |
| |
| string daeElement::compareResult::format() { |
| if (!elt1 || !elt2) |
| return ""; |
| |
| // Gather the data we'll be printing |
| string name1 = formatToken(elt1->getElementName()), |
| name2 = formatToken(elt2->getElementName()), |
| type1 = formatToken(elt1->getTypeName()), |
| type2 = formatToken(elt2->getTypeName()), |
| id1 = formatToken(elt1->getAttribute("id")), |
| id2 = formatToken(elt2->getAttribute("id")), |
| attrName1 = formatToken(attrMismatch), |
| attrName2 = formatToken(attrMismatch), |
| attrValue1 = formatToken(elt1->getAttribute(attrMismatch.c_str())), |
| attrValue2 = formatToken(elt2->getAttribute(attrMismatch.c_str())), |
| charData1 = formatToken(elt1->getCharData()), |
| charData2 = formatToken(elt2->getCharData()), |
| childCount1 = formatToken(cdom::toString(elt1->getChildren().getCount())), |
| childCount2 = formatToken(cdom::toString(elt2->getChildren().getCount())); |
| |
| // Compute formatting information |
| vector<string> col1Tokens = cdom::makeStringArray("Name", "Type", "ID", |
| "Attr name", "Attr value", "Char data", "Child count", 0); |
| vector<string> col2Tokens = cdom::makeStringArray("Element 1", name1.c_str(), |
| type1.c_str(), id1.c_str(), attrName1.c_str(), attrValue1.c_str(), |
| charData1.c_str(), childCount1.c_str(), 0); |
| |
| int c1w = getNecessaryColumnWidth(col1Tokens), |
| c2w = getNecessaryColumnWidth(col2Tokens); |
| ostringstream msg; |
| msg << setw(c1w) << left << "" << setw(c2w) << left << "Element 1" << "Element 2\n" |
| << setw(c1w) << left << "" << setw(c2w) << left << "---------" << "---------\n" |
| << setw(c1w) << left << "Name" << setw(c2w) << left << name1 << name2 << endl |
| << setw(c1w) << left << "Type" << setw(c2w) << left << type1 << type2 << endl |
| << setw(c1w) << left << "ID" << setw(c2w) << left << id1 << id2 << endl |
| << setw(c1w) << left << "Attr name" << setw(c2w) << left << attrName1 << attrName2 << endl |
| << setw(c1w) << left << "Attr value" << setw(c2w) << left << attrValue1 << attrValue2 << endl |
| << setw(c1w) << left << "Char data" << setw(c2w) << left << charData1 << charData2 << endl |
| << setw(c1w) << left << "Child count" << setw(c2w) << left << childCount1 << childCount2; |
| |
| return msg.str(); |
| } |
| |
| namespace { |
| daeElement::compareResult compareMatch() { |
| daeElement::compareResult result; |
| result.compareValue = 0; |
| return result; |
| } |
| |
| daeElement::compareResult nameMismatch(daeElement& elt1, daeElement& elt2) { |
| daeElement::compareResult result; |
| result.elt1 = &elt1; |
| result.elt2 = &elt2; |
| result.compareValue = strcmp(elt1.getElementName(), elt2.getElementName()); |
| result.nameMismatch = true; |
| return result; |
| } |
| |
| daeElement::compareResult attrMismatch(daeElement& elt1, daeElement& elt2, const string& attr) { |
| daeElement::compareResult result; |
| result.elt1 = &elt1; |
| result.elt2 = &elt2; |
| result.compareValue = strcmp(elt1.getAttribute(attr.c_str()).c_str(), |
| elt2.getAttribute(attr.c_str()).c_str()); |
| result.attrMismatch = attr; |
| return result; |
| } |
| |
| daeElement::compareResult charDataMismatch(daeElement& elt1, daeElement& elt2) { |
| daeElement::compareResult result; |
| result.elt1 = &elt1; |
| result.elt2 = &elt2; |
| result.compareValue = strcmp(elt1.getCharData().c_str(), |
| elt2.getCharData().c_str()); |
| result.charDataMismatch = true; |
| return result; |
| } |
| |
| daeElement::compareResult childCountMismatch(daeElement& elt1, daeElement& elt2) { |
| daeElement::compareResult result; |
| result.elt1 = &elt1; |
| result.elt2 = &elt2; |
| daeElementRefArray children1 = elt1.getChildren(), |
| children2 = elt2.getChildren(); |
| result.compareValue = int(children1.getCount()) - int(children2.getCount()); |
| result.childCountMismatch = true; |
| return result; |
| } |
| |
| daeElement::compareResult compareElementsSameType(daeElement& elt1, daeElement& elt2) { |
| // Compare attributes |
| for (size_t i = 0; i < elt1.getAttributeCount(); i++) |
| if (elt1.getAttributeObject(i)->compare(&elt1, &elt2) != 0) |
| return attrMismatch(elt1, elt2, elt1.getAttributeName(i)); |
| |
| // Compare character data |
| if (elt1.getCharDataObject()) |
| if (elt1.getCharDataObject()->compare(&elt1, &elt2) != 0) |
| return charDataMismatch(elt1, elt2); |
| |
| // Compare children |
| daeElementRefArray children1 = elt1.getChildren(), |
| children2 = elt2.getChildren(); |
| if (children1.getCount() != children2.getCount()) |
| return childCountMismatch(elt1, elt2); |
| for (size_t i = 0; i < children1.getCount(); i++) { |
| daeElement::compareResult result = daeElement::compareWithFullResult(*children1[i], *children2[i]); |
| if (result.compareValue != 0) |
| return result; |
| } |
| |
| return compareMatch(); |
| } |
| |
| daeElement::compareResult compareElementsDifferentTypes(daeElement& elt1, daeElement& elt2) { |
| string value1, value2; |
| |
| // Compare attributes. Be careful because each element could have a |
| // different number of attributes. |
| if (elt1.getAttributeCount() > elt2.getAttributeCount()) |
| return attrMismatch(elt1, elt2, elt1.getAttributeName(elt2.getAttributeCount())); |
| if (elt2.getAttributeCount() > elt1.getAttributeCount()) |
| return attrMismatch(elt1, elt2, elt2.getAttributeName(elt1.getAttributeCount())); |
| for (size_t i = 0; i < elt1.getAttributeCount(); i++) { |
| elt1.getAttribute(i, value1); |
| elt2.getAttribute(elt1.getAttributeName(i).c_str(), value2); |
| if (value1 != value2) |
| return attrMismatch(elt1, elt2, elt1.getAttributeName(i)); |
| } |
| |
| // Compare character data |
| elt1.getCharData(value1); |
| elt2.getCharData(value2); |
| if (value1 != value2) |
| return charDataMismatch(elt1, elt2); |
| |
| // Compare children |
| daeElementRefArray children1 = elt1.getChildren(), |
| children2 = elt2.getChildren(); |
| if (children1.getCount() != children2.getCount()) |
| return childCountMismatch(elt1, elt2); |
| for (size_t i = 0; i < children1.getCount(); i++) { |
| daeElement::compareResult result = daeElement::compareWithFullResult(*children1[i], *children2[i]); |
| if (result.compareValue != 0) |
| return result; |
| } |
| |
| return compareMatch(); |
| } |
| } // namespace { |
| |
| int daeElement::compare(daeElement& elt1, daeElement& elt2) { |
| return compareWithFullResult(elt1, elt2).compareValue; |
| } |
| |
| daeElement::compareResult daeElement::compareWithFullResult(daeElement& elt1, daeElement& elt2) { |
| // Check the element name |
| if (strcmp(elt1.getElementName(), elt2.getElementName()) != 0) |
| return nameMismatch(elt1, elt2); |
| |
| // Dispatch to a specific function based on whether or not the types are the same |
| if ((elt1.typeID() != elt2.typeID()) || elt1.typeID() == domAny::ID()) |
| return compareElementsDifferentTypes(elt1, elt2); |
| else |
| return compareElementsSameType(elt1, elt2); |
| } |
| |
| |
| daeURI *daeElement::getDocumentURI() const { |
| if ( _document == NULL ) { |
| return NULL; |
| } |
| return _document->getDocumentURI(); |
| } |
| |
| |
| daeElement::matchName::matchName(daeString name) : name(name) { } |
| |
| bool daeElement::matchName::operator()(daeElement* elt) const { |
| return strcmp(elt->getElementName(), name.c_str()) == 0; |
| } |
| |
| daeElement::matchType::matchType(daeInt typeID) : typeID(typeID) { } |
| |
| bool daeElement::matchType::operator()(daeElement* elt) const { |
| return elt->typeID() == typeID; |
| } |
| |
| daeElement* daeElement::getChild(const matchElement& matcher) { |
| daeElementRefArray children; |
| getChildren(children); |
| for (size_t i = 0; i < children.getCount(); i++) |
| if (matcher(children[i])) |
| return children[i]; |
| |
| return NULL; |
| } |
| |
| daeElement* daeElement::getDescendant(const matchElement& matcher) { |
| daeElementRefArray elts; |
| getChildren(elts); |
| |
| for (size_t i = 0; i < elts.getCount(); i++) { |
| // Check the current element for a match |
| if (matcher(elts[i])) |
| return elts[i]; |
| |
| // Append the element's children to the queue |
| daeElementRefArray children; |
| elts[i]->getChildren(children); |
| size_t oldCount = elts.getCount(); |
| elts.setCount(elts.getCount() + children.getCount()); |
| for (size_t j = 0; j < children.getCount(); j++) |
| elts[oldCount + j] = children[j]; |
| } |
| |
| return NULL; |
| } |
| |
| daeElement* daeElement::getAncestor(const matchElement& matcher) { |
| daeElement* elt = getParent(); |
| while (elt) { |
| if (matcher(elt)) |
| return elt; |
| elt = elt->getParent(); |
| } |
| |
| return NULL; |
| } |
| |
| daeElement* daeElement::getParent() { |
| return _parent; |
| } |
| |
| daeElement* daeElement::getChild(daeString eltName) { |
| if (!eltName) |
| return NULL; |
| matchName test(eltName); |
| return getChild(matchName(eltName)); |
| } |
| |
| daeElement* daeElement::getDescendant(daeString eltName) { |
| if (!eltName) |
| return NULL; |
| return getDescendant(matchName(eltName)); |
| } |
| |
| daeElement* daeElement::getAncestor(daeString eltName) { |
| if (!eltName) |
| return NULL; |
| return getAncestor(matchName(eltName)); |
| } |
| |
| DAE* daeElement::getDAE() { |
| return _meta->getDAE(); |
| } |
| |
| void daeElement::setUserData(void* data) { |
| _userData = data; |
| } |
| |
| void* daeElement::getUserData() { |
| return _userData; |
| } |