diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-05-15 09:07:21 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-05-15 09:07:21 -0400 |
commit | 5d43bc166d011e911e0492579b2f4f8bf015b48f (patch) | |
tree | ccc4cda5c2c2c3a5689f4a33dcfda2a896f21b8c /indra/llxml | |
parent | a3f2cacf542e1d770698ef6c7e6ea1c0a5cd3368 (diff) | |
parent | e7eced3c87310b15ac20cc3cd470d67686104a14 (diff) |
Merge commit 'e7eced3' into release/luau-scripting: whitespace fix.
Diffstat (limited to 'indra/llxml')
-rw-r--r-- | indra/llxml/llxmlnode.cpp | 5442 | ||||
-rw-r--r-- | indra/llxml/llxmlnode.h | 382 | ||||
-rw-r--r-- | indra/llxml/llxmlparser.cpp | 536 | ||||
-rw-r--r-- | indra/llxml/llxmlparser.h | 164 | ||||
-rw-r--r-- | indra/llxml/llxmltree.cpp | 718 | ||||
-rw-r--r-- | indra/llxml/llxmltree.h | 292 | ||||
-rw-r--r-- | indra/llxml/tests/llcontrol_test.cpp | 224 |
7 files changed, 3879 insertions, 3879 deletions
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 455df13e48..cf2bc4476e 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llxmlnode.cpp * @author Tom Yedwab * @brief LLXMLNode implementation @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,1110 +47,1110 @@ BOOL LLXMLNode::sStripEscapedStrings = TRUE; BOOL LLXMLNode::sStripWhitespaceValues = FALSE; -LLXMLNode::LLXMLNode() : - mID(""), - mParser(NULL), - mIsAttribute(FALSE), - mVersionMajor(0), - mVersionMinor(0), - mLength(0), - mPrecision(64), - mType(TYPE_CONTAINER), - mEncoding(ENCODING_DEFAULT), - mLineNumber(-1), - mParent(NULL), - mChildren(NULL), - mAttributes(), - mPrev(NULL), - mNext(NULL), - mName(NULL), - mValue(""), - mDefault(NULL) -{ -} - -LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) : - mID(""), - mParser(NULL), - mIsAttribute(is_attribute), - mVersionMajor(0), - mVersionMinor(0), - mLength(0), - mPrecision(64), - mType(TYPE_CONTAINER), - mEncoding(ENCODING_DEFAULT), - mLineNumber(-1), - mParent(NULL), - mChildren(NULL), - mAttributes(), - mPrev(NULL), - mNext(NULL), - mValue(""), - mDefault(NULL) +LLXMLNode::LLXMLNode() : + mID(""), + mParser(NULL), + mIsAttribute(FALSE), + mVersionMajor(0), + mVersionMinor(0), + mLength(0), + mPrecision(64), + mType(TYPE_CONTAINER), + mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), + mParent(NULL), + mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), + mName(NULL), + mValue(""), + mDefault(NULL) +{ +} + +LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) : + mID(""), + mParser(NULL), + mIsAttribute(is_attribute), + mVersionMajor(0), + mVersionMinor(0), + mLength(0), + mPrecision(64), + mType(TYPE_CONTAINER), + mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), + mParent(NULL), + mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), + mValue(""), + mDefault(NULL) { mName = gStringTable.addStringEntry(name); } -LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) : - mID(""), - mParser(NULL), - mIsAttribute(is_attribute), - mVersionMajor(0), - mVersionMinor(0), - mLength(0), - mPrecision(64), - mType(TYPE_CONTAINER), - mEncoding(ENCODING_DEFAULT), - mLineNumber(-1), - mParent(NULL), - mChildren(NULL), - mAttributes(), - mPrev(NULL), - mNext(NULL), - mName(name), - mValue(""), - mDefault(NULL) +LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) : + mID(""), + mParser(NULL), + mIsAttribute(is_attribute), + mVersionMajor(0), + mVersionMinor(0), + mLength(0), + mPrecision(64), + mType(TYPE_CONTAINER), + mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), + mParent(NULL), + mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), + mName(name), + mValue(""), + mDefault(NULL) { } // copy constructor (except for the children) -LLXMLNode::LLXMLNode(const LLXMLNode& rhs) : - mID(rhs.mID), - mIsAttribute(rhs.mIsAttribute), - mVersionMajor(rhs.mVersionMajor), - mVersionMinor(rhs.mVersionMinor), - mLength(rhs.mLength), - mPrecision(rhs.mPrecision), - mType(rhs.mType), - mEncoding(rhs.mEncoding), - mLineNumber(0), - mParser(NULL), - mParent(NULL), - mChildren(NULL), - mAttributes(), - mPrev(NULL), - mNext(NULL), - mName(rhs.mName), - mValue(rhs.mValue), - mDefault(rhs.mDefault) +LLXMLNode::LLXMLNode(const LLXMLNode& rhs) : + mID(rhs.mID), + mIsAttribute(rhs.mIsAttribute), + mVersionMajor(rhs.mVersionMajor), + mVersionMinor(rhs.mVersionMinor), + mLength(rhs.mLength), + mPrecision(rhs.mPrecision), + mType(rhs.mType), + mEncoding(rhs.mEncoding), + mLineNumber(0), + mParser(NULL), + mParent(NULL), + mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), + mName(rhs.mName), + mValue(rhs.mValue), + mDefault(rhs.mDefault) { } // returns a new copy of this node and all its children LLXMLNodePtr LLXMLNode::deepCopy() { - LLXMLNodePtr newnode = LLXMLNodePtr(new LLXMLNode(*this)); - if (mChildren.notNull()) - { - for (LLXMLChildList::iterator iter = mChildren->map.begin(); - iter != mChildren->map.end(); ++iter) - { - LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); - newnode->addChild(temp_ptr_for_gcc); - } - } - for (LLXMLAttribList::iterator iter = mAttributes.begin(); - iter != mAttributes.end(); ++iter) - { - LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); - newnode->addChild(temp_ptr_for_gcc); - } - - return newnode; + LLXMLNodePtr newnode = LLXMLNodePtr(new LLXMLNode(*this)); + if (mChildren.notNull()) + { + for (LLXMLChildList::iterator iter = mChildren->map.begin(); + iter != mChildren->map.end(); ++iter) + { + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); + } + } + for (LLXMLAttribList::iterator iter = mAttributes.begin(); + iter != mAttributes.end(); ++iter) + { + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); + } + + return newnode; } // virtual LLXMLNode::~LLXMLNode() { - // Strictly speaking none of this should be required execept 'delete mChildren'... - // Sadly, that's only true if we hadn't had reference-counted smart pointers linked - // in three different directions. This entire class is a frightening, hard-to-maintain - // mess. - if (mChildren.notNull()) - { - for (LLXMLChildList::iterator iter = mChildren->map.begin(); - iter != mChildren->map.end(); ++iter) - { - LLXMLNodePtr child = iter->second; - child->mParent = NULL; - child->mNext = NULL; - child->mPrev = NULL; - } - mChildren->map.clear(); - mChildren->head = NULL; - mChildren->tail = NULL; - mChildren = NULL; - } - for (LLXMLAttribList::iterator iter = mAttributes.begin(); - iter != mAttributes.end(); ++iter) - { - LLXMLNodePtr attr = iter->second; - attr->mParent = NULL; - attr->mNext = NULL; - attr->mPrev = NULL; - } - llassert(mParent == NULL); - mDefault = NULL; + // Strictly speaking none of this should be required execept 'delete mChildren'... + // Sadly, that's only true if we hadn't had reference-counted smart pointers linked + // in three different directions. This entire class is a frightening, hard-to-maintain + // mess. + if (mChildren.notNull()) + { + for (LLXMLChildList::iterator iter = mChildren->map.begin(); + iter != mChildren->map.end(); ++iter) + { + LLXMLNodePtr child = iter->second; + child->mParent = NULL; + child->mNext = NULL; + child->mPrev = NULL; + } + mChildren->map.clear(); + mChildren->head = NULL; + mChildren->tail = NULL; + mChildren = NULL; + } + for (LLXMLAttribList::iterator iter = mAttributes.begin(); + iter != mAttributes.end(); ++iter) + { + LLXMLNodePtr attr = iter->second; + attr->mParent = NULL; + attr->mNext = NULL; + attr->mPrev = NULL; + } + llassert(mParent == NULL); + mDefault = NULL; } BOOL LLXMLNode::isNull() -{ - return (mName == NULL); +{ + return (mName == NULL); } // protected -BOOL LLXMLNode::removeChild(LLXMLNode *target_child) -{ - if (!target_child) - { - return FALSE; - } - if (target_child->mIsAttribute) - { - LLXMLAttribList::iterator children_itr = mAttributes.find(target_child->mName); - if (children_itr != mAttributes.end()) - { - target_child->mParent = NULL; - mAttributes.erase(children_itr); - return TRUE; - } - } - else if (mChildren.notNull()) - { - LLXMLChildList::iterator children_itr = mChildren->map.find(target_child->mName); - while (children_itr != mChildren->map.end()) - { - if (target_child == children_itr->second) - { - if (target_child == mChildren->head) - { - mChildren->head = target_child->mNext; - } - if (target_child == mChildren->tail) - { - mChildren->tail = target_child->mPrev; - } - - LLXMLNodePtr prev = target_child->mPrev; - LLXMLNodePtr next = target_child->mNext; - if (prev.notNull()) prev->mNext = next; - if (next.notNull()) next->mPrev = prev; - - target_child->mPrev = NULL; - target_child->mNext = NULL; - target_child->mParent = NULL; - mChildren->map.erase(children_itr); - if (mChildren->map.empty()) - { - mChildren = NULL; - } - return TRUE; - } - else if (children_itr->first != target_child->mName) - { - break; - } - else - { - ++children_itr; - } - } - } - return FALSE; +BOOL LLXMLNode::removeChild(LLXMLNode *target_child) +{ + if (!target_child) + { + return FALSE; + } + if (target_child->mIsAttribute) + { + LLXMLAttribList::iterator children_itr = mAttributes.find(target_child->mName); + if (children_itr != mAttributes.end()) + { + target_child->mParent = NULL; + mAttributes.erase(children_itr); + return TRUE; + } + } + else if (mChildren.notNull()) + { + LLXMLChildList::iterator children_itr = mChildren->map.find(target_child->mName); + while (children_itr != mChildren->map.end()) + { + if (target_child == children_itr->second) + { + if (target_child == mChildren->head) + { + mChildren->head = target_child->mNext; + } + if (target_child == mChildren->tail) + { + mChildren->tail = target_child->mPrev; + } + + LLXMLNodePtr prev = target_child->mPrev; + LLXMLNodePtr next = target_child->mNext; + if (prev.notNull()) prev->mNext = next; + if (next.notNull()) next->mPrev = prev; + + target_child->mPrev = NULL; + target_child->mNext = NULL; + target_child->mParent = NULL; + mChildren->map.erase(children_itr); + if (mChildren->map.empty()) + { + mChildren = NULL; + } + return TRUE; + } + else if (children_itr->first != target_child->mName) + { + break; + } + else + { + ++children_itr; + } + } + } + return FALSE; } void LLXMLNode::addChild(LLXMLNodePtr& new_child) { - if (new_child->mParent != NULL) - { - if (new_child->mParent == this) - { - return; - } - new_child->mParent->removeChild(new_child); - } - - new_child->mParent = this; - if (new_child->mIsAttribute) - { - LLXMLAttribList::iterator found_it = mAttributes.find(new_child->mName); - if (found_it != mAttributes.end()) - { - removeChild(found_it->second); - } - mAttributes.insert(std::make_pair(new_child->mName, new_child)); - } - else - { - if (mChildren.isNull()) - { - mChildren = new LLXMLChildren(); - mChildren->head = new_child; - mChildren->tail = new_child; - } - mChildren->map.insert(std::make_pair(new_child->mName, new_child)); - - if (mChildren->tail != new_child) - { - mChildren->tail->mNext = new_child; - new_child->mPrev = mChildren->tail; - mChildren->tail = new_child; - } - } - - new_child->updateDefault(); -} - -// virtual + if (new_child->mParent != NULL) + { + if (new_child->mParent == this) + { + return; + } + new_child->mParent->removeChild(new_child); + } + + new_child->mParent = this; + if (new_child->mIsAttribute) + { + LLXMLAttribList::iterator found_it = mAttributes.find(new_child->mName); + if (found_it != mAttributes.end()) + { + removeChild(found_it->second); + } + mAttributes.insert(std::make_pair(new_child->mName, new_child)); + } + else + { + if (mChildren.isNull()) + { + mChildren = new LLXMLChildren(); + mChildren->head = new_child; + mChildren->tail = new_child; + } + mChildren->map.insert(std::make_pair(new_child->mName, new_child)); + + if (mChildren->tail != new_child) + { + mChildren->tail->mNext = new_child; + new_child->mPrev = mChildren->tail; + mChildren->tail = new_child; + } + } + + new_child->updateDefault(); +} + +// virtual LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute) { - return createChild(gStringTable.addStringEntry(name), is_attribute); + return createChild(gStringTable.addStringEntry(name), is_attribute); } -// virtual +// virtual LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute) { - LLXMLNodePtr ret(new LLXMLNode(name, is_attribute)); - ret->mID.clear(); - - addChild(ret); - return ret; + LLXMLNodePtr ret(new LLXMLNode(name, is_attribute)); + ret->mID.clear(); + + addChild(ret); + return ret; } BOOL LLXMLNode::deleteChild(LLXMLNode *child) { - if (removeChild(child)) - { - return TRUE; - } - return FALSE; + if (removeChild(child)) + { + return TRUE; + } + return FALSE; } void LLXMLNode::setParent(LLXMLNodePtr& new_parent) { - if (new_parent.notNull()) - { - LLXMLNodePtr this_ptr(this); - new_parent->addChild(this_ptr); - } - else - { - if (mParent != NULL) - { - LLXMLNodePtr old_parent = mParent; - mParent = NULL; - old_parent->removeChild(this); - } - } + if (new_parent.notNull()) + { + LLXMLNodePtr this_ptr(this); + new_parent->addChild(this_ptr); + } + else + { + if (mParent != NULL) + { + LLXMLNodePtr old_parent = mParent; + mParent = NULL; + old_parent->removeChild(this); + } + } } void LLXMLNode::updateDefault() { - if (mParent != NULL && !mParent->mDefault.isNull()) - { - mDefault = NULL; - - // Find default value in parent's default tree - if (!mParent->mDefault.isNull()) - { - findDefault(mParent->mDefault); - } - } - - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator children_itr; - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNodePtr child = (*children_itr).second; - child->updateDefault(); - } - } + if (mParent != NULL && !mParent->mDefault.isNull()) + { + mDefault = NULL; + + // Find default value in parent's default tree + if (!mParent->mDefault.isNull()) + { + findDefault(mParent->mDefault); + } + } + + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator children_itr; + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNodePtr child = (*children_itr).second; + child->updateDefault(); + } + } } void XMLCALL StartXMLNode(void *userData, const XML_Char *name, const XML_Char **atts) { - // Create a new node - LLXMLNode *new_node_ptr = new LLXMLNode(name, FALSE); - - LLXMLNodePtr new_node = new_node_ptr; - new_node->mID.clear(); - LLXMLNodePtr ptr_new_node = new_node; - - // Set the parent-child relationship with the current active node - LLXMLNode* parent = (LLXMLNode *)userData; - - if (NULL == parent) - { - LL_WARNS() << "parent (userData) is NULL; aborting function" << LL_ENDL; - return; - } - - new_node_ptr->mParser = parent->mParser; - new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); - - // Set the current active node to the new node - XML_Parser *parser = parent->mParser; - XML_SetUserData(*parser, (void *)new_node_ptr); - - // Parse attributes - U32 pos = 0; - while (atts[pos] != NULL) - { - std::string attr_name = atts[pos]; - std::string attr_value = atts[pos+1]; - - // Special cases - if ('i' == attr_name[0] && "id" == attr_name) - { - new_node->mID = attr_value; - } - else if ('v' == attr_name[0] && "version" == attr_name) - { - U32 version_major = 0; - U32 version_minor = 0; - if (sscanf(attr_value.c_str(), "%d.%d", &version_major, &version_minor) > 0) - { - new_node->mVersionMajor = version_major; - new_node->mVersionMinor = version_minor; - } - } - else if (('s' == attr_name[0] && "size" == attr_name) || ('l' == attr_name[0] && "length" == attr_name)) - { - U32 length; - if (sscanf(attr_value.c_str(), "%d", &length) > 0) - { - new_node->mLength = length; - } - } - else if ('p' == attr_name[0] && "precision" == attr_name) - { - U32 precision; - if (sscanf(attr_value.c_str(), "%d", &precision) > 0) - { - new_node->mPrecision = precision; - } - } - else if ('t' == attr_name[0] && "type" == attr_name) - { - if ("boolean" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_BOOLEAN; - } - else if ("integer" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_INTEGER; - } - else if ("float" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_FLOAT; - } - else if ("string" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_STRING; - } - else if ("uuid" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_UUID; - } - else if ("noderef" == attr_value) - { - new_node->mType = LLXMLNode::TYPE_NODEREF; - } - } - else if ('e' == attr_name[0] && "encoding" == attr_name) - { - if ("decimal" == attr_value) - { - new_node->mEncoding = LLXMLNode::ENCODING_DECIMAL; - } - else if ("hex" == attr_value) - { - new_node->mEncoding = LLXMLNode::ENCODING_HEX; - } - /*else if (attr_value == "base32") - { - new_node->mEncoding = LLXMLNode::ENCODING_BASE32; - }*/ - } - - // only one attribute child per description - LLXMLNodePtr attr_node; - if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE)) - { - attr_node = new LLXMLNode(attr_name.c_str(), TRUE); - attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); - } - attr_node->setValue(attr_value); - new_node->addChild(attr_node); - - pos += 2; - } - - if (parent) - { - parent->addChild(new_node); - } + // Create a new node + LLXMLNode *new_node_ptr = new LLXMLNode(name, FALSE); + + LLXMLNodePtr new_node = new_node_ptr; + new_node->mID.clear(); + LLXMLNodePtr ptr_new_node = new_node; + + // Set the parent-child relationship with the current active node + LLXMLNode* parent = (LLXMLNode *)userData; + + if (NULL == parent) + { + LL_WARNS() << "parent (userData) is NULL; aborting function" << LL_ENDL; + return; + } + + new_node_ptr->mParser = parent->mParser; + new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); + + // Set the current active node to the new node + XML_Parser *parser = parent->mParser; + XML_SetUserData(*parser, (void *)new_node_ptr); + + // Parse attributes + U32 pos = 0; + while (atts[pos] != NULL) + { + std::string attr_name = atts[pos]; + std::string attr_value = atts[pos+1]; + + // Special cases + if ('i' == attr_name[0] && "id" == attr_name) + { + new_node->mID = attr_value; + } + else if ('v' == attr_name[0] && "version" == attr_name) + { + U32 version_major = 0; + U32 version_minor = 0; + if (sscanf(attr_value.c_str(), "%d.%d", &version_major, &version_minor) > 0) + { + new_node->mVersionMajor = version_major; + new_node->mVersionMinor = version_minor; + } + } + else if (('s' == attr_name[0] && "size" == attr_name) || ('l' == attr_name[0] && "length" == attr_name)) + { + U32 length; + if (sscanf(attr_value.c_str(), "%d", &length) > 0) + { + new_node->mLength = length; + } + } + else if ('p' == attr_name[0] && "precision" == attr_name) + { + U32 precision; + if (sscanf(attr_value.c_str(), "%d", &precision) > 0) + { + new_node->mPrecision = precision; + } + } + else if ('t' == attr_name[0] && "type" == attr_name) + { + if ("boolean" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_BOOLEAN; + } + else if ("integer" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_INTEGER; + } + else if ("float" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_FLOAT; + } + else if ("string" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_STRING; + } + else if ("uuid" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_UUID; + } + else if ("noderef" == attr_value) + { + new_node->mType = LLXMLNode::TYPE_NODEREF; + } + } + else if ('e' == attr_name[0] && "encoding" == attr_name) + { + if ("decimal" == attr_value) + { + new_node->mEncoding = LLXMLNode::ENCODING_DECIMAL; + } + else if ("hex" == attr_value) + { + new_node->mEncoding = LLXMLNode::ENCODING_HEX; + } + /*else if (attr_value == "base32") + { + new_node->mEncoding = LLXMLNode::ENCODING_BASE32; + }*/ + } + + // only one attribute child per description + LLXMLNodePtr attr_node; + if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE)) + { + attr_node = new LLXMLNode(attr_name.c_str(), TRUE); + attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); + } + attr_node->setValue(attr_value); + new_node->addChild(attr_node); + + pos += 2; + } + + if (parent) + { + parent->addChild(new_node); + } } void XMLCALL EndXMLNode(void *userData, const XML_Char *name) { - // [FUGLY] Set the current active node to the current node's parent - LLXMLNode *node = (LLXMLNode *)userData; - XML_Parser *parser = node->mParser; - XML_SetUserData(*parser, (void *)node->mParent); - // SJB: total hack: - if (LLXMLNode::sStripWhitespaceValues) - { - std::string value = node->getValue(); - BOOL is_empty = TRUE; - for (std::string::size_type s = 0; s < value.length(); s++) - { - char c = value[s]; - if (c != ' ' && c != '\t' && c != '\n') - { - is_empty = FALSE; - break; - } - } - if (is_empty) - { - value.clear(); - node->setValue(value); - } - } + // [FUGLY] Set the current active node to the current node's parent + LLXMLNode *node = (LLXMLNode *)userData; + XML_Parser *parser = node->mParser; + XML_SetUserData(*parser, (void *)node->mParent); + // SJB: total hack: + if (LLXMLNode::sStripWhitespaceValues) + { + std::string value = node->getValue(); + BOOL is_empty = TRUE; + for (std::string::size_type s = 0; s < value.length(); s++) + { + char c = value[s]; + if (c != ' ' && c != '\t' && c != '\n') + { + is_empty = FALSE; + break; + } + } + if (is_empty) + { + value.clear(); + node->setValue(value); + } + } } void XMLCALL XMLData(void *userData, const XML_Char *s, int len) { - LLXMLNode* current_node = (LLXMLNode *)userData; - std::string value = current_node->getValue(); - if (LLXMLNode::sStripEscapedStrings) - { - if (s[0] == '\"' && s[len-1] == '\"') - { - // Special-case: Escaped string. - std::string unescaped_string; - for (S32 pos=1; pos<len-1; ++pos) - { - if (s[pos] == '\\' && s[pos+1] == '\\') - { - unescaped_string.append("\\"); - ++pos; - } - else if (s[pos] == '\\' && s[pos+1] == '\"') - { - unescaped_string.append("\""); - ++pos; - } - else - { - unescaped_string.append(&s[pos], 1); - } - } - value.append(unescaped_string); - current_node->setValue(value); - return; - } - } - value.append(std::string(s, len)); - current_node->setValue(value); -} - - - -// static + LLXMLNode* current_node = (LLXMLNode *)userData; + std::string value = current_node->getValue(); + if (LLXMLNode::sStripEscapedStrings) + { + if (s[0] == '\"' && s[len-1] == '\"') + { + // Special-case: Escaped string. + std::string unescaped_string; + for (S32 pos=1; pos<len-1; ++pos) + { + if (s[pos] == '\\' && s[pos+1] == '\\') + { + unescaped_string.append("\\"); + ++pos; + } + else if (s[pos] == '\\' && s[pos+1] == '\"') + { + unescaped_string.append("\""); + ++pos; + } + else + { + unescaped_string.append(&s[pos], 1); + } + } + value.append(unescaped_string); + current_node->setValue(value); + return; + } + } + value.append(std::string(s, len)); + current_node->setValue(value); +} + + + +// static bool LLXMLNode::updateNode( - LLXMLNodePtr& node, - LLXMLNodePtr& update_node) -{ - - if (!node || !update_node) - { - LL_WARNS() << "Node invalid" << LL_ENDL; - return FALSE; - } - - //update the node value - node->mValue = update_node->mValue; - - //update all attribute values - LLXMLAttribList::const_iterator itor; - - for(itor = update_node->mAttributes.begin(); itor != update_node->mAttributes.end(); ++itor) - { - const LLStringTableEntry* attribNameEntry = (*itor).first; - LLXMLNodePtr updateAttribNode = (*itor).second; - - LLXMLNodePtr attribNode; - - node->getAttribute(attribNameEntry, attribNode, 0); - - if (attribNode) - { - attribNode->mValue = updateAttribNode->mValue; - } - } - - //update all of node's children with updateNodes children that match name - LLXMLNodePtr child = node->getFirstChild(); - LLXMLNodePtr last_child = child; - LLXMLNodePtr updateChild; - - for (updateChild = update_node->getFirstChild(); updateChild.notNull(); - updateChild = updateChild->getNextSibling()) - { - while(child.notNull()) - { - std::string nodeName; - std::string updateName; - - updateChild->getAttributeString("name", updateName); - child->getAttributeString("name", nodeName); - - - //if it's a combobox there's no name, but there is a value - if (updateName.empty()) - { - updateChild->getAttributeString("value", updateName); - child->getAttributeString("value", nodeName); - } - - if ((nodeName != "") && (updateName == nodeName)) - { - updateNode(child, updateChild); - last_child = child; - child = child->getNextSibling(); - if (child.isNull()) - { - child = node->getFirstChild(); - } - break; - } - - child = child->getNextSibling(); - if (child.isNull()) - { - child = node->getFirstChild(); - } - if (child == last_child) - { - break; - } - } - } - - return TRUE; + LLXMLNodePtr& node, + LLXMLNodePtr& update_node) +{ + + if (!node || !update_node) + { + LL_WARNS() << "Node invalid" << LL_ENDL; + return FALSE; + } + + //update the node value + node->mValue = update_node->mValue; + + //update all attribute values + LLXMLAttribList::const_iterator itor; + + for(itor = update_node->mAttributes.begin(); itor != update_node->mAttributes.end(); ++itor) + { + const LLStringTableEntry* attribNameEntry = (*itor).first; + LLXMLNodePtr updateAttribNode = (*itor).second; + + LLXMLNodePtr attribNode; + + node->getAttribute(attribNameEntry, attribNode, 0); + + if (attribNode) + { + attribNode->mValue = updateAttribNode->mValue; + } + } + + //update all of node's children with updateNodes children that match name + LLXMLNodePtr child = node->getFirstChild(); + LLXMLNodePtr last_child = child; + LLXMLNodePtr updateChild; + + for (updateChild = update_node->getFirstChild(); updateChild.notNull(); + updateChild = updateChild->getNextSibling()) + { + while(child.notNull()) + { + std::string nodeName; + std::string updateName; + + updateChild->getAttributeString("name", updateName); + child->getAttributeString("name", nodeName); + + + //if it's a combobox there's no name, but there is a value + if (updateName.empty()) + { + updateChild->getAttributeString("value", updateName); + child->getAttributeString("value", nodeName); + } + + if ((nodeName != "") && (updateName == nodeName)) + { + updateNode(child, updateChild); + last_child = child; + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + break; + } + + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + if (child == last_child) + { + break; + } + } + } + + return TRUE; } // static bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree) { - // Read file - LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL; - LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ - if (fp == NULL) - { - node = NULL ; - return false; - } - fseek(fp, 0, SEEK_END); - U32 length = ftell(fp); - fseek(fp, 0, SEEK_SET); + // Read file + LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL; + LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ + if (fp == NULL) + { + node = NULL ; + return false; + } + fseek(fp, 0, SEEK_END); + U32 length = ftell(fp); + fseek(fp, 0, SEEK_SET); - U8* buffer = new U8[length+1]; - size_t nread = fread(buffer, 1, length, fp); - buffer[nread] = 0; - fclose(fp); + U8* buffer = new U8[length+1]; + size_t nread = fread(buffer, 1, length, fp); + buffer[nread] = 0; + fclose(fp); - bool rv = parseBuffer(buffer, nread, node, defaults_tree); - delete [] buffer; - return rv; + bool rv = parseBuffer(buffer, nread, node, defaults_tree); + delete [] buffer; + return rv; } // static bool LLXMLNode::parseBuffer( - U8* buffer, - U32 length, - LLXMLNodePtr& node, - LLXMLNode* defaults) + U8* buffer, + U32 length, + LLXMLNodePtr& node, + LLXMLNode* defaults) { - // Init - XML_Parser my_parser = XML_ParserCreate(NULL); - XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode); - XML_SetCharacterDataHandler(my_parser, XMLData); + // Init + XML_Parser my_parser = XML_ParserCreate(NULL); + XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode); + XML_SetCharacterDataHandler(my_parser, XMLData); - // Create a root node - LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE); - LLXMLNodePtr file_node = file_node_ptr; + // Create a root node + LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE); + LLXMLNodePtr file_node = file_node_ptr; - file_node->mParser = &my_parser; + file_node->mParser = &my_parser; - XML_SetUserData(my_parser, (void *)file_node_ptr); + XML_SetUserData(my_parser, (void *)file_node_ptr); - // Do the parsing - if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK) - { - LL_WARNS() << "Error parsing xml error code: " - << XML_ErrorString(XML_GetErrorCode(my_parser)) - << " on line " << XML_GetCurrentLineNumber(my_parser) - << LL_ENDL; - } + // Do the parsing + if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK) + { + LL_WARNS() << "Error parsing xml error code: " + << XML_ErrorString(XML_GetErrorCode(my_parser)) + << " on line " << XML_GetCurrentLineNumber(my_parser) + << LL_ENDL; + } - // Deinit - XML_ParserFree(my_parser); + // Deinit + XML_ParserFree(my_parser); - if (!file_node->mChildren || file_node->mChildren->map.size() != 1) - { - LL_WARNS() << "Parse failure - wrong number of top-level nodes xml." - << LL_ENDL; - node = NULL ; - return false; - } + if (!file_node->mChildren || file_node->mChildren->map.size() != 1) + { + LL_WARNS() << "Parse failure - wrong number of top-level nodes xml." + << LL_ENDL; + node = NULL ; + return false; + } - LLXMLNode *return_node = file_node->mChildren->map.begin()->second; + LLXMLNode *return_node = file_node->mChildren->map.begin()->second; - return_node->setDefault(defaults); - return_node->updateDefault(); + return_node->setDefault(defaults); + return_node->updateDefault(); - node = return_node; - return true; + node = return_node; + return true; } // static bool LLXMLNode::parseStream( - std::istream& str, - LLXMLNodePtr& node, - LLXMLNode* defaults) + std::istream& str, + LLXMLNodePtr& node, + LLXMLNode* defaults) { - // Init - XML_Parser my_parser = XML_ParserCreate(NULL); - XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode); - XML_SetCharacterDataHandler(my_parser, XMLData); + // Init + XML_Parser my_parser = XML_ParserCreate(NULL); + XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode); + XML_SetCharacterDataHandler(my_parser, XMLData); - // Create a root node - LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE); - LLXMLNodePtr file_node = file_node_ptr; + // Create a root node + LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE); + LLXMLNodePtr file_node = file_node_ptr; - file_node->mParser = &my_parser; + file_node->mParser = &my_parser; - XML_SetUserData(my_parser, (void *)file_node_ptr); + XML_SetUserData(my_parser, (void *)file_node_ptr); - const int BUFSIZE = 1024; - U8* buffer = new U8[BUFSIZE]; + const int BUFSIZE = 1024; + U8* buffer = new U8[BUFSIZE]; - while(str.good()) - { - str.read((char*)buffer, BUFSIZE); - int count = (int)str.gcount(); - - if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK) - { - LL_WARNS() << "Error parsing xml error code: " - << XML_ErrorString(XML_GetErrorCode(my_parser)) - << " on lne " << XML_GetCurrentLineNumber(my_parser) - << LL_ENDL; - break; - } - } - - delete [] buffer; + while(str.good()) + { + str.read((char*)buffer, BUFSIZE); + int count = (int)str.gcount(); + + if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK) + { + LL_WARNS() << "Error parsing xml error code: " + << XML_ErrorString(XML_GetErrorCode(my_parser)) + << " on lne " << XML_GetCurrentLineNumber(my_parser) + << LL_ENDL; + break; + } + } - // Deinit - XML_ParserFree(my_parser); + delete [] buffer; - if (!file_node->mChildren || file_node->mChildren->map.size() != 1) - { - LL_WARNS() << "Parse failure - wrong number of top-level nodes xml." - << LL_ENDL; - node = NULL; - return false; - } + // Deinit + XML_ParserFree(my_parser); - LLXMLNode *return_node = file_node->mChildren->map.begin()->second; + if (!file_node->mChildren || file_node->mChildren->map.size() != 1) + { + LL_WARNS() << "Parse failure - wrong number of top-level nodes xml." + << LL_ENDL; + node = NULL; + return false; + } - return_node->setDefault(defaults); - return_node->updateDefault(); + LLXMLNode *return_node = file_node->mChildren->map.begin()->second; - node = return_node; - return true; + return_node->setDefault(defaults); + return_node->updateDefault(); + + node = return_node; + return true; } BOOL LLXMLNode::isFullyDefault() { - if (mDefault.isNull()) - { - return FALSE; - } - BOOL has_default_value = (mValue == mDefault->mValue); - BOOL has_default_attribute = (mIsAttribute == mDefault->mIsAttribute); - BOOL has_default_type = mIsAttribute || (mType == mDefault->mType); - BOOL has_default_encoding = mIsAttribute || (mEncoding == mDefault->mEncoding); - BOOL has_default_precision = mIsAttribute || (mPrecision == mDefault->mPrecision); - BOOL has_default_length = mIsAttribute || (mLength == mDefault->mLength); - - if (has_default_value - && has_default_type - && has_default_encoding - && has_default_precision - && has_default_length - && has_default_attribute) - { - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator children_itr; - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNodePtr child = (*children_itr).second; - if (!child->isFullyDefault()) - { - return FALSE; - } - } - } - return TRUE; - } - - return FALSE; + if (mDefault.isNull()) + { + return FALSE; + } + BOOL has_default_value = (mValue == mDefault->mValue); + BOOL has_default_attribute = (mIsAttribute == mDefault->mIsAttribute); + BOOL has_default_type = mIsAttribute || (mType == mDefault->mType); + BOOL has_default_encoding = mIsAttribute || (mEncoding == mDefault->mEncoding); + BOOL has_default_precision = mIsAttribute || (mPrecision == mDefault->mPrecision); + BOOL has_default_length = mIsAttribute || (mLength == mDefault->mLength); + + if (has_default_value + && has_default_type + && has_default_encoding + && has_default_precision + && has_default_length + && has_default_attribute) + { + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator children_itr; + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNodePtr child = (*children_itr).second; + if (!child->isFullyDefault()) + { + return FALSE; + } + } + } + return TRUE; + } + + return FALSE; } // static bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, - const std::vector<std::string>& paths) + const std::vector<std::string>& paths) { - if (paths.empty()) return false; - - std::string filename = paths.front(); - if (filename.empty()) - { - return false; - } - - if (!LLXMLNode::parseFile(filename, root, NULL)) - { - LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL; - return false; - } - - LLXMLNodePtr updateRoot; + if (paths.empty()) return false; - std::vector<std::string>::const_iterator itor; - - // We've already dealt with the first item, skip that one - for (itor = paths.begin() + 1; itor != paths.end(); ++itor) - { - std::string layer_filename = *itor; - if(layer_filename.empty() || layer_filename == filename) - { - // no localized version of this file, that's ok, keep looking - continue; - } + std::string filename = paths.front(); + if (filename.empty()) + { + return false; + } - if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL)) - { - LL_WARNS() << "Problem reading localized UI description file: " << layer_filename << LL_ENDL; - return false; - } + if (!LLXMLNode::parseFile(filename, root, NULL)) + { + LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL; + return false; + } - std::string nodeName; - std::string updateName; + LLXMLNodePtr updateRoot; - updateRoot->getAttributeString("name", updateName); - root->getAttributeString("name", nodeName); + std::vector<std::string>::const_iterator itor; - if (updateName == nodeName) - { - LLXMLNode::updateNode(root, updateRoot); - } - } + // We've already dealt with the first item, skip that one + for (itor = paths.begin() + 1; itor != paths.end(); ++itor) + { + std::string layer_filename = *itor; + if(layer_filename.empty() || layer_filename == filename) + { + // no localized version of this file, that's ok, keep looking + continue; + } + + if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL)) + { + LL_WARNS() << "Problem reading localized UI description file: " << layer_filename << LL_ENDL; + return false; + } + + std::string nodeName; + std::string updateName; + + updateRoot->getAttributeString("name", updateName); + root->getAttributeString("name", nodeName); + + if (updateName == nodeName) + { + LLXMLNode::updateNode(root, updateRoot); + } + } - return true; + return true; } // static void LLXMLNode::writeHeaderToFile(LLFILE *out_file) { - fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"); + fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"); } void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations) { - if (isFullyDefault()) - { - // Don't write out nodes that are an exact match to defaults - return; - } + if (isFullyDefault()) + { + // Don't write out nodes that are an exact match to defaults + return; + } - std::ostringstream ostream; - writeToOstream(ostream, indent, use_type_decorations); - std::string outstring = ostream.str(); - size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file); - if (written != outstring.length()) - { - LL_WARNS() << "Short write" << LL_ENDL; - } + std::ostringstream ostream; + writeToOstream(ostream, indent, use_type_decorations); + std::string outstring = ostream.str(); + size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file); + if (written != outstring.length()) + { + LL_WARNS() << "Short write" << LL_ENDL; + } } void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations) { - if (isFullyDefault()) - { - // Don't write out nodes that are an exact match to defaults - return; - } - - BOOL has_default_type = mDefault.isNull()?FALSE:(mType == mDefault->mType); - BOOL has_default_encoding = mDefault.isNull()?FALSE:(mEncoding == mDefault->mEncoding); - BOOL has_default_precision = mDefault.isNull()?FALSE:(mPrecision == mDefault->mPrecision); - BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength); - - // stream the name - output_stream << indent << "<" << mName->mString << "\n"; - - if (use_type_decorations) - { - // ID - if (mID != "") - { - output_stream << indent << " id=\"" << mID << "\"\n"; - } - - // Type - if (!has_default_type) - { - switch (mType) - { - case TYPE_BOOLEAN: - output_stream << indent << " type=\"boolean\"\n"; - break; - case TYPE_INTEGER: - output_stream << indent << " type=\"integer\"\n"; - break; - case TYPE_FLOAT: - output_stream << indent << " type=\"float\"\n"; - break; - case TYPE_STRING: - output_stream << indent << " type=\"string\"\n"; - break; - case TYPE_UUID: - output_stream << indent << " type=\"uuid\"\n"; - break; - case TYPE_NODEREF: - output_stream << indent << " type=\"noderef\"\n"; - break; - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } - - // Encoding - if (!has_default_encoding) - { - switch (mEncoding) - { - case ENCODING_DECIMAL: - output_stream << indent << " encoding=\"decimal\"\n"; - break; - case ENCODING_HEX: - output_stream << indent << " encoding=\"hex\"\n"; - break; - /*case ENCODING_BASE32: - output_stream << indent << " encoding=\"base32\"\n"; - break;*/ - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } - - // Precision - if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) - { - output_stream << indent << " precision=\"" << mPrecision << "\"\n"; - } - - // Version - if (mVersionMajor > 0 || mVersionMinor > 0) - { - output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; - } - - // Array length - if (!has_default_length && mLength > 0) - { - output_stream << indent << " length=\"" << mLength << "\"\n"; - } - } - - { - // Write out attributes - LLXMLAttribList::const_iterator attr_itr; - LLXMLAttribList::const_iterator attr_end = mAttributes.end(); - for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr) - { - LLXMLNodePtr child = (*attr_itr).second; - if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue) - { - std::string attr = child->mName->mString; - if (use_type_decorations - && (attr == "id" || - attr == "type" || - attr == "encoding" || - attr == "precision" || - attr == "version" || - attr == "length")) - { - continue; // skip built-in attributes - } - - std::string attr_str = llformat(" %s=\"%s\"", - attr.c_str(), - escapeXML(child->mValue).c_str()); - output_stream << indent << attr_str << "\n"; - } - } - } - - // erase last \n before attaching final > or /> - output_stream.seekp(-1, std::ios::cur); - - if (mChildren.isNull() && mValue == "") - { - output_stream << " />\n"; - return; - } - else - { - output_stream << ">\n"; - if (mChildren.notNull()) - { - // stream non-attributes - std::string next_indent = indent + " "; - for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling()) - { - child->writeToOstream(output_stream, next_indent, use_type_decorations); - } - } - if (!mValue.empty()) - { - std::string contents = getTextContents(); - output_stream << indent << " " << escapeXML(contents) << "\n"; - } - output_stream << indent << "</" << mName->mString << ">\n"; - } + if (isFullyDefault()) + { + // Don't write out nodes that are an exact match to defaults + return; + } + + BOOL has_default_type = mDefault.isNull()?FALSE:(mType == mDefault->mType); + BOOL has_default_encoding = mDefault.isNull()?FALSE:(mEncoding == mDefault->mEncoding); + BOOL has_default_precision = mDefault.isNull()?FALSE:(mPrecision == mDefault->mPrecision); + BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength); + + // stream the name + output_stream << indent << "<" << mName->mString << "\n"; + + if (use_type_decorations) + { + // ID + if (mID != "") + { + output_stream << indent << " id=\"" << mID << "\"\n"; + } + + // Type + if (!has_default_type) + { + switch (mType) + { + case TYPE_BOOLEAN: + output_stream << indent << " type=\"boolean\"\n"; + break; + case TYPE_INTEGER: + output_stream << indent << " type=\"integer\"\n"; + break; + case TYPE_FLOAT: + output_stream << indent << " type=\"float\"\n"; + break; + case TYPE_STRING: + output_stream << indent << " type=\"string\"\n"; + break; + case TYPE_UUID: + output_stream << indent << " type=\"uuid\"\n"; + break; + case TYPE_NODEREF: + output_stream << indent << " type=\"noderef\"\n"; + break; + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } + + // Encoding + if (!has_default_encoding) + { + switch (mEncoding) + { + case ENCODING_DECIMAL: + output_stream << indent << " encoding=\"decimal\"\n"; + break; + case ENCODING_HEX: + output_stream << indent << " encoding=\"hex\"\n"; + break; + /*case ENCODING_BASE32: + output_stream << indent << " encoding=\"base32\"\n"; + break;*/ + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } + + // Precision + if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) + { + output_stream << indent << " precision=\"" << mPrecision << "\"\n"; + } + + // Version + if (mVersionMajor > 0 || mVersionMinor > 0) + { + output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; + } + + // Array length + if (!has_default_length && mLength > 0) + { + output_stream << indent << " length=\"" << mLength << "\"\n"; + } + } + + { + // Write out attributes + LLXMLAttribList::const_iterator attr_itr; + LLXMLAttribList::const_iterator attr_end = mAttributes.end(); + for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr) + { + LLXMLNodePtr child = (*attr_itr).second; + if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue) + { + std::string attr = child->mName->mString; + if (use_type_decorations + && (attr == "id" || + attr == "type" || + attr == "encoding" || + attr == "precision" || + attr == "version" || + attr == "length")) + { + continue; // skip built-in attributes + } + + std::string attr_str = llformat(" %s=\"%s\"", + attr.c_str(), + escapeXML(child->mValue).c_str()); + output_stream << indent << attr_str << "\n"; + } + } + } + + // erase last \n before attaching final > or /> + output_stream.seekp(-1, std::ios::cur); + + if (mChildren.isNull() && mValue == "") + { + output_stream << " />\n"; + return; + } + else + { + output_stream << ">\n"; + if (mChildren.notNull()) + { + // stream non-attributes + std::string next_indent = indent + " "; + for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling()) + { + child->writeToOstream(output_stream, next_indent, use_type_decorations); + } + } + if (!mValue.empty()) + { + std::string contents = getTextContents(); + output_stream << indent << " " << escapeXML(contents) << "\n"; + } + output_stream << indent << "</" << mName->mString << ">\n"; + } } void LLXMLNode::findName(const std::string& name, LLXMLNodeList &results) { LLStringTableEntry* name_entry = gStringTable.checkStringEntry(name); - if (name_entry == mName) - { - results.insert(std::make_pair(this->mName->mString, this)); - return; - } - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator children_itr; - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNodePtr child = (*children_itr).second; - child->findName(name_entry, results); - } - } + if (name_entry == mName) + { + results.insert(std::make_pair(this->mName->mString, this)); + return; + } + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator children_itr; + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNodePtr child = (*children_itr).second; + child->findName(name_entry, results); + } + } } void LLXMLNode::findName(LLStringTableEntry* name, LLXMLNodeList &results) { - if (name == mName) - { - results.insert(std::make_pair(this->mName->mString, this)); - return; - } - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator children_itr; - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNodePtr child = (*children_itr).second; - child->findName(name, results); - } - } + if (name == mName) + { + results.insert(std::make_pair(this->mName->mString, this)); + return; + } + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator children_itr; + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNodePtr child = (*children_itr).second; + child->findName(name, results); + } + } } void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results) { - if (id == mID) - { - results.insert(std::make_pair(this->mName->mString, this)); - return; - } - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator children_itr; - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNodePtr child = (*children_itr).second; - child->findID(id, results); - } - } + if (id == mID) + { + results.insert(std::make_pair(this->mName->mString, this)); + return; + } + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator children_itr; + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNodePtr child = (*children_itr).second; + child->findID(id, results); + } + } } void LLXMLNode::scrubToTree(LLXMLNode *tree) { - if (!tree || tree->mChildren.isNull()) - { - return; - } - if (mChildren.notNull()) - { - std::vector<LLXMLNodePtr> to_delete_list; - LLXMLChildList::iterator itor = mChildren->map.begin(); - while (itor != mChildren->map.end()) - { - LLXMLNodePtr child = itor->second; - LLXMLNodePtr child_tree = NULL; - // Look for this child in the default's children - bool found = false; - LLXMLChildList::iterator itor2 = tree->mChildren->map.begin(); - while (itor2 != tree->mChildren->map.end()) - { - if (child->mName == itor2->second->mName) - { - child_tree = itor2->second; - found = true; - } - ++itor2; - } - if (!found) - { - to_delete_list.push_back(child); - } - else - { - child->scrubToTree(child_tree); - } - ++itor; - } - std::vector<LLXMLNodePtr>::iterator itor3; - for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) - { - LLXMLNodePtr ptr; - (*itor3)->setParent(ptr); - } - } + if (!tree || tree->mChildren.isNull()) + { + return; + } + if (mChildren.notNull()) + { + std::vector<LLXMLNodePtr> to_delete_list; + LLXMLChildList::iterator itor = mChildren->map.begin(); + while (itor != mChildren->map.end()) + { + LLXMLNodePtr child = itor->second; + LLXMLNodePtr child_tree = NULL; + // Look for this child in the default's children + bool found = false; + LLXMLChildList::iterator itor2 = tree->mChildren->map.begin(); + while (itor2 != tree->mChildren->map.end()) + { + if (child->mName == itor2->second->mName) + { + child_tree = itor2->second; + found = true; + } + ++itor2; + } + if (!found) + { + to_delete_list.push_back(child); + } + else + { + child->scrubToTree(child_tree); + } + ++itor; + } + std::vector<LLXMLNodePtr>::iterator itor3; + for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) + { + LLXMLNodePtr ptr; + (*itor3)->setParent(ptr); + } + } } bool LLXMLNode::getChild(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing) @@ -1160,21 +1160,21 @@ bool LLXMLNode::getChild(const char* name, LLXMLNodePtr& node, BOOL use_default_ bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing) { - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); - if (child_itr != mChildren->map.end()) - { - node = (*child_itr).second; - return true; - } - } - if (use_default_if_missing && !mDefault.isNull()) - { - return mDefault->getChild(name, node, FALSE); - } - node = NULL; - return false; + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); + if (child_itr != mChildren->map.end()) + { + node = (*child_itr).second; + return true; + } + } + if (use_default_if_missing && !mDefault.isNull()) + { + return mDefault->getChild(name, node, FALSE); + } + node = NULL; + return false; } void LLXMLNode::getChildren(const char* name, LLXMLNodeList &children, BOOL use_default_if_missing) const @@ -1184,47 +1184,47 @@ void LLXMLNode::getChildren(const char* name, LLXMLNodeList &children, BOOL use_ void LLXMLNode::getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, BOOL use_default_if_missing) const { - if (mChildren.notNull()) - { - LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); - if (child_itr != mChildren->map.end()) - { - LLXMLChildList::const_iterator children_end = mChildren->map.end(); - while (child_itr != children_end) - { - LLXMLNodePtr child = (*child_itr).second; - if (name != child->mName) - { - break; - } - children.insert(std::make_pair(child->mName->mString, child)); - child_itr++; - } - } - } - if (children.size() == 0 && use_default_if_missing && !mDefault.isNull()) - { - mDefault->getChildren(name, children, FALSE); - } + if (mChildren.notNull()) + { + LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); + if (child_itr != mChildren->map.end()) + { + LLXMLChildList::const_iterator children_end = mChildren->map.end(); + while (child_itr != children_end) + { + LLXMLNodePtr child = (*child_itr).second; + if (name != child->mName) + { + break; + } + children.insert(std::make_pair(child->mName->mString, child)); + child_itr++; + } + } + } + if (children.size() == 0 && use_default_if_missing && !mDefault.isNull()) + { + mDefault->getChildren(name, children, FALSE); + } } // recursively walks the tree and returns all children at all nesting levels matching the name void LLXMLNode::getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const { - if (mChildren.notNull()) - { - for (LLXMLChildList::const_iterator child_itr = mChildren->map.begin(); - child_itr != mChildren->map.end(); ++child_itr) - { - LLXMLNodePtr child = (*child_itr).second; - if (name == child->mName) - { - children.insert(std::make_pair(child->mName->mString, child)); - } - // and check each child as well - child->getDescendants(name, children); - } - } + if (mChildren.notNull()) + { + for (LLXMLChildList::const_iterator child_itr = mChildren->map.begin(); + child_itr != mChildren->map.end(); ++child_itr) + { + LLXMLNodePtr child = (*child_itr).second; + if (name == child->mName) + { + children.insert(std::make_pair(child->mName->mString, child)); + } + // and check each child as well + child->getDescendants(name, children); + } + } } bool LLXMLNode::getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing) @@ -1234,37 +1234,37 @@ bool LLXMLNode::getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_defa bool LLXMLNode::getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing) { - LLXMLAttribList::const_iterator child_itr = mAttributes.find(name); - if (child_itr != mAttributes.end()) - { - node = (*child_itr).second; - return true; - } - if (use_default_if_missing && !mDefault.isNull()) - { - return mDefault->getAttribute(name, node, FALSE); - } - - return false; + LLXMLAttribList::const_iterator child_itr = mAttributes.find(name); + if (child_itr != mAttributes.end()) + { + node = (*child_itr).second; + return true; + } + if (use_default_if_missing && !mDefault.isNull()) + { + return mDefault->getAttribute(name, node, FALSE); + } + + return false; } bool LLXMLNode::setAttributeString(const char* attr, const std::string& value) { - LLStringTableEntry* name = gStringTable.checkStringEntry(attr); - LLXMLAttribList::const_iterator child_itr = mAttributes.find(name); - if (child_itr != mAttributes.end()) - { - LLXMLNodePtr node = (*child_itr).second; - node->setValue(value); - return true; - } - return false; + LLStringTableEntry* name = gStringTable.checkStringEntry(attr); + LLXMLAttribList::const_iterator child_itr = mAttributes.find(name); + if (child_itr != mAttributes.end()) + { + LLXMLNodePtr node = (*child_itr).second; + node->setValue(value); + return true; + } + return false; } BOOL LLXMLNode::hasAttribute(const char* name ) { - LLXMLNodePtr node; - return getAttribute(name, node); + LLXMLNodePtr node; + return getAttribute(name, node); } // the structure of these getAttribute_ functions is ugly, but it's because the @@ -1273,1072 +1273,1072 @@ BOOL LLXMLNode::hasAttribute(const char* name ) // simplified. bool LLXMLNode::getAttribute_bool(const char* name, bool& value ) { - LLXMLNodePtr node; + LLXMLNodePtr node; if (!getAttribute(name, node)) { return false; } BOOL temp; - bool retval = node->getBoolValue(1, &temp); + bool retval = node->getBoolValue(1, &temp); value = temp; return retval; } BOOL LLXMLNode::getAttributeBOOL(const char* name, BOOL& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getBoolValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getBoolValue(1, &value)); } BOOL LLXMLNode::getAttributeU8(const char* name, U8& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getByteValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getByteValue(1, &value)); } BOOL LLXMLNode::getAttributeS8(const char* name, S8& value ) { - LLXMLNodePtr node; - S32 val; - if (!(getAttribute(name, node) && node->getIntValue(1, &val))) - { - return false; - } - value = val; - return true; + LLXMLNodePtr node; + S32 val; + if (!(getAttribute(name, node) && node->getIntValue(1, &val))) + { + return false; + } + value = val; + return true; } BOOL LLXMLNode::getAttributeU16(const char* name, U16& value ) { - LLXMLNodePtr node; - U32 val; - if (!(getAttribute(name, node) && node->getUnsignedValue(1, &val))) - { - return false; - } - value = val; - return true; + LLXMLNodePtr node; + U32 val; + if (!(getAttribute(name, node) && node->getUnsignedValue(1, &val))) + { + return false; + } + value = val; + return true; } BOOL LLXMLNode::getAttributeS16(const char* name, S16& value ) { - LLXMLNodePtr node; - S32 val; - if (!(getAttribute(name, node) && node->getIntValue(1, &val))) - { - return false; - } - value = val; - return true; + LLXMLNodePtr node; + S32 val; + if (!(getAttribute(name, node) && node->getIntValue(1, &val))) + { + return false; + } + value = val; + return true; } BOOL LLXMLNode::getAttributeU32(const char* name, U32& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getUnsignedValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getUnsignedValue(1, &value)); } BOOL LLXMLNode::getAttributeS32(const char* name, S32& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getIntValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getIntValue(1, &value)); } BOOL LLXMLNode::getAttributeF32(const char* name, F32& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getFloatValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getFloatValue(1, &value)); } BOOL LLXMLNode::getAttributeF64(const char* name, F64& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getDoubleValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getDoubleValue(1, &value)); } BOOL LLXMLNode::getAttributeColor(const char* name, LLColor4& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getFloatValue(4, value.mV)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getFloatValue(4, value.mV)); } BOOL LLXMLNode::getAttributeColor4(const char* name, LLColor4& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getFloatValue(4, value.mV)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getFloatValue(4, value.mV)); } BOOL LLXMLNode::getAttributeColor4U(const char* name, LLColor4U& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getByteValue(4, value.mV)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getByteValue(4, value.mV)); } BOOL LLXMLNode::getAttributeVector3(const char* name, LLVector3& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getFloatValue(3, value.mV)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getFloatValue(3, value.mV)); } BOOL LLXMLNode::getAttributeVector3d(const char* name, LLVector3d& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getDoubleValue(3, value.mdV)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getDoubleValue(3, value.mdV)); } BOOL LLXMLNode::getAttributeQuat(const char* name, LLQuaternion& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getFloatValue(4, value.mQ)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getFloatValue(4, value.mQ)); } BOOL LLXMLNode::getAttributeUUID(const char* name, LLUUID& value ) { - LLXMLNodePtr node; - return (getAttribute(name, node) && node->getUUIDValue(1, &value)); + LLXMLNodePtr node; + return (getAttribute(name, node) && node->getUUIDValue(1, &value)); } BOOL LLXMLNode::getAttributeString(const char* name, std::string& value ) { - LLXMLNodePtr node; - if (!getAttribute(name, node)) - { - return false; - } - value = node->getValue(); - return true; + LLXMLNodePtr node; + if (!getAttribute(name, node)) + { + return false; + } + value = node->getValue(); + return true; } LLXMLNodePtr LLXMLNode::getRoot() { - if (mParent == NULL) - { - return this; - } - return mParent->getRoot(); + if (mParent == NULL) + { + return this; + } + return mParent->getRoot(); } /*static */ const char *LLXMLNode::skipWhitespace(const char *str) { - // skip whitespace characters - while (str[0] == ' ' || str[0] == '\t' || str[0] == '\n') ++str; - return str; + // skip whitespace characters + while (str[0] == ' ' || str[0] == '\t' || str[0] == '\n') ++str; + return str; } /*static */ const char *LLXMLNode::skipNonWhitespace(const char *str) { - // skip non-whitespace characters - while (str[0] != ' ' && str[0] != '\t' && str[0] != '\n' && str[0] != 0) ++str; - return str; + // skip non-whitespace characters + while (str[0] != ' ' && str[0] != '\t' && str[0] != '\n' && str[0] != 0) ++str; + return str; } /*static */ const char *LLXMLNode::parseInteger(const char *str, U64 *dest, BOOL *is_negative, U32 precision, Encoding encoding) { - *dest = 0; - *is_negative = FALSE; - - str = skipWhitespace(str); - - if (str[0] == 0) return NULL; - - if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT) - { - if (str[0] == '+') - { - ++str; - } - if (str[0] == '-') - { - *is_negative = TRUE; - ++str; - } - - str = skipWhitespace(str); - - U64 ret = 0; - while (str[0] >= '0' && str[0] <= '9') - { - ret *= 10; - ret += str[0] - '0'; - ++str; - } - - if (str[0] == '.') - { - // If there is a fractional part, skip it - str = skipNonWhitespace(str); - } - - *dest = ret; - return str; - } - if (encoding == ENCODING_HEX) - { - U64 ret = 0; - str = skipWhitespace(str); - for (U32 pos=0; pos<(precision/4); ++pos) - { - ret <<= 4; - str = skipWhitespace(str); - if (str[0] >= '0' && str[0] <= '9') - { - ret += str[0] - '0'; - } - else if (str[0] >= 'a' && str[0] <= 'f') - { - ret += str[0] - 'a' + 10; - } - else if (str[0] >= 'A' && str[0] <= 'F') - { - ret += str[0] - 'A' + 10; - } - else - { - return NULL; - } - ++str; - } - - *dest = ret; - return str; - } - return NULL; + *dest = 0; + *is_negative = FALSE; + + str = skipWhitespace(str); + + if (str[0] == 0) return NULL; + + if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT) + { + if (str[0] == '+') + { + ++str; + } + if (str[0] == '-') + { + *is_negative = TRUE; + ++str; + } + + str = skipWhitespace(str); + + U64 ret = 0; + while (str[0] >= '0' && str[0] <= '9') + { + ret *= 10; + ret += str[0] - '0'; + ++str; + } + + if (str[0] == '.') + { + // If there is a fractional part, skip it + str = skipNonWhitespace(str); + } + + *dest = ret; + return str; + } + if (encoding == ENCODING_HEX) + { + U64 ret = 0; + str = skipWhitespace(str); + for (U32 pos=0; pos<(precision/4); ++pos) + { + ret <<= 4; + str = skipWhitespace(str); + if (str[0] >= '0' && str[0] <= '9') + { + ret += str[0] - '0'; + } + else if (str[0] >= 'a' && str[0] <= 'f') + { + ret += str[0] - 'a' + 10; + } + else if (str[0] >= 'A' && str[0] <= 'F') + { + ret += str[0] - 'A' + 10; + } + else + { + return NULL; + } + ++str; + } + + *dest = ret; + return str; + } + return NULL; } // 25 elements - decimal expansions of 1/(2^n), multiplied by 10 each iteration -const U64 float_coeff_table[] = - { 5, 25, 125, 625, 3125, - 15625, 78125, 390625, 1953125, 9765625, - 48828125, 244140625, 1220703125, 6103515625LL, 30517578125LL, - 152587890625LL, 762939453125LL, 3814697265625LL, 19073486328125LL, 95367431640625LL, - 476837158203125LL, 2384185791015625LL, 11920928955078125LL, 59604644775390625LL, 298023223876953125LL }; +const U64 float_coeff_table[] = + { 5, 25, 125, 625, 3125, + 15625, 78125, 390625, 1953125, 9765625, + 48828125, 244140625, 1220703125, 6103515625LL, 30517578125LL, + 152587890625LL, 762939453125LL, 3814697265625LL, 19073486328125LL, 95367431640625LL, + 476837158203125LL, 2384185791015625LL, 11920928955078125LL, 59604644775390625LL, 298023223876953125LL }; // 36 elements - decimal expansions of 1/(2^n) after the last 28, truncated, no multiply each iteration const U64 float_coeff_table_2[] = - { 149011611938476562LL,74505805969238281LL, - 37252902984619140LL, 18626451492309570LL, 9313225746154785LL, 4656612873077392LL, - 2328306436538696LL, 1164153218269348LL, 582076609134674LL, 291038304567337LL, - 145519152283668LL, 72759576141834LL, 36379788070917LL, 18189894035458LL, - 9094947017729LL, 4547473508864LL, 2273736754432LL, 1136868377216LL, - 568434188608LL, 284217094304LL, 142108547152LL, 71054273576LL, - 35527136788LL, 17763568394LL, 8881784197LL, 4440892098LL, - 2220446049LL, 1110223024LL, 555111512LL, 277555756LL, - 138777878, 69388939, 34694469, 17347234, - 8673617, 4336808, 2168404, 1084202, - 542101, 271050, 135525, 67762, - }; + { 149011611938476562LL,74505805969238281LL, + 37252902984619140LL, 18626451492309570LL, 9313225746154785LL, 4656612873077392LL, + 2328306436538696LL, 1164153218269348LL, 582076609134674LL, 291038304567337LL, + 145519152283668LL, 72759576141834LL, 36379788070917LL, 18189894035458LL, + 9094947017729LL, 4547473508864LL, 2273736754432LL, 1136868377216LL, + 568434188608LL, 284217094304LL, 142108547152LL, 71054273576LL, + 35527136788LL, 17763568394LL, 8881784197LL, 4440892098LL, + 2220446049LL, 1110223024LL, 555111512LL, 277555756LL, + 138777878, 69388939, 34694469, 17347234, + 8673617, 4336808, 2168404, 1084202, + 542101, 271050, 135525, 67762, + }; /*static */ const char *LLXMLNode::parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding) { - str = skipWhitespace(str); - - if (str[0] == 0) return NULL; - - if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT) - { - str = skipWhitespace(str); - - if (memcmp(str, "inf", 3) == 0) - { - *(U64 *)dest = 0x7FF0000000000000ll; - return str + 3; - } - if (memcmp(str, "-inf", 4) == 0) - { - *(U64 *)dest = 0xFFF0000000000000ll; - return str + 4; - } - if (memcmp(str, "1.#INF", 6) == 0) - { - *(U64 *)dest = 0x7FF0000000000000ll; - return str + 6; - } - if (memcmp(str, "-1.#INF", 7) == 0) - { - *(U64 *)dest = 0xFFF0000000000000ll; - return str + 7; - } - - F64 negative = 1.0f; - if (str[0] == '+') - { - ++str; - } - if (str[0] == '-') - { - negative = -1.0f; - ++str; - } - - const char* base_str = str; - str = skipWhitespace(str); - - // Parse the integer part of the expression - U64 int_part = 0; - while (str[0] >= '0' && str[0] <= '9') - { - int_part *= 10; - int_part += U64(str[0] - '0'); - ++str; - } - - U64 f_part = 0;//, f_decimal = 1; - if (str[0] == '.') - { - ++str; - U64 remainder = 0; - U32 pos = 0; - // Parse the decimal part of the expression - while (str[0] >= '0' && str[0] <= '9' && pos < 25) - { - remainder = (remainder*10) + U64(str[0] - '0'); - f_part <<= 1; - //f_decimal <<= 1; - // Check the n'th bit - if (remainder >= float_coeff_table[pos]) - { - remainder -= float_coeff_table[pos]; - f_part |= 1; - } - ++pos; - ++str; - } - if (pos == 25) - { - // Drop any excessive digits - while (str[0] >= '0' && str[0] <= '9') - { - ++str; - } - } - else - { - while (pos < 25) - { - remainder *= 10; - f_part <<= 1; - //f_decimal <<= 1; - // Check the n'th bit - if (remainder >= float_coeff_table[pos]) - { - remainder -= float_coeff_table[pos]; - f_part |= 1; - } - ++pos; - } - } - pos = 0; - while (pos < 36) - { - f_part <<= 1; - //f_decimal <<= 1; - if (remainder >= float_coeff_table_2[pos]) - { - remainder -= float_coeff_table_2[pos]; - f_part |= 1; - } - ++pos; - } - } - - F64 ret = F64(int_part) + (F64(f_part)/F64(1LL<<61)); - - F64 exponent = 1.f; - if (str[0] == 'e') - { - // Scientific notation! - ++str; - U64 exp; - BOOL is_negative; - str = parseInteger(str, &exp, &is_negative, 64, ENCODING_DECIMAL); - if (str == NULL) - { - exp = 1; - } - F64 exp_d = F64(exp) * (is_negative?-1:1); - exponent = pow(10.0, exp_d); - } - - if (str == base_str) - { - // no digits parsed - return NULL; - } - else - { - *dest = ret*negative*exponent; - return str; - } - } - if (encoding == ENCODING_HEX) - { - U64 bytes_dest; - BOOL is_negative; - str = parseInteger(str, (U64 *)&bytes_dest, &is_negative, precision, ENCODING_HEX); - // Upcast to F64 - switch (precision) - { - case 32: - { - U32 short_dest = (U32)bytes_dest; - F32 ret_val = *(F32 *)&short_dest; - *dest = ret_val; - } - break; - case 64: - *dest = *(F64 *)&bytes_dest; - break; - default: - return NULL; - } - return str; - } - return NULL; + str = skipWhitespace(str); + + if (str[0] == 0) return NULL; + + if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT) + { + str = skipWhitespace(str); + + if (memcmp(str, "inf", 3) == 0) + { + *(U64 *)dest = 0x7FF0000000000000ll; + return str + 3; + } + if (memcmp(str, "-inf", 4) == 0) + { + *(U64 *)dest = 0xFFF0000000000000ll; + return str + 4; + } + if (memcmp(str, "1.#INF", 6) == 0) + { + *(U64 *)dest = 0x7FF0000000000000ll; + return str + 6; + } + if (memcmp(str, "-1.#INF", 7) == 0) + { + *(U64 *)dest = 0xFFF0000000000000ll; + return str + 7; + } + + F64 negative = 1.0f; + if (str[0] == '+') + { + ++str; + } + if (str[0] == '-') + { + negative = -1.0f; + ++str; + } + + const char* base_str = str; + str = skipWhitespace(str); + + // Parse the integer part of the expression + U64 int_part = 0; + while (str[0] >= '0' && str[0] <= '9') + { + int_part *= 10; + int_part += U64(str[0] - '0'); + ++str; + } + + U64 f_part = 0;//, f_decimal = 1; + if (str[0] == '.') + { + ++str; + U64 remainder = 0; + U32 pos = 0; + // Parse the decimal part of the expression + while (str[0] >= '0' && str[0] <= '9' && pos < 25) + { + remainder = (remainder*10) + U64(str[0] - '0'); + f_part <<= 1; + //f_decimal <<= 1; + // Check the n'th bit + if (remainder >= float_coeff_table[pos]) + { + remainder -= float_coeff_table[pos]; + f_part |= 1; + } + ++pos; + ++str; + } + if (pos == 25) + { + // Drop any excessive digits + while (str[0] >= '0' && str[0] <= '9') + { + ++str; + } + } + else + { + while (pos < 25) + { + remainder *= 10; + f_part <<= 1; + //f_decimal <<= 1; + // Check the n'th bit + if (remainder >= float_coeff_table[pos]) + { + remainder -= float_coeff_table[pos]; + f_part |= 1; + } + ++pos; + } + } + pos = 0; + while (pos < 36) + { + f_part <<= 1; + //f_decimal <<= 1; + if (remainder >= float_coeff_table_2[pos]) + { + remainder -= float_coeff_table_2[pos]; + f_part |= 1; + } + ++pos; + } + } + + F64 ret = F64(int_part) + (F64(f_part)/F64(1LL<<61)); + + F64 exponent = 1.f; + if (str[0] == 'e') + { + // Scientific notation! + ++str; + U64 exp; + BOOL is_negative; + str = parseInteger(str, &exp, &is_negative, 64, ENCODING_DECIMAL); + if (str == NULL) + { + exp = 1; + } + F64 exp_d = F64(exp) * (is_negative?-1:1); + exponent = pow(10.0, exp_d); + } + + if (str == base_str) + { + // no digits parsed + return NULL; + } + else + { + *dest = ret*negative*exponent; + return str; + } + } + if (encoding == ENCODING_HEX) + { + U64 bytes_dest; + BOOL is_negative; + str = parseInteger(str, (U64 *)&bytes_dest, &is_negative, precision, ENCODING_HEX); + // Upcast to F64 + switch (precision) + { + case 32: + { + U32 short_dest = (U32)bytes_dest; + F32 ret_val = *(F32 *)&short_dest; + *dest = ret_val; + } + break; + case 64: + *dest = *(F64 *)&bytes_dest; + break; + default: + return NULL; + } + return str; + } + return NULL; } U32 LLXMLNode::getBoolValue(U32 expected_length, BOOL *array) { - llassert(array); + llassert(array); - // Check type - accept booleans or strings - if (mType != TYPE_BOOLEAN && mType != TYPE_STRING && mType != TYPE_UNKNOWN) - { - return 0; - } + // Check type - accept booleans or strings + if (mType != TYPE_BOOLEAN && mType != TYPE_STRING && mType != TYPE_UNKNOWN) + { + return 0; + } - std::string *str_array = new std::string[expected_length]; + std::string *str_array = new std::string[expected_length]; - U32 length = getStringValue(expected_length, str_array); + U32 length = getStringValue(expected_length, str_array); - U32 ret_length = 0; - for (U32 i=0; i<length; ++i) - { - LLStringUtil::toLower(str_array[i]); - if (str_array[i] == "false") - { - array[ret_length++] = FALSE; - } - else if (str_array[i] == "true") - { - array[ret_length++] = TRUE; - } - } + U32 ret_length = 0; + for (U32 i=0; i<length; ++i) + { + LLStringUtil::toLower(str_array[i]); + if (str_array[i] == "false") + { + array[ret_length++] = FALSE; + } + else if (str_array[i] == "true") + { + array[ret_length++] = TRUE; + } + } - delete[] str_array; + delete[] str_array; #if LL_DEBUG - if (ret_length != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getBoolValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << ret_length << LL_ENDL; - } + if (ret_length != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getBoolValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << ret_length << LL_ENDL; + } #endif - return ret_length; + return ret_length; } U32 LLXMLNode::getByteValue(U32 expected_length, U8 *array, Encoding encoding) { - llassert(array); - - // Check type - accept bytes or integers (below 256 only) - if (mType != TYPE_INTEGER - && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getByteValue asked for " << expected_length - << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i; - for (i=0; i<expected_length; ++i) - { - U64 value; - BOOL is_negative; - value_string = parseInteger(value_string, &value, &is_negative, 8, encoding); - if (value_string == NULL) - { - break; - } - if (value > 255 || is_negative) - { - LL_WARNS() << "getByteValue: Value outside of valid range." << LL_ENDL; - break; - } - array[i] = U8(value); - } + llassert(array); + + // Check type - accept bytes or integers (below 256 only) + if (mType != TYPE_INTEGER + && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getByteValue asked for " << expected_length + << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i; + for (i=0; i<expected_length; ++i) + { + U64 value; + BOOL is_negative; + value_string = parseInteger(value_string, &value, &is_negative, 8, encoding); + if (value_string == NULL) + { + break; + } + if (value > 255 || is_negative) + { + LL_WARNS() << "getByteValue: Value outside of valid range." << LL_ENDL; + break; + } + array[i] = U8(value); + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getByteValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getByteValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getIntValue(U32 expected_length, S32 *array, Encoding encoding) { - llassert(array); - - // Check type - accept bytes or integers - if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getIntValue asked for " << expected_length - << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i = 0; - for (i=0; i<expected_length; ++i) - { - U64 value; - BOOL is_negative; - value_string = parseInteger(value_string, &value, &is_negative, 32, encoding); - if (value_string == NULL) - { - break; - } - if (value > 0x7fffffff) - { - LL_WARNS() << "getIntValue: Value outside of valid range." << LL_ENDL; - break; - } - array[i] = S32(value) * (is_negative?-1:1); - } + llassert(array); + + // Check type - accept bytes or integers + if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getIntValue asked for " << expected_length + << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i = 0; + for (i=0; i<expected_length; ++i) + { + U64 value; + BOOL is_negative; + value_string = parseInteger(value_string, &value, &is_negative, 32, encoding); + if (value_string == NULL) + { + break; + } + if (value > 0x7fffffff) + { + LL_WARNS() << "getIntValue: Value outside of valid range." << LL_ENDL; + break; + } + array[i] = S32(value) * (is_negative?-1:1); + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getIntValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getIntValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getUnsignedValue(U32 expected_length, U32 *array, Encoding encoding) { - llassert(array); - - // Check type - accept bytes or integers - if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getUnsignedValue asked for " << expected_length - << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i = 0; - // Int type - for (i=0; i<expected_length; ++i) - { - U64 value; - BOOL is_negative; - value_string = parseInteger(value_string, &value, &is_negative, 32, encoding); - if (value_string == NULL) - { - break; - } - if (is_negative || value > 0xffffffff) - { - LL_WARNS() << "getUnsignedValue: Value outside of valid range." << LL_ENDL; - break; - } - array[i] = U32(value); - } + llassert(array); + + // Check type - accept bytes or integers + if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getUnsignedValue asked for " << expected_length + << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i = 0; + // Int type + for (i=0; i<expected_length; ++i) + { + U64 value; + BOOL is_negative; + value_string = parseInteger(value_string, &value, &is_negative, 32, encoding); + if (value_string == NULL) + { + break; + } + if (is_negative || value > 0xffffffff) + { + LL_WARNS() << "getUnsignedValue: Value outside of valid range." << LL_ENDL; + break; + } + array[i] = U32(value); + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getUnsignedValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getUnsignedValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getLongValue(U32 expected_length, U64 *array, Encoding encoding) { - llassert(array); - - // Check type - accept bytes or integers - if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getLongValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i = 0; - // Int type - for (i=0; i<expected_length; ++i) - { - U64 value; - BOOL is_negative; - value_string = parseInteger(value_string, &value, &is_negative, 64, encoding); - if (value_string == NULL) - { - break; - } - if (is_negative) - { - LL_WARNS() << "getLongValue: Value outside of valid range." << LL_ENDL; - break; - } - array[i] = value; - } + llassert(array); + + // Check type - accept bytes or integers + if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getLongValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i = 0; + // Int type + for (i=0; i<expected_length; ++i) + { + U64 value; + BOOL is_negative; + value_string = parseInteger(value_string, &value, &is_negative, 64, encoding); + if (value_string == NULL) + { + break; + } + if (is_negative) + { + LL_WARNS() << "getLongValue: Value outside of valid range." << LL_ENDL; + break; + } + array[i] = value; + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getLongValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getLongValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getFloatValue(U32 expected_length, F32 *array, Encoding encoding) { - llassert(array); - - // Check type - accept only floats or doubles - if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getFloatValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i; - for (i=0; i<expected_length; ++i) - { - F64 value; - value_string = parseFloat(value_string, &value, 32, encoding); - if (value_string == NULL) - { - break; - } - array[i] = F32(value); - } + llassert(array); + + // Check type - accept only floats or doubles + if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getFloatValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i; + for (i=0; i<expected_length; ++i) + { + F64 value; + value_string = parseFloat(value_string, &value, 32, encoding); + if (value_string == NULL) + { + break; + } + array[i] = F32(value); + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getFloatValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getFloatValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getDoubleValue(U32 expected_length, F64 *array, Encoding encoding) { - llassert(array); - - // Check type - accept only floats or doubles - if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN) - { - return 0; - } - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getDoubleValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - if (encoding == ENCODING_DEFAULT) - { - encoding = mEncoding; - } - - const char *value_string = mValue.c_str(); - - U32 i; - for (i=0; i<expected_length; ++i) - { - F64 value; - value_string = parseFloat(value_string, &value, 64, encoding); - if (value_string == NULL) - { - break; - } - array[i] = value; - } + llassert(array); + + // Check type - accept only floats or doubles + if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN) + { + return 0; + } + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getDoubleValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + if (encoding == ENCODING_DEFAULT) + { + encoding = mEncoding; + } + + const char *value_string = mValue.c_str(); + + U32 i; + for (i=0; i<expected_length; ++i) + { + F64 value; + value_string = parseFloat(value_string, &value, 64, encoding); + if (value_string == NULL) + { + break; + } + array[i] = value; + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getDoubleValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getDoubleValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getStringValue(U32 expected_length, std::string *array) { - llassert(array); - - // Can always return any value as a string - - if (mLength > 0 && mLength != expected_length) - { - LL_WARNS() << "XMLNode::getStringValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; - return 0; - } - - U32 num_returned_strings = 0; - - // Array of strings is whitespace-separated - const std::string sep(" \n\t"); - - std::string::size_type n = 0; - std::string::size_type m = 0; - while(1) - { - if (num_returned_strings >= expected_length) - { - break; - } - n = mValue.find_first_not_of(sep, m); - m = mValue.find_first_of(sep, n); - if (m == std::string::npos) - { - break; - } - array[num_returned_strings++] = mValue.substr(n,m-n); - } - if (n != std::string::npos && num_returned_strings < expected_length) - { - array[num_returned_strings++] = mValue.substr(n); - } + llassert(array); + + // Can always return any value as a string + + if (mLength > 0 && mLength != expected_length) + { + LL_WARNS() << "XMLNode::getStringValue asked for " << expected_length << " elements, while node has " << mLength << LL_ENDL; + return 0; + } + + U32 num_returned_strings = 0; + + // Array of strings is whitespace-separated + const std::string sep(" \n\t"); + + std::string::size_type n = 0; + std::string::size_type m = 0; + while(1) + { + if (num_returned_strings >= expected_length) + { + break; + } + n = mValue.find_first_not_of(sep, m); + m = mValue.find_first_of(sep, n); + if (m == std::string::npos) + { + break; + } + array[num_returned_strings++] = mValue.substr(n,m-n); + } + if (n != std::string::npos && num_returned_strings < expected_length) + { + array[num_returned_strings++] = mValue.substr(n); + } #if LL_DEBUG - if (num_returned_strings != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getStringValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << num_returned_strings << LL_ENDL; - } + if (num_returned_strings != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getStringValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << num_returned_strings << LL_ENDL; + } #endif - return num_returned_strings; + return num_returned_strings; } U32 LLXMLNode::getUUIDValue(U32 expected_length, LLUUID *array) { - llassert(array); - - // Check type - if (mType != TYPE_UUID && mType != TYPE_UNKNOWN) - { - return 0; - } - - const char *value_string = mValue.c_str(); - - U32 i; - for (i=0; i<expected_length; ++i) - { - LLUUID uuid_value; - value_string = skipWhitespace(value_string); - - if (strlen(value_string) < (UUID_STR_LENGTH-1)) /* Flawfinder: ignore */ - { - break; - } - char uuid_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */ - memcpy(uuid_string, value_string, (UUID_STR_LENGTH-1)); /* Flawfinder: ignore */ - uuid_string[(UUID_STR_LENGTH-1)] = 0; - - if (!LLUUID::parseUUID(std::string(uuid_string), &uuid_value)) - { - break; - } - value_string = &value_string[(UUID_STR_LENGTH-1)]; - array[i] = uuid_value; - } + llassert(array); + + // Check type + if (mType != TYPE_UUID && mType != TYPE_UNKNOWN) + { + return 0; + } + + const char *value_string = mValue.c_str(); + + U32 i; + for (i=0; i<expected_length; ++i) + { + LLUUID uuid_value; + value_string = skipWhitespace(value_string); + + if (strlen(value_string) < (UUID_STR_LENGTH-1)) /* Flawfinder: ignore */ + { + break; + } + char uuid_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */ + memcpy(uuid_string, value_string, (UUID_STR_LENGTH-1)); /* Flawfinder: ignore */ + uuid_string[(UUID_STR_LENGTH-1)] = 0; + + if (!LLUUID::parseUUID(std::string(uuid_string), &uuid_value)) + { + break; + } + value_string = &value_string[(UUID_STR_LENGTH-1)]; + array[i] = uuid_value; + } #if LL_DEBUG - if (i != expected_length) - { - LL_DEBUGS() << "LLXMLNode::getUUIDValue() failed for node named '" - << mName->mString << "' -- expected " << expected_length << " but " - << "only found " << i << LL_ENDL; - } + if (i != expected_length) + { + LL_DEBUGS() << "LLXMLNode::getUUIDValue() failed for node named '" + << mName->mString << "' -- expected " << expected_length << " but " + << "only found " << i << LL_ENDL; + } #endif - return i; + return i; } U32 LLXMLNode::getNodeRefValue(U32 expected_length, LLXMLNode **array) { - llassert(array); - - // Check type - if (mType != TYPE_NODEREF && mType != TYPE_UNKNOWN) - { - return 0; - } + llassert(array); - std::string *string_array = new std::string[expected_length]; + // Check type + if (mType != TYPE_NODEREF && mType != TYPE_UNKNOWN) + { + return 0; + } - U32 num_strings = getStringValue(expected_length, string_array); + std::string *string_array = new std::string[expected_length]; - U32 num_returned_refs = 0; + U32 num_strings = getStringValue(expected_length, string_array); - LLXMLNodePtr root = getRoot(); - for (U32 strnum=0; strnum<num_strings; ++strnum) - { - LLXMLNodeList node_list; - root->findID(string_array[strnum], node_list); - if (node_list.empty()) - { - LL_WARNS() << "XML: Could not find node ID: " << string_array[strnum] << LL_ENDL; - } - else if (node_list.size() > 1) - { - LL_WARNS() << "XML: Node ID not unique: " << string_array[strnum] << LL_ENDL; - } - else - { - LLXMLNodeList::const_iterator list_itr = node_list.begin(); - if (list_itr != node_list.end()) - { - LLXMLNode* child = (*list_itr).second; + U32 num_returned_refs = 0; - array[num_returned_refs++] = child; - } - } - } + LLXMLNodePtr root = getRoot(); + for (U32 strnum=0; strnum<num_strings; ++strnum) + { + LLXMLNodeList node_list; + root->findID(string_array[strnum], node_list); + if (node_list.empty()) + { + LL_WARNS() << "XML: Could not find node ID: " << string_array[strnum] << LL_ENDL; + } + else if (node_list.size() > 1) + { + LL_WARNS() << "XML: Node ID not unique: " << string_array[strnum] << LL_ENDL; + } + else + { + LLXMLNodeList::const_iterator list_itr = node_list.begin(); + if (list_itr != node_list.end()) + { + LLXMLNode* child = (*list_itr).second; + + array[num_returned_refs++] = child; + } + } + } - delete[] string_array; + delete[] string_array; - return num_returned_refs; + return num_returned_refs; } void LLXMLNode::setBoolValue(U32 length, const BOOL *array) { - if (length == 0) return; + if (length == 0) return; - std::string new_value; - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value = llformat("%s %s", new_value.c_str(), array[pos]?"true":"false"); - } - else - { - new_value = array[pos]?"true":"false"; - } - } + std::string new_value; + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value = llformat("%s %s", new_value.c_str(), array[pos]?"true":"false"); + } + else + { + new_value = array[pos]?"true":"false"; + } + } - mValue = new_value; - mEncoding = ENCODING_DEFAULT; - mLength = length; - mType = TYPE_BOOLEAN; + mValue = new_value; + mEncoding = ENCODING_DEFAULT; + mLength = length; + mType = TYPE_BOOLEAN; } void LLXMLNode::setByteValue(U32 length, const U8* const array, Encoding encoding) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(llformat(" %u", array[pos])); - } - else - { - new_value = llformat("%u", array[pos]); - } - } - } - if (encoding == ENCODING_HEX) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0 && pos % 16 == 0) - { - new_value.append(llformat(" %02X", array[pos])); - } - else - { - new_value.append(llformat("%02X", array[pos])); - } - } - } - // TODO -- Handle Base32 - - mValue = new_value; - mEncoding = encoding; - mLength = length; - mType = TYPE_INTEGER; - mPrecision = 8; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(llformat(" %u", array[pos])); + } + else + { + new_value = llformat("%u", array[pos]); + } + } + } + if (encoding == ENCODING_HEX) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0 && pos % 16 == 0) + { + new_value.append(llformat(" %02X", array[pos])); + } + else + { + new_value.append(llformat("%02X", array[pos])); + } + } + } + // TODO -- Handle Base32 + + mValue = new_value; + mEncoding = encoding; + mLength = length; + mType = TYPE_INTEGER; + mPrecision = 8; } void LLXMLNode::setIntValue(U32 length, const S32 *array, Encoding encoding) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(llformat(" %d", array[pos])); - } - else - { - new_value = llformat("%d", array[pos]); - } - } - mValue = new_value; - } - else if (encoding == ENCODING_HEX) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0 && pos % 16 == 0) - { - new_value.append(llformat(" %08X", ((U32 *)array)[pos])); - } - else - { - new_value.append(llformat("%08X", ((U32 *)array)[pos])); - } - } - mValue = new_value; - } - else - { - mValue = new_value; - } - // TODO -- Handle Base32 - - mEncoding = encoding; - mLength = length; - mType = TYPE_INTEGER; - mPrecision = 32; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(llformat(" %d", array[pos])); + } + else + { + new_value = llformat("%d", array[pos]); + } + } + mValue = new_value; + } + else if (encoding == ENCODING_HEX) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0 && pos % 16 == 0) + { + new_value.append(llformat(" %08X", ((U32 *)array)[pos])); + } + else + { + new_value.append(llformat("%08X", ((U32 *)array)[pos])); + } + } + mValue = new_value; + } + else + { + mValue = new_value; + } + // TODO -- Handle Base32 + + mEncoding = encoding; + mLength = length; + mType = TYPE_INTEGER; + mPrecision = 32; } void LLXMLNode::setUnsignedValue(U32 length, const U32* array, Encoding encoding) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(llformat(" %u", array[pos])); - } - else - { - new_value = llformat("%u", array[pos]); - } - } - } - if (encoding == ENCODING_HEX) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0 && pos % 16 == 0) - { - new_value.append(llformat(" %08X", array[pos])); - } - else - { - new_value.append(llformat("%08X", array[pos])); - } - } - mValue = new_value; - } - // TODO -- Handle Base32 - - mValue = new_value; - mEncoding = encoding; - mLength = length; - mType = TYPE_INTEGER; - mPrecision = 32; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(llformat(" %u", array[pos])); + } + else + { + new_value = llformat("%u", array[pos]); + } + } + } + if (encoding == ENCODING_HEX) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0 && pos % 16 == 0) + { + new_value.append(llformat(" %08X", array[pos])); + } + else + { + new_value.append(llformat("%08X", array[pos])); + } + } + mValue = new_value; + } + // TODO -- Handle Base32 + + mValue = new_value; + mEncoding = encoding; + mLength = length; + mType = TYPE_INTEGER; + mPrecision = 32; } #if LL_WINDOWS @@ -2349,937 +2349,937 @@ void LLXMLNode::setUnsignedValue(U32 length, const U32* array, Encoding encoding void LLXMLNode::setLongValue(U32 length, const U64* array, Encoding encoding) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(llformat(" %" PU64, array[pos])); - } - else - { - new_value = llformat("%" PU64, array[pos]); - } - } - mValue = new_value; - } - if (encoding == ENCODING_HEX) - { - for (U32 pos=0; pos<length; ++pos) - { - U32 upper_32 = U32(array[pos]>>32); - U32 lower_32 = U32(array[pos]&0xffffffff); - if (pos > 0 && pos % 8 == 0) - { - new_value.append(llformat(" %08X%08X", upper_32, lower_32)); - } - else - { - new_value.append(llformat("%08X%08X", upper_32, lower_32)); - } - } - mValue = new_value; - } - else - { - mValue = new_value; - } - // TODO -- Handle Base32 - - mEncoding = encoding; - mLength = length; - mType = TYPE_INTEGER; - mPrecision = 64; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(llformat(" %" PU64, array[pos])); + } + else + { + new_value = llformat("%" PU64, array[pos]); + } + } + mValue = new_value; + } + if (encoding == ENCODING_HEX) + { + for (U32 pos=0; pos<length; ++pos) + { + U32 upper_32 = U32(array[pos]>>32); + U32 lower_32 = U32(array[pos]&0xffffffff); + if (pos > 0 && pos % 8 == 0) + { + new_value.append(llformat(" %08X%08X", upper_32, lower_32)); + } + else + { + new_value.append(llformat("%08X%08X", upper_32, lower_32)); + } + } + mValue = new_value; + } + else + { + mValue = new_value; + } + // TODO -- Handle Base32 + + mEncoding = encoding; + mLength = length; + mType = TYPE_INTEGER; + mPrecision = 64; } void LLXMLNode::setFloatValue(U32 length, const F32 *array, Encoding encoding, U32 precision) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - std::string format_string; - if (precision > 0) - { - if (precision > 25) - { - precision = 25; - } - format_string = llformat( "%%.%dg", precision); - } - else - { - format_string = llformat( "%%g"); - } - - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(" "); - new_value.append(llformat(format_string.c_str(), array[pos])); - } - else - { - new_value.assign(llformat(format_string.c_str(), array[pos])); - } - } - mValue = new_value; - } - else if (encoding == ENCODING_HEX) - { - U32 *byte_array = (U32 *)array; - setUnsignedValue(length, byte_array, ENCODING_HEX); - } - else - { - mValue = new_value; - } - - mEncoding = encoding; - mLength = length; - mType = TYPE_FLOAT; - mPrecision = 32; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + std::string format_string; + if (precision > 0) + { + if (precision > 25) + { + precision = 25; + } + format_string = llformat( "%%.%dg", precision); + } + else + { + format_string = llformat( "%%g"); + } + + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(" "); + new_value.append(llformat(format_string.c_str(), array[pos])); + } + else + { + new_value.assign(llformat(format_string.c_str(), array[pos])); + } + } + mValue = new_value; + } + else if (encoding == ENCODING_HEX) + { + U32 *byte_array = (U32 *)array; + setUnsignedValue(length, byte_array, ENCODING_HEX); + } + else + { + mValue = new_value; + } + + mEncoding = encoding; + mLength = length; + mType = TYPE_FLOAT; + mPrecision = 32; } void LLXMLNode::setDoubleValue(U32 length, const F64 *array, Encoding encoding, U32 precision) { - if (length == 0) return; - - std::string new_value; - if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) - { - std::string format_string; - if (precision > 0) - { - if (precision > 25) - { - precision = 25; - } - format_string = llformat( "%%.%dg", precision); - } - else - { - format_string = llformat( "%%g"); - } - for (U32 pos=0; pos<length; ++pos) - { - if (pos > 0) - { - new_value.append(" "); - new_value.append(llformat(format_string.c_str(), array[pos])); - } - else - { - new_value.assign(llformat(format_string.c_str(), array[pos])); - } - } - mValue = new_value; - } - if (encoding == ENCODING_HEX) - { - U64 *byte_array = (U64 *)array; - setLongValue(length, byte_array, ENCODING_HEX); - } - else - { - mValue = new_value; - } - // TODO -- Handle Base32 - - mEncoding = encoding; - mLength = length; - mType = TYPE_FLOAT; - mPrecision = 64; + if (length == 0) return; + + std::string new_value; + if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL) + { + std::string format_string; + if (precision > 0) + { + if (precision > 25) + { + precision = 25; + } + format_string = llformat( "%%.%dg", precision); + } + else + { + format_string = llformat( "%%g"); + } + for (U32 pos=0; pos<length; ++pos) + { + if (pos > 0) + { + new_value.append(" "); + new_value.append(llformat(format_string.c_str(), array[pos])); + } + else + { + new_value.assign(llformat(format_string.c_str(), array[pos])); + } + } + mValue = new_value; + } + if (encoding == ENCODING_HEX) + { + U64 *byte_array = (U64 *)array; + setLongValue(length, byte_array, ENCODING_HEX); + } + else + { + mValue = new_value; + } + // TODO -- Handle Base32 + + mEncoding = encoding; + mLength = length; + mType = TYPE_FLOAT; + mPrecision = 64; } // static std::string LLXMLNode::escapeXML(const std::string& xml) { - std::string out; - for (std::string::size_type i = 0; i < xml.size(); ++i) - { - char c = xml[i]; - switch(c) - { - case '"': out.append("""); break; - case '\'': out.append("'"); break; - case '&': out.append("&"); break; - case '<': out.append("<"); break; - case '>': out.append(">"); break; - default: out.push_back(c); break; - } - } - return out; + std::string out; + for (std::string::size_type i = 0; i < xml.size(); ++i) + { + char c = xml[i]; + switch(c) + { + case '"': out.append("""); break; + case '\'': out.append("'"); break; + case '&': out.append("&"); break; + case '<': out.append("<"); break; + case '>': out.append(">"); break; + default: out.push_back(c); break; + } + } + return out; } void LLXMLNode::setStringValue(U32 length, const std::string *strings) { - if (length == 0) return; + if (length == 0) return; - std::string new_value; - for (U32 pos=0; pos<length; ++pos) - { - // *NOTE: Do not escape strings here - do it on output - new_value.append( strings[pos] ); - if (pos < length-1) new_value.append(" "); - } + std::string new_value; + for (U32 pos=0; pos<length; ++pos) + { + // *NOTE: Do not escape strings here - do it on output + new_value.append( strings[pos] ); + if (pos < length-1) new_value.append(" "); + } - mValue = new_value; - mEncoding = ENCODING_DEFAULT; - mLength = length; - mType = TYPE_STRING; + mValue = new_value; + mEncoding = ENCODING_DEFAULT; + mLength = length; + mType = TYPE_STRING; } void LLXMLNode::setUUIDValue(U32 length, const LLUUID *array) { - if (length == 0) return; + if (length == 0) return; - std::string new_value; - for (U32 pos=0; pos<length; ++pos) - { - new_value.append(array[pos].asString()); - if (pos < length-1) new_value.append(" "); - } + std::string new_value; + for (U32 pos=0; pos<length; ++pos) + { + new_value.append(array[pos].asString()); + if (pos < length-1) new_value.append(" "); + } - mValue = new_value; - mEncoding = ENCODING_DEFAULT; - mLength = length; - mType = TYPE_UUID; + mValue = new_value; + mEncoding = ENCODING_DEFAULT; + mLength = length; + mType = TYPE_UUID; } void LLXMLNode::setNodeRefValue(U32 length, const LLXMLNode **array) { - if (length == 0) return; + if (length == 0) return; - std::string new_value; - for (U32 pos=0; pos<length; ++pos) - { - if (array[pos]->mID != "") - { - new_value.append(array[pos]->mID); - } - else - { - new_value.append("(null)"); - } - if (pos < length-1) new_value.append(" "); - } + std::string new_value; + for (U32 pos=0; pos<length; ++pos) + { + if (array[pos]->mID != "") + { + new_value.append(array[pos]->mID); + } + else + { + new_value.append("(null)"); + } + if (pos < length-1) new_value.append(" "); + } - mValue = new_value; - mEncoding = ENCODING_DEFAULT; - mLength = length; - mType = TYPE_NODEREF; + mValue = new_value; + mEncoding = ENCODING_DEFAULT; + mLength = length; + mType = TYPE_NODEREF; } void LLXMLNode::setValue(const std::string& value) { - if (TYPE_CONTAINER == mType) - { - mType = TYPE_UNKNOWN; - } - mValue = value; + if (TYPE_CONTAINER == mType) + { + mType = TYPE_UNKNOWN; + } + mValue = value; } void LLXMLNode::setDefault(LLXMLNode *default_node) { - mDefault = default_node; + mDefault = default_node; } void LLXMLNode::findDefault(LLXMLNode *defaults_list) { - if (defaults_list) - { - LLXMLNodeList children; - defaults_list->getChildren(mName->mString, children); - - LLXMLNodeList::const_iterator children_itr; - LLXMLNodeList::const_iterator children_end = children.end(); - for (children_itr = children.begin(); children_itr != children_end; ++children_itr) - { - LLXMLNode* child = (*children_itr).second; - if (child->mVersionMajor == mVersionMajor && - child->mVersionMinor == mVersionMinor) - { - mDefault = child; - return; - } - } - } - mDefault = NULL; + if (defaults_list) + { + LLXMLNodeList children; + defaults_list->getChildren(mName->mString, children); + + LLXMLNodeList::const_iterator children_itr; + LLXMLNodeList::const_iterator children_end = children.end(); + for (children_itr = children.begin(); children_itr != children_end; ++children_itr) + { + LLXMLNode* child = (*children_itr).second; + if (child->mVersionMajor == mVersionMajor && + child->mVersionMinor == mVersionMinor) + { + mDefault = child; + return; + } + } + } + mDefault = NULL; } BOOL LLXMLNode::deleteChildren(const std::string& name) { - U32 removed_count = 0; - LLXMLNodeList node_list; - findName(name, node_list); - if (!node_list.empty()) - { - // TODO -- use multimap::find() - // TODO -- need to watch out for invalid iterators - LLXMLNodeList::iterator children_itr; - for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr) - { - LLXMLNode* child = (*children_itr).second; - if (deleteChild(child)) - { - removed_count++; - } - } - } - return removed_count > 0 ? TRUE : FALSE; + U32 removed_count = 0; + LLXMLNodeList node_list; + findName(name, node_list); + if (!node_list.empty()) + { + // TODO -- use multimap::find() + // TODO -- need to watch out for invalid iterators + LLXMLNodeList::iterator children_itr; + for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr) + { + LLXMLNode* child = (*children_itr).second; + if (deleteChild(child)) + { + removed_count++; + } + } + } + return removed_count > 0 ? TRUE : FALSE; } BOOL LLXMLNode::deleteChildren(LLStringTableEntry* name) { - U32 removed_count = 0; - LLXMLNodeList node_list; - findName(name, node_list); - if (!node_list.empty()) - { - // TODO -- use multimap::find() - // TODO -- need to watch out for invalid iterators - LLXMLNodeList::iterator children_itr; - for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr) - { - LLXMLNode* child = (*children_itr).second; - if (deleteChild(child)) - { - removed_count++; - } - } - } - return removed_count > 0 ? TRUE : FALSE; + U32 removed_count = 0; + LLXMLNodeList node_list; + findName(name, node_list); + if (!node_list.empty()) + { + // TODO -- use multimap::find() + // TODO -- need to watch out for invalid iterators + LLXMLNodeList::iterator children_itr; + for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr) + { + LLXMLNode* child = (*children_itr).second; + if (deleteChild(child)) + { + removed_count++; + } + } + } + return removed_count > 0 ? TRUE : FALSE; } void LLXMLNode::setAttributes(LLXMLNode::ValueType type, U32 precision, LLXMLNode::Encoding encoding, U32 length) { - mType = type; - mEncoding = encoding; - mPrecision = precision; - mLength = length; + mType = type; + mEncoding = encoding; + mPrecision = precision; + mLength = length; } void LLXMLNode::setName(const std::string& name) { - setName(gStringTable.addStringEntry(name)); + setName(gStringTable.addStringEntry(name)); } void LLXMLNode::setName(LLStringTableEntry* name) { - LLXMLNode* old_parent = mParent; - if (mParent) - { - // we need to remove and re-add to the parent so that - // the multimap key agrees with this node's name - mParent->removeChild(this); - } - mName = name; - if (old_parent) - { - LLXMLNodePtr this_ptr(this); - old_parent->addChild(this_ptr); - } + LLXMLNode* old_parent = mParent; + if (mParent) + { + // we need to remove and re-add to the parent so that + // the multimap key agrees with this node's name + mParent->removeChild(this); + } + mName = name; + if (old_parent) + { + LLXMLNodePtr this_ptr(this); + old_parent->addChild(this_ptr); + } } // Unused // void LLXMLNode::appendValue(const std::string& value) // { -// mValue.append(value); +// mValue.append(value); // } -U32 LLXMLNode::getChildCount() const -{ - if (mChildren.notNull()) - { - return mChildren->map.size(); - } - return 0; +U32 LLXMLNode::getChildCount() const +{ + if (mChildren.notNull()) + { + return mChildren->map.size(); + } + return 0; } //*************************************************** -// UNIT TESTING +// UNIT TESTING //*************************************************** U32 get_rand(U32 max_value) { - U32 random_num = rand() + ((U32)rand() << 16); - return (random_num % max_value); + U32 random_num = rand() + ((U32)rand() << 16); + return (random_num % max_value); } LLXMLNode *get_rand_node(LLXMLNode *node) { - if (node->mChildren.notNull()) - { - U32 num_children = node->mChildren->map.size(); - if (get_rand(2) == 0) - { - while (true) - { - S32 child_num = S32(get_rand(num_children*2)) - num_children; - LLXMLChildList::iterator itor = node->mChildren->map.begin(); - while (child_num > 0) - { - --child_num; - ++itor; - } - if (!itor->second->mIsAttribute) - { - return get_rand_node(itor->second); - } - } - } - } - return node; + if (node->mChildren.notNull()) + { + U32 num_children = node->mChildren->map.size(); + if (get_rand(2) == 0) + { + while (true) + { + S32 child_num = S32(get_rand(num_children*2)) - num_children; + LLXMLChildList::iterator itor = node->mChildren->map.begin(); + while (child_num > 0) + { + --child_num; + ++itor; + } + if (!itor->second->mIsAttribute) + { + return get_rand_node(itor->second); + } + } + } + } + return node; } void LLXMLNode::createUnitTest(S32 max_num_children) { - // Random ID - std::string rand_id; - U32 rand_id_len = get_rand(10)+5; - for (U32 pos = 0; pos<rand_id_len; ++pos) - { - char c = 'a' + get_rand(26); - rand_id.append(1, c); - } - mID = rand_id; - - if (max_num_children < 2) - { - setStringValue(1, &mID); - return; - } - - // Checksums - U32 integer_checksum = 0; - U64 long_checksum = 0; - U32 bool_true_count = 0; - LLUUID uuid_checksum; - U32 noderef_checksum = 0; - U32 float_checksum = 0; - - // Create a random number of children - U32 num_children = get_rand(max_num_children)+1; - for (U32 child_num=0; child_num<num_children; ++child_num) - { - // Random Name - std::string child_name; - U32 child_name_len = get_rand(10)+5; - for (U32 pos = 0; pos<child_name_len; ++pos) - { - char c = 'a' + get_rand(26); - child_name.append(1, c); - } - - LLXMLNode *new_child = createChild(child_name.c_str(), FALSE); - - // Random ID - std::string child_id; - U32 child_id_len = get_rand(10)+5; - for (U32 pos=0; pos<child_id_len; ++pos) - { - char c = 'a' + get_rand(26); - child_id.append(1, c); - } - new_child->mID = child_id; - - // Random Length - U32 array_size = get_rand(28)+1; - - // Random Encoding - Encoding new_encoding = get_rand(2)?ENCODING_DECIMAL:ENCODING_HEX; - - // Random Type - int type = get_rand(8); - switch (type) - { - case 0: // TYPE_CONTAINER - new_child->createUnitTest(max_num_children/2); - break; - case 1: // TYPE_BOOLEAN - { - BOOL random_bool_values[30]; - for (U32 value=0; value<array_size; ++value) - { - random_bool_values[value] = get_rand(2); - if (random_bool_values[value]) - { - ++bool_true_count; - } - } - new_child->setBoolValue(array_size, random_bool_values); - } - break; - case 2: // TYPE_INTEGER (32-bit) - { - U32 random_int_values[30]; - for (U32 value=0; value<array_size; ++value) - { - random_int_values[value] = get_rand(0xffffffff); - integer_checksum ^= random_int_values[value]; - } - new_child->setUnsignedValue(array_size, random_int_values, new_encoding); - } - break; - case 3: // TYPE_INTEGER (64-bit) - { - U64 random_int_values[30]; - for (U64 value=0; value<array_size; ++value) - { - random_int_values[value] = (U64(get_rand(0xffffffff)) << 32) + get_rand(0xffffffff); - long_checksum ^= random_int_values[value]; - } - new_child->setLongValue(array_size, random_int_values, new_encoding); - } - break; - case 4: // TYPE_FLOAT (32-bit) - { - F32 random_float_values[30]; - for (U32 value=0; value<array_size; ++value) - { - S32 exponent = get_rand(256) - 128; - S32 fractional_part = get_rand(0xffffffff); - S32 sign = get_rand(2) * 2 - 1; - random_float_values[value] = F32(fractional_part) / F32(0xffffffff) * exp(F32(exponent)) * F32(sign); - - U32 *float_bits = &((U32 *)random_float_values)[value]; - if (*float_bits == 0x80000000) - { - *float_bits = 0x00000000; - } - float_checksum ^= (*float_bits & 0xfffff000); - } - new_child->setFloatValue(array_size, random_float_values, new_encoding, 12); - } - break; - case 5: // TYPE_FLOAT (64-bit) - { - F64 random_float_values[30]; - for (U32 value=0; value<array_size; ++value) - { - S32 exponent = get_rand(2048) - 1024; - S32 fractional_part = get_rand(0xffffffff); - S32 sign = get_rand(2) * 2 - 1; - random_float_values[value] = F64(fractional_part) / F64(0xffffffff) * exp(F64(exponent)) * F64(sign); - - U64 *float_bits = &((U64 *)random_float_values)[value]; - if (*float_bits == 0x8000000000000000ll) - { - *float_bits = 0x0000000000000000ll; - } - float_checksum ^= ((*float_bits & 0xfffffff000000000ll) >> 32); - } - new_child->setDoubleValue(array_size, random_float_values, new_encoding, 12); - } - break; - case 6: // TYPE_UUID - { - LLUUID random_uuid_values[30]; - for (U32 value=0; value<array_size; ++value) - { - random_uuid_values[value].generate(); - for (S32 byte=0; byte<UUID_BYTES; ++byte) - { - uuid_checksum.mData[byte] ^= random_uuid_values[value].mData[byte]; - } - } - new_child->setUUIDValue(array_size, random_uuid_values); - } - break; - case 7: // TYPE_NODEREF - { - LLXMLNode *random_node_array[30]; - LLXMLNode *root = getRoot(); - for (U32 value=0; value<array_size; ++value) - { - random_node_array[value] = get_rand_node(root); - const char *node_name = random_node_array[value]->mName->mString; - for (U32 pos=0; pos<strlen(node_name); ++pos) /* Flawfinder: ignore */ - { - U32 hash_contrib = U32(node_name[pos]) << ((pos % 4) * 8); - noderef_checksum ^= hash_contrib; - } - } - new_child->setNodeRefValue(array_size, (const LLXMLNode **)random_node_array); - } - break; - } - } - - createChild("integer_checksum", TRUE)->setUnsignedValue(1, &integer_checksum, LLXMLNode::ENCODING_HEX); - createChild("long_checksum", TRUE)->setLongValue(1, &long_checksum, LLXMLNode::ENCODING_HEX); - createChild("bool_true_count", TRUE)->setUnsignedValue(1, &bool_true_count, LLXMLNode::ENCODING_HEX); - createChild("uuid_checksum", TRUE)->setUUIDValue(1, &uuid_checksum); - createChild("noderef_checksum", TRUE)->setUnsignedValue(1, &noderef_checksum, LLXMLNode::ENCODING_HEX); - createChild("float_checksum", TRUE)->setUnsignedValue(1, &float_checksum, LLXMLNode::ENCODING_HEX); + // Random ID + std::string rand_id; + U32 rand_id_len = get_rand(10)+5; + for (U32 pos = 0; pos<rand_id_len; ++pos) + { + char c = 'a' + get_rand(26); + rand_id.append(1, c); + } + mID = rand_id; + + if (max_num_children < 2) + { + setStringValue(1, &mID); + return; + } + + // Checksums + U32 integer_checksum = 0; + U64 long_checksum = 0; + U32 bool_true_count = 0; + LLUUID uuid_checksum; + U32 noderef_checksum = 0; + U32 float_checksum = 0; + + // Create a random number of children + U32 num_children = get_rand(max_num_children)+1; + for (U32 child_num=0; child_num<num_children; ++child_num) + { + // Random Name + std::string child_name; + U32 child_name_len = get_rand(10)+5; + for (U32 pos = 0; pos<child_name_len; ++pos) + { + char c = 'a' + get_rand(26); + child_name.append(1, c); + } + + LLXMLNode *new_child = createChild(child_name.c_str(), FALSE); + + // Random ID + std::string child_id; + U32 child_id_len = get_rand(10)+5; + for (U32 pos=0; pos<child_id_len; ++pos) + { + char c = 'a' + get_rand(26); + child_id.append(1, c); + } + new_child->mID = child_id; + + // Random Length + U32 array_size = get_rand(28)+1; + + // Random Encoding + Encoding new_encoding = get_rand(2)?ENCODING_DECIMAL:ENCODING_HEX; + + // Random Type + int type = get_rand(8); + switch (type) + { + case 0: // TYPE_CONTAINER + new_child->createUnitTest(max_num_children/2); + break; + case 1: // TYPE_BOOLEAN + { + BOOL random_bool_values[30]; + for (U32 value=0; value<array_size; ++value) + { + random_bool_values[value] = get_rand(2); + if (random_bool_values[value]) + { + ++bool_true_count; + } + } + new_child->setBoolValue(array_size, random_bool_values); + } + break; + case 2: // TYPE_INTEGER (32-bit) + { + U32 random_int_values[30]; + for (U32 value=0; value<array_size; ++value) + { + random_int_values[value] = get_rand(0xffffffff); + integer_checksum ^= random_int_values[value]; + } + new_child->setUnsignedValue(array_size, random_int_values, new_encoding); + } + break; + case 3: // TYPE_INTEGER (64-bit) + { + U64 random_int_values[30]; + for (U64 value=0; value<array_size; ++value) + { + random_int_values[value] = (U64(get_rand(0xffffffff)) << 32) + get_rand(0xffffffff); + long_checksum ^= random_int_values[value]; + } + new_child->setLongValue(array_size, random_int_values, new_encoding); + } + break; + case 4: // TYPE_FLOAT (32-bit) + { + F32 random_float_values[30]; + for (U32 value=0; value<array_size; ++value) + { + S32 exponent = get_rand(256) - 128; + S32 fractional_part = get_rand(0xffffffff); + S32 sign = get_rand(2) * 2 - 1; + random_float_values[value] = F32(fractional_part) / F32(0xffffffff) * exp(F32(exponent)) * F32(sign); + + U32 *float_bits = &((U32 *)random_float_values)[value]; + if (*float_bits == 0x80000000) + { + *float_bits = 0x00000000; + } + float_checksum ^= (*float_bits & 0xfffff000); + } + new_child->setFloatValue(array_size, random_float_values, new_encoding, 12); + } + break; + case 5: // TYPE_FLOAT (64-bit) + { + F64 random_float_values[30]; + for (U32 value=0; value<array_size; ++value) + { + S32 exponent = get_rand(2048) - 1024; + S32 fractional_part = get_rand(0xffffffff); + S32 sign = get_rand(2) * 2 - 1; + random_float_values[value] = F64(fractional_part) / F64(0xffffffff) * exp(F64(exponent)) * F64(sign); + + U64 *float_bits = &((U64 *)random_float_values)[value]; + if (*float_bits == 0x8000000000000000ll) + { + *float_bits = 0x0000000000000000ll; + } + float_checksum ^= ((*float_bits & 0xfffffff000000000ll) >> 32); + } + new_child->setDoubleValue(array_size, random_float_values, new_encoding, 12); + } + break; + case 6: // TYPE_UUID + { + LLUUID random_uuid_values[30]; + for (U32 value=0; value<array_size; ++value) + { + random_uuid_values[value].generate(); + for (S32 byte=0; byte<UUID_BYTES; ++byte) + { + uuid_checksum.mData[byte] ^= random_uuid_values[value].mData[byte]; + } + } + new_child->setUUIDValue(array_size, random_uuid_values); + } + break; + case 7: // TYPE_NODEREF + { + LLXMLNode *random_node_array[30]; + LLXMLNode *root = getRoot(); + for (U32 value=0; value<array_size; ++value) + { + random_node_array[value] = get_rand_node(root); + const char *node_name = random_node_array[value]->mName->mString; + for (U32 pos=0; pos<strlen(node_name); ++pos) /* Flawfinder: ignore */ + { + U32 hash_contrib = U32(node_name[pos]) << ((pos % 4) * 8); + noderef_checksum ^= hash_contrib; + } + } + new_child->setNodeRefValue(array_size, (const LLXMLNode **)random_node_array); + } + break; + } + } + + createChild("integer_checksum", TRUE)->setUnsignedValue(1, &integer_checksum, LLXMLNode::ENCODING_HEX); + createChild("long_checksum", TRUE)->setLongValue(1, &long_checksum, LLXMLNode::ENCODING_HEX); + createChild("bool_true_count", TRUE)->setUnsignedValue(1, &bool_true_count, LLXMLNode::ENCODING_HEX); + createChild("uuid_checksum", TRUE)->setUUIDValue(1, &uuid_checksum); + createChild("noderef_checksum", TRUE)->setUnsignedValue(1, &noderef_checksum, LLXMLNode::ENCODING_HEX); + createChild("float_checksum", TRUE)->setUnsignedValue(1, &float_checksum, LLXMLNode::ENCODING_HEX); } BOOL LLXMLNode::performUnitTest(std::string &error_buffer) { - if (mChildren.isNull()) - { - error_buffer.append(llformat("ERROR Node %s: No children found.\n", mName->mString)); - return FALSE; - } - - // Checksums - U32 integer_checksum = 0; - U32 bool_true_count = 0; - LLUUID uuid_checksum; - U32 noderef_checksum = 0; - U32 float_checksum = 0; - U64 long_checksum = 0; - - LLXMLChildList::iterator itor; - for (itor=mChildren->map.begin(); itor!=mChildren->map.end(); ++itor) - { - LLXMLNode *node = itor->second; - if (node->mIsAttribute) - { - continue; - } - if (node->mType == TYPE_CONTAINER) - { - if (!node->performUnitTest(error_buffer)) - { - error_buffer.append(llformat("Child test failed for %s.\n", mName->mString)); - //return FALSE; - } - continue; - } - if (node->mLength < 1 || node->mLength > 30) - { - error_buffer.append(llformat("ERROR Node %s: Invalid array length %d, child %s.\n", mName->mString, node->mLength, node->mName->mString)); - return FALSE; - } - switch (node->mType) - { - case TYPE_CONTAINER: - case TYPE_UNKNOWN: - break; - case TYPE_BOOLEAN: - { - BOOL bool_array[30]; - if (node->getBoolValue(node->mLength, bool_array) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read boolean array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - if (bool_array[pos]) - { - ++bool_true_count; - } - } - } - break; - case TYPE_INTEGER: - { - if (node->mPrecision == 32) - { - U32 integer_array[30]; - if (node->getUnsignedValue(node->mLength, integer_array, node->mEncoding) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read integer array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - integer_checksum ^= integer_array[pos]; - } - } - else - { - U64 integer_array[30]; - if (node->getLongValue(node->mLength, integer_array, node->mEncoding) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read long integer array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - long_checksum ^= integer_array[pos]; - } - } - } - break; - case TYPE_FLOAT: - { - if (node->mPrecision == 32) - { - F32 float_array[30]; - if (node->getFloatValue(node->mLength, float_array, node->mEncoding) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - U32 float_bits = ((U32 *)float_array)[pos]; - float_checksum ^= (float_bits & 0xfffff000); - } - } - else - { - F64 float_array[30]; - if (node->getDoubleValue(node->mLength, float_array, node->mEncoding) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - U64 float_bits = ((U64 *)float_array)[pos]; - float_checksum ^= ((float_bits & 0xfffffff000000000ll) >> 32); - } - } - } - break; - case TYPE_STRING: - break; - case TYPE_UUID: - { - LLUUID uuid_array[30]; - if (node->getUUIDValue(node->mLength, uuid_array) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read uuid array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<(U32)node->mLength; ++pos) - { - for (S32 byte=0; byte<UUID_BYTES; ++byte) - { - uuid_checksum.mData[byte] ^= uuid_array[pos].mData[byte]; - } - } - } - break; - case TYPE_NODEREF: - { - LLXMLNode *node_array[30]; - if (node->getNodeRefValue(node->mLength, node_array) < node->mLength) - { - error_buffer.append(llformat("ERROR Node %s: Could not read node ref array, child %s.\n", mName->mString, node->mName->mString)); - return FALSE; - } - for (U32 pos=0; pos<node->mLength; ++pos) - { - const char *node_name = node_array[pos]->mName->mString; - for (U32 pos2=0; pos2<strlen(node_name); ++pos2) /* Flawfinder: ignore */ - { - U32 hash_contrib = U32(node_name[pos2]) << ((pos2 % 4) * 8); - noderef_checksum ^= hash_contrib; - } - } - } - break; - } - } - - LLXMLNodePtr checksum_node; - - // Compare checksums - { - U32 node_integer_checksum = 0; - if (!getAttribute("integer_checksum", checksum_node, FALSE) || - checksum_node->getUnsignedValue(1, &node_integer_checksum, ENCODING_HEX) != 1) - { - error_buffer.append(llformat("ERROR Node %s: Integer checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_integer_checksum != integer_checksum) - { - error_buffer.append(llformat("ERROR Node %s: Integer checksum mismatch: read %X / calc %X.\n", mName->mString, node_integer_checksum, integer_checksum)); - return FALSE; - } - } - - { - U64 node_long_checksum = 0; - if (!getAttribute("long_checksum", checksum_node, FALSE) || - checksum_node->getLongValue(1, &node_long_checksum, ENCODING_HEX) != 1) - { - error_buffer.append(llformat("ERROR Node %s: Long Integer checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_long_checksum != long_checksum) - { - U32 *pp1 = (U32 *)&node_long_checksum; - U32 *pp2 = (U32 *)&long_checksum; - error_buffer.append(llformat("ERROR Node %s: Long Integer checksum mismatch: read %08X%08X / calc %08X%08X.\n", mName->mString, pp1[1], pp1[0], pp2[1], pp2[0])); - return FALSE; - } - } - - { - U32 node_bool_true_count = 0; - if (!getAttribute("bool_true_count", checksum_node, FALSE) || - checksum_node->getUnsignedValue(1, &node_bool_true_count, ENCODING_HEX) != 1) - { - error_buffer.append(llformat("ERROR Node %s: Boolean checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_bool_true_count != bool_true_count) - { - error_buffer.append(llformat("ERROR Node %s: Boolean checksum mismatch: read %X / calc %X.\n", mName->mString, node_bool_true_count, bool_true_count)); - return FALSE; - } - } - - { - LLUUID node_uuid_checksum; - if (!getAttribute("uuid_checksum", checksum_node, FALSE) || - checksum_node->getUUIDValue(1, &node_uuid_checksum) != 1) - { - error_buffer.append(llformat("ERROR Node %s: UUID checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_uuid_checksum != uuid_checksum) - { - error_buffer.append(llformat("ERROR Node %s: UUID checksum mismatch: read %s / calc %s.\n", mName->mString, node_uuid_checksum.asString().c_str(), uuid_checksum.asString().c_str())); - return FALSE; - } - } - - { - U32 node_noderef_checksum = 0; - if (!getAttribute("noderef_checksum", checksum_node, FALSE) || - checksum_node->getUnsignedValue(1, &node_noderef_checksum, ENCODING_HEX) != 1) - { - error_buffer.append(llformat("ERROR Node %s: Node Ref checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_noderef_checksum != noderef_checksum) - { - error_buffer.append(llformat("ERROR Node %s: Node Ref checksum mismatch: read %X / calc %X.\n", mName->mString, node_noderef_checksum, noderef_checksum)); - return FALSE; - } - } - - { - U32 node_float_checksum = 0; - if (!getAttribute("float_checksum", checksum_node, FALSE) || - checksum_node->getUnsignedValue(1, &node_float_checksum, ENCODING_HEX) != 1) - { - error_buffer.append(llformat("ERROR Node %s: Float checksum missing.\n", mName->mString)); - return FALSE; - } - if (node_float_checksum != float_checksum) - { - error_buffer.append(llformat("ERROR Node %s: Float checksum mismatch: read %X / calc %X.\n", mName->mString, node_float_checksum, float_checksum)); - return FALSE; - } - } - - return TRUE; + if (mChildren.isNull()) + { + error_buffer.append(llformat("ERROR Node %s: No children found.\n", mName->mString)); + return FALSE; + } + + // Checksums + U32 integer_checksum = 0; + U32 bool_true_count = 0; + LLUUID uuid_checksum; + U32 noderef_checksum = 0; + U32 float_checksum = 0; + U64 long_checksum = 0; + + LLXMLChildList::iterator itor; + for (itor=mChildren->map.begin(); itor!=mChildren->map.end(); ++itor) + { + LLXMLNode *node = itor->second; + if (node->mIsAttribute) + { + continue; + } + if (node->mType == TYPE_CONTAINER) + { + if (!node->performUnitTest(error_buffer)) + { + error_buffer.append(llformat("Child test failed for %s.\n", mName->mString)); + //return FALSE; + } + continue; + } + if (node->mLength < 1 || node->mLength > 30) + { + error_buffer.append(llformat("ERROR Node %s: Invalid array length %d, child %s.\n", mName->mString, node->mLength, node->mName->mString)); + return FALSE; + } + switch (node->mType) + { + case TYPE_CONTAINER: + case TYPE_UNKNOWN: + break; + case TYPE_BOOLEAN: + { + BOOL bool_array[30]; + if (node->getBoolValue(node->mLength, bool_array) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read boolean array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + if (bool_array[pos]) + { + ++bool_true_count; + } + } + } + break; + case TYPE_INTEGER: + { + if (node->mPrecision == 32) + { + U32 integer_array[30]; + if (node->getUnsignedValue(node->mLength, integer_array, node->mEncoding) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read integer array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + integer_checksum ^= integer_array[pos]; + } + } + else + { + U64 integer_array[30]; + if (node->getLongValue(node->mLength, integer_array, node->mEncoding) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read long integer array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + long_checksum ^= integer_array[pos]; + } + } + } + break; + case TYPE_FLOAT: + { + if (node->mPrecision == 32) + { + F32 float_array[30]; + if (node->getFloatValue(node->mLength, float_array, node->mEncoding) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + U32 float_bits = ((U32 *)float_array)[pos]; + float_checksum ^= (float_bits & 0xfffff000); + } + } + else + { + F64 float_array[30]; + if (node->getDoubleValue(node->mLength, float_array, node->mEncoding) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + U64 float_bits = ((U64 *)float_array)[pos]; + float_checksum ^= ((float_bits & 0xfffffff000000000ll) >> 32); + } + } + } + break; + case TYPE_STRING: + break; + case TYPE_UUID: + { + LLUUID uuid_array[30]; + if (node->getUUIDValue(node->mLength, uuid_array) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read uuid array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<(U32)node->mLength; ++pos) + { + for (S32 byte=0; byte<UUID_BYTES; ++byte) + { + uuid_checksum.mData[byte] ^= uuid_array[pos].mData[byte]; + } + } + } + break; + case TYPE_NODEREF: + { + LLXMLNode *node_array[30]; + if (node->getNodeRefValue(node->mLength, node_array) < node->mLength) + { + error_buffer.append(llformat("ERROR Node %s: Could not read node ref array, child %s.\n", mName->mString, node->mName->mString)); + return FALSE; + } + for (U32 pos=0; pos<node->mLength; ++pos) + { + const char *node_name = node_array[pos]->mName->mString; + for (U32 pos2=0; pos2<strlen(node_name); ++pos2) /* Flawfinder: ignore */ + { + U32 hash_contrib = U32(node_name[pos2]) << ((pos2 % 4) * 8); + noderef_checksum ^= hash_contrib; + } + } + } + break; + } + } + + LLXMLNodePtr checksum_node; + + // Compare checksums + { + U32 node_integer_checksum = 0; + if (!getAttribute("integer_checksum", checksum_node, FALSE) || + checksum_node->getUnsignedValue(1, &node_integer_checksum, ENCODING_HEX) != 1) + { + error_buffer.append(llformat("ERROR Node %s: Integer checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_integer_checksum != integer_checksum) + { + error_buffer.append(llformat("ERROR Node %s: Integer checksum mismatch: read %X / calc %X.\n", mName->mString, node_integer_checksum, integer_checksum)); + return FALSE; + } + } + + { + U64 node_long_checksum = 0; + if (!getAttribute("long_checksum", checksum_node, FALSE) || + checksum_node->getLongValue(1, &node_long_checksum, ENCODING_HEX) != 1) + { + error_buffer.append(llformat("ERROR Node %s: Long Integer checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_long_checksum != long_checksum) + { + U32 *pp1 = (U32 *)&node_long_checksum; + U32 *pp2 = (U32 *)&long_checksum; + error_buffer.append(llformat("ERROR Node %s: Long Integer checksum mismatch: read %08X%08X / calc %08X%08X.\n", mName->mString, pp1[1], pp1[0], pp2[1], pp2[0])); + return FALSE; + } + } + + { + U32 node_bool_true_count = 0; + if (!getAttribute("bool_true_count", checksum_node, FALSE) || + checksum_node->getUnsignedValue(1, &node_bool_true_count, ENCODING_HEX) != 1) + { + error_buffer.append(llformat("ERROR Node %s: Boolean checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_bool_true_count != bool_true_count) + { + error_buffer.append(llformat("ERROR Node %s: Boolean checksum mismatch: read %X / calc %X.\n", mName->mString, node_bool_true_count, bool_true_count)); + return FALSE; + } + } + + { + LLUUID node_uuid_checksum; + if (!getAttribute("uuid_checksum", checksum_node, FALSE) || + checksum_node->getUUIDValue(1, &node_uuid_checksum) != 1) + { + error_buffer.append(llformat("ERROR Node %s: UUID checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_uuid_checksum != uuid_checksum) + { + error_buffer.append(llformat("ERROR Node %s: UUID checksum mismatch: read %s / calc %s.\n", mName->mString, node_uuid_checksum.asString().c_str(), uuid_checksum.asString().c_str())); + return FALSE; + } + } + + { + U32 node_noderef_checksum = 0; + if (!getAttribute("noderef_checksum", checksum_node, FALSE) || + checksum_node->getUnsignedValue(1, &node_noderef_checksum, ENCODING_HEX) != 1) + { + error_buffer.append(llformat("ERROR Node %s: Node Ref checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_noderef_checksum != noderef_checksum) + { + error_buffer.append(llformat("ERROR Node %s: Node Ref checksum mismatch: read %X / calc %X.\n", mName->mString, node_noderef_checksum, noderef_checksum)); + return FALSE; + } + } + + { + U32 node_float_checksum = 0; + if (!getAttribute("float_checksum", checksum_node, FALSE) || + checksum_node->getUnsignedValue(1, &node_float_checksum, ENCODING_HEX) != 1) + { + error_buffer.append(llformat("ERROR Node %s: Float checksum missing.\n", mName->mString)); + return FALSE; + } + if (node_float_checksum != float_checksum) + { + error_buffer.append(llformat("ERROR Node %s: Float checksum mismatch: read %X / calc %X.\n", mName->mString, node_float_checksum, float_checksum)); + return FALSE; + } + } + + return TRUE; } LLXMLNodePtr LLXMLNode::getFirstChild() const { - if (mChildren.isNull()) return NULL; - LLXMLNodePtr ret = mChildren->head; - return ret; + if (mChildren.isNull()) return NULL; + LLXMLNodePtr ret = mChildren->head; + return ret; } LLXMLNodePtr LLXMLNode::getNextSibling() const { - LLXMLNodePtr ret = mNext; - return ret; + LLXMLNodePtr ret = mNext; + return ret; } -std::string LLXMLNode::getSanitizedValue() const -{ - if (mIsAttribute) - { - return getValue() ; - } - else - { - return getTextContents(); - } +std::string LLXMLNode::getSanitizedValue() const +{ + if (mIsAttribute) + { + return getValue() ; + } + else + { + return getTextContents(); + } } std::string LLXMLNode::getTextContents() const { - std::string msg; - std::string contents = mValue; - std::string::size_type n = contents.find_first_not_of(" \t\n"); - if (n != std::string::npos && contents[n] == '\"') - { - // Case 1: node has quoted text - S32 num_lines = 0; - while(1) - { - // mContents[n] == '"' - ++n; - std::string::size_type t = n; - std::string::size_type m = 0; - // fix-up escaped characters - while(1) - { - m = contents.find_first_of("\\\"", t); // find first \ or " - if ((m == std::string::npos) || (contents[m] == '\"')) - { - break; - } - contents.erase(m,1); - t = m+1; - } - if (m == std::string::npos) - { - break; - } - // mContents[m] == '"' - num_lines++; - msg += contents.substr(n,m-n) + "\n"; - n = contents.find_first_of("\"", m+1); - if (n == std::string::npos) - { - if (num_lines == 1) - { - msg.erase(msg.size()-1); // remove "\n" if only one line - } - break; - } - } - } - else - { - // Case 2: node has embedded text (beginning and trailing whitespace trimmed) - std::string::size_type start = mValue.find_first_not_of(" \t\n"); - if (start != mValue.npos) - { - std::string::size_type end = mValue.find_last_not_of(" \t\n"); - if (end != mValue.npos) - { - msg = mValue.substr(start, end+1-start); - } - else - { - msg = mValue.substr(start); - } - } - // Convert any internal CR to LF - msg = utf8str_removeCRLF(msg); - } - return msg; + std::string msg; + std::string contents = mValue; + std::string::size_type n = contents.find_first_not_of(" \t\n"); + if (n != std::string::npos && contents[n] == '\"') + { + // Case 1: node has quoted text + S32 num_lines = 0; + while(1) + { + // mContents[n] == '"' + ++n; + std::string::size_type t = n; + std::string::size_type m = 0; + // fix-up escaped characters + while(1) + { + m = contents.find_first_of("\\\"", t); // find first \ or " + if ((m == std::string::npos) || (contents[m] == '\"')) + { + break; + } + contents.erase(m,1); + t = m+1; + } + if (m == std::string::npos) + { + break; + } + // mContents[m] == '"' + num_lines++; + msg += contents.substr(n,m-n) + "\n"; + n = contents.find_first_of("\"", m+1); + if (n == std::string::npos) + { + if (num_lines == 1) + { + msg.erase(msg.size()-1); // remove "\n" if only one line + } + break; + } + } + } + else + { + // Case 2: node has embedded text (beginning and trailing whitespace trimmed) + std::string::size_type start = mValue.find_first_not_of(" \t\n"); + if (start != mValue.npos) + { + std::string::size_type end = mValue.find_last_not_of(" \t\n"); + if (end != mValue.npos) + { + msg = mValue.substr(start, end+1-start); + } + else + { + msg = mValue.substr(start); + } + } + // Convert any internal CR to LF + msg = utf8str_removeCRLF(msg); + } + return msg; } void LLXMLNode::setLineNumber(S32 line_number) { - mLineNumber = line_number; + mLineNumber = line_number; } S32 LLXMLNode::getLineNumber() { - return mLineNumber; + return mLineNumber; } diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index 0b8da5dc5d..62ab51fa8c 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -1,25 +1,25 @@ -/** +/** * @file llxmlnode.h * @brief LLXMLNode definition * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -54,15 +54,15 @@ class LLColor4U; struct CompareAttributes { - bool operator()(const LLStringTableEntry* const lhs, const LLStringTableEntry* const rhs) const - { - if (lhs == NULL) - return TRUE; - if (rhs == NULL) - return FALSE; - - return strcmp(lhs->mString, rhs->mString) < 0; - } + bool operator()(const LLStringTableEntry* const lhs, const LLStringTableEntry* const rhs) const + { + if (lhs == NULL) + return TRUE; + if (rhs == NULL) + return FALSE; + + return strcmp(lhs->mString, rhs->mString) < 0; + } }; @@ -84,78 +84,78 @@ class LLVector4U; struct LLXMLChildren : public LLThreadSafeRefCount { - LLXMLChildList map; // Map of children names->pointers - LLXMLNodePtr head; // Head of the double-linked list - LLXMLNodePtr tail; // Tail of the double-linked list + LLXMLChildList map; // Map of children names->pointers + LLXMLNodePtr head; // Head of the double-linked list + LLXMLNodePtr tail; // Tail of the double-linked list }; typedef LLPointer<LLXMLChildren> LLXMLChildrenPtr; class LLXMLNode : public LLThreadSafeRefCount { public: - enum ValueType - { - TYPE_CONTAINER, // A node which contains nodes - TYPE_UNKNOWN, // A node loaded from file without a specified type - TYPE_BOOLEAN, // "true" or "false" - TYPE_INTEGER, // any integer type: U8, U32, S32, U64, etc. - TYPE_FLOAT, // any floating point type: F32, F64 - TYPE_STRING, // a string - TYPE_UUID, // a UUID - TYPE_NODEREF, // the ID of another node in the hierarchy to reference - }; - - enum Encoding - { - ENCODING_DEFAULT = 0, - ENCODING_DECIMAL, - ENCODING_HEX, - // ENCODING_BASE32, // Not implemented yet - }; + enum ValueType + { + TYPE_CONTAINER, // A node which contains nodes + TYPE_UNKNOWN, // A node loaded from file without a specified type + TYPE_BOOLEAN, // "true" or "false" + TYPE_INTEGER, // any integer type: U8, U32, S32, U64, etc. + TYPE_FLOAT, // any floating point type: F32, F64 + TYPE_STRING, // a string + TYPE_UUID, // a UUID + TYPE_NODEREF, // the ID of another node in the hierarchy to reference + }; + + enum Encoding + { + ENCODING_DEFAULT = 0, + ENCODING_DECIMAL, + ENCODING_HEX, + // ENCODING_BASE32, // Not implemented yet + }; protected: - ~LLXMLNode(); + ~LLXMLNode(); public: - LLXMLNode(); - LLXMLNode(const char* name, BOOL is_attribute); - LLXMLNode(LLStringTableEntry* name, BOOL is_attribute); - LLXMLNode(const LLXMLNode& rhs); - LLXMLNodePtr deepCopy(); + LLXMLNode(); + LLXMLNode(const char* name, BOOL is_attribute); + LLXMLNode(LLStringTableEntry* name, BOOL is_attribute); + LLXMLNode(const LLXMLNode& rhs); + LLXMLNodePtr deepCopy(); - BOOL isNull(); + BOOL isNull(); - BOOL deleteChild(LLXMLNode* child); - void addChild(LLXMLNodePtr& new_child); + BOOL deleteChild(LLXMLNode* child); + void addChild(LLXMLNodePtr& new_child); void setParent(LLXMLNodePtr& new_parent); // reparent if necessary // Serialization - static bool parseFile( - const std::string& filename, - LLXMLNodePtr& node, - LLXMLNode* defaults_tree); - static bool parseBuffer( - U8* buffer, - U32 length, - LLXMLNodePtr& node, - LLXMLNode* defaults); - static bool parseStream( - std::istream& str, - LLXMLNodePtr& node, - LLXMLNode* defaults); - static bool updateNode( - LLXMLNodePtr& node, - LLXMLNodePtr& update_node); - - static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths); - - - // Write standard XML file header: - // <?xml version="1.0" encoding="utf-8" standalone="yes" ?> - static void writeHeaderToFile(LLFILE *out_file); - - // Write XML to file with one attribute per line. - // XML escapes values as they are written. + static bool parseFile( + const std::string& filename, + LLXMLNodePtr& node, + LLXMLNode* defaults_tree); + static bool parseBuffer( + U8* buffer, + U32 length, + LLXMLNodePtr& node, + LLXMLNode* defaults); + static bool parseStream( + std::istream& str, + LLXMLNodePtr& node, + LLXMLNode* defaults); + static bool updateNode( + LLXMLNodePtr& node, + LLXMLNodePtr& update_node); + + static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths); + + + // Write standard XML file header: + // <?xml version="1.0" encoding="utf-8" standalone="yes" ?> + static void writeHeaderToFile(LLFILE *out_file); + + // Write XML to file with one attribute per line. + // XML escapes values as they are written. void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true); void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true); @@ -181,39 +181,39 @@ public: U32 getUUIDValue(U32 expected_length, LLUUID *array); U32 getNodeRefValue(U32 expected_length, LLXMLNode **array); - BOOL hasAttribute(const char* name ); + BOOL hasAttribute(const char* name ); // these are designed to be more generic versions of the functions // rather than relying on LL-types - bool getAttribute_bool(const char* name, bool& value ); - - BOOL getAttributeBOOL(const char* name, BOOL& value ); - BOOL getAttributeU8(const char* name, U8& value ); - BOOL getAttributeS8(const char* name, S8& value ); - BOOL getAttributeU16(const char* name, U16& value ); - BOOL getAttributeS16(const char* name, S16& value ); - BOOL getAttributeU32(const char* name, U32& value ); - BOOL getAttributeS32(const char* name, S32& value ); - BOOL getAttributeF32(const char* name, F32& value ); - BOOL getAttributeF64(const char* name, F64& value ); - BOOL getAttributeColor(const char* name, LLColor4& value ); - BOOL getAttributeColor4(const char* name, LLColor4& value ); - BOOL getAttributeColor4U(const char* name, LLColor4U& value ); - BOOL getAttributeVector3(const char* name, LLVector3& value ); - BOOL getAttributeVector3d(const char* name, LLVector3d& value ); - BOOL getAttributeQuat(const char* name, LLQuaternion& value ); - BOOL getAttributeUUID(const char* name, LLUUID& value ); - BOOL getAttributeString(const char* name, std::string& value ); + bool getAttribute_bool(const char* name, bool& value ); + + BOOL getAttributeBOOL(const char* name, BOOL& value ); + BOOL getAttributeU8(const char* name, U8& value ); + BOOL getAttributeS8(const char* name, S8& value ); + BOOL getAttributeU16(const char* name, U16& value ); + BOOL getAttributeS16(const char* name, S16& value ); + BOOL getAttributeU32(const char* name, U32& value ); + BOOL getAttributeS32(const char* name, S32& value ); + BOOL getAttributeF32(const char* name, F32& value ); + BOOL getAttributeF64(const char* name, F64& value ); + BOOL getAttributeColor(const char* name, LLColor4& value ); + BOOL getAttributeColor4(const char* name, LLColor4& value ); + BOOL getAttributeColor4U(const char* name, LLColor4U& value ); + BOOL getAttributeVector3(const char* name, LLVector3& value ); + BOOL getAttributeVector3d(const char* name, LLVector3d& value ); + BOOL getAttributeQuat(const char* name, LLQuaternion& value ); + BOOL getAttributeUUID(const char* name, LLUUID& value ); + BOOL getAttributeString(const char* name, std::string& value ); const ValueType& getType() const { return mType; } U32 getLength() const { return mLength; } U32 getPrecision() const { return mPrecision; } const std::string& getValue() const { return mValue; } - std::string getSanitizedValue() const; - std::string getTextContents() const; + std::string getSanitizedValue() const; + std::string getTextContents() const; const LLStringTableEntry* getName() const { return mName; } - BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); } - BOOL hasName(const std::string& name) const { return mName == gStringTable.checkStringEntry(name.c_str()); } + BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); } + BOOL hasName(const std::string& name) const { return mName == gStringTable.checkStringEntry(name.c_str()); } const std::string& getID() const { return mID; } U32 getChildCount() const; @@ -223,117 +223,117 @@ public: bool getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); void getChildren(const char* name, LLXMLNodeList &children, BOOL use_default_if_missing = TRUE) const; void getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, BOOL use_default_if_missing = TRUE) const; - - // recursively finds all children at any level matching name - void getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const; - bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); - bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); + // recursively finds all children at any level matching name + void getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const; + + bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); + bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); - S32 getLineNumber(); + S32 getLineNumber(); - // The following skip over attributes - LLXMLNodePtr getFirstChild() const; - LLXMLNodePtr getNextSibling() const; + // The following skip over attributes + LLXMLNodePtr getFirstChild() const; + LLXMLNodePtr getNextSibling() const; LLXMLNodePtr getRoot(); - // Setters - - bool setAttributeString(const char* attr, const std::string& value); - - void setBoolValue(const BOOL value) { setBoolValue(1, &value); } - void setByteValue(const U8 value, Encoding encoding = ENCODING_DEFAULT) { setByteValue(1, &value, encoding); } - void setIntValue(const S32 value, Encoding encoding = ENCODING_DEFAULT) { setIntValue(1, &value, encoding); } - void setUnsignedValue(const U32 value, Encoding encoding = ENCODING_DEFAULT) { setUnsignedValue(1, &value, encoding); } - void setLongValue(const U64 value, Encoding encoding = ENCODING_DEFAULT) { setLongValue(1, &value, encoding); } - void setFloatValue(const F32 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setFloatValue(1, &value, encoding); } - void setDoubleValue(const F64 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setDoubleValue(1, &value, encoding); } - void setStringValue(const std::string& value) { setStringValue(1, &value); } - void setUUIDValue(const LLUUID value) { setUUIDValue(1, &value); } - void setNodeRefValue(const LLXMLNode *value) { setNodeRefValue(1, &value); } - - void setBoolValue(U32 length, const BOOL *array); - void setByteValue(U32 length, const U8 *array, Encoding encoding = ENCODING_DEFAULT); - void setIntValue(U32 length, const S32 *array, Encoding encoding = ENCODING_DEFAULT); - void setUnsignedValue(U32 length, const U32* array, Encoding encoding = ENCODING_DEFAULT); - void setLongValue(U32 length, const U64 *array, Encoding encoding = ENCODING_DEFAULT); - void setFloatValue(U32 length, const F32 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0); - void setDoubleValue(U32 length, const F64 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0); - void setStringValue(U32 length, const std::string *array); - void setUUIDValue(U32 length, const LLUUID *array); - void setNodeRefValue(U32 length, const LLXMLNode **array); - void setValue(const std::string& value); - void setName(const std::string& name); - void setName(LLStringTableEntry* name); - - void setLineNumber(S32 line_number); - - // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt) - static std::string escapeXML(const std::string& xml); - - // Set the default node corresponding to this default node - void setDefault(LLXMLNode *default_node); - - // Find the node within defaults_list which corresponds to this node - void findDefault(LLXMLNode *defaults_list); - - void updateDefault(); - - // Delete any child nodes that aren't among the tree's children, recursive - void scrubToTree(LLXMLNode *tree); - - BOOL deleteChildren(const std::string& name); - BOOL deleteChildren(LLStringTableEntry* name); - void setAttributes(ValueType type, U32 precision, Encoding encoding, U32 length); -// void appendValue(const std::string& value); // Unused - - // Unit Testing - void createUnitTest(S32 max_num_children); - BOOL performUnitTest(std::string &error_buffer); + // Setters + + bool setAttributeString(const char* attr, const std::string& value); + + void setBoolValue(const BOOL value) { setBoolValue(1, &value); } + void setByteValue(const U8 value, Encoding encoding = ENCODING_DEFAULT) { setByteValue(1, &value, encoding); } + void setIntValue(const S32 value, Encoding encoding = ENCODING_DEFAULT) { setIntValue(1, &value, encoding); } + void setUnsignedValue(const U32 value, Encoding encoding = ENCODING_DEFAULT) { setUnsignedValue(1, &value, encoding); } + void setLongValue(const U64 value, Encoding encoding = ENCODING_DEFAULT) { setLongValue(1, &value, encoding); } + void setFloatValue(const F32 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setFloatValue(1, &value, encoding); } + void setDoubleValue(const F64 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setDoubleValue(1, &value, encoding); } + void setStringValue(const std::string& value) { setStringValue(1, &value); } + void setUUIDValue(const LLUUID value) { setUUIDValue(1, &value); } + void setNodeRefValue(const LLXMLNode *value) { setNodeRefValue(1, &value); } + + void setBoolValue(U32 length, const BOOL *array); + void setByteValue(U32 length, const U8 *array, Encoding encoding = ENCODING_DEFAULT); + void setIntValue(U32 length, const S32 *array, Encoding encoding = ENCODING_DEFAULT); + void setUnsignedValue(U32 length, const U32* array, Encoding encoding = ENCODING_DEFAULT); + void setLongValue(U32 length, const U64 *array, Encoding encoding = ENCODING_DEFAULT); + void setFloatValue(U32 length, const F32 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0); + void setDoubleValue(U32 length, const F64 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0); + void setStringValue(U32 length, const std::string *array); + void setUUIDValue(U32 length, const LLUUID *array); + void setNodeRefValue(U32 length, const LLXMLNode **array); + void setValue(const std::string& value); + void setName(const std::string& name); + void setName(LLStringTableEntry* name); + + void setLineNumber(S32 line_number); + + // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt) + static std::string escapeXML(const std::string& xml); + + // Set the default node corresponding to this default node + void setDefault(LLXMLNode *default_node); + + // Find the node within defaults_list which corresponds to this node + void findDefault(LLXMLNode *defaults_list); + + void updateDefault(); + + // Delete any child nodes that aren't among the tree's children, recursive + void scrubToTree(LLXMLNode *tree); + + BOOL deleteChildren(const std::string& name); + BOOL deleteChildren(LLStringTableEntry* name); + void setAttributes(ValueType type, U32 precision, Encoding encoding, U32 length); +// void appendValue(const std::string& value); // Unused + + // Unit Testing + void createUnitTest(S32 max_num_children); + BOOL performUnitTest(std::string &error_buffer); protected: - BOOL removeChild(LLXMLNode* child); + BOOL removeChild(LLXMLNode* child); public: - std::string mID; // The ID attribute of this node - - XML_Parser *mParser; // Temporary pointer while loading - - BOOL mIsAttribute; // Flag is only used for output formatting - U32 mVersionMajor; // Version of this tag to use - U32 mVersionMinor; - U32 mLength; // If the length is nonzero, then only return arrays of this length - U32 mPrecision; // The number of BITS per array item - ValueType mType; // The value type - Encoding mEncoding; // The value encoding - S32 mLineNumber; // line number in source file, if applicable - - LLXMLNode* mParent; // The parent node - LLXMLChildrenPtr mChildren; // The child nodes - LLXMLAttribList mAttributes; // The attribute nodes - LLXMLNodePtr mPrev; // Double-linked list previous node - LLXMLNodePtr mNext; // Double-linked list next node - - static BOOL sStripEscapedStrings; - static BOOL sStripWhitespaceValues; - + std::string mID; // The ID attribute of this node + + XML_Parser *mParser; // Temporary pointer while loading + + BOOL mIsAttribute; // Flag is only used for output formatting + U32 mVersionMajor; // Version of this tag to use + U32 mVersionMinor; + U32 mLength; // If the length is nonzero, then only return arrays of this length + U32 mPrecision; // The number of BITS per array item + ValueType mType; // The value type + Encoding mEncoding; // The value encoding + S32 mLineNumber; // line number in source file, if applicable + + LLXMLNode* mParent; // The parent node + LLXMLChildrenPtr mChildren; // The child nodes + LLXMLAttribList mAttributes; // The attribute nodes + LLXMLNodePtr mPrev; // Double-linked list previous node + LLXMLNodePtr mNext; // Double-linked list next node + + static BOOL sStripEscapedStrings; + static BOOL sStripWhitespaceValues; + protected: - LLStringTableEntry *mName; // The name of this node + LLStringTableEntry *mName; // The name of this node - // The value of this node (use getters/setters only) - // Values are not XML-escaped in memory - // They may contain " (quot) ' (apos) & (amp) < (lt) > (gt) - std::string mValue; + // The value of this node (use getters/setters only) + // Values are not XML-escaped in memory + // They may contain " (quot) ' (apos) & (amp) < (lt) > (gt) + std::string mValue; - LLXMLNodePtr mDefault; // Mirror node in the default tree + LLXMLNodePtr mDefault; // Mirror node in the default tree - static const char *skipWhitespace(const char *str); - static const char *skipNonWhitespace(const char *str); - static const char *parseInteger(const char *str, U64 *dest, BOOL *is_negative, U32 precision, Encoding encoding); - static const char *parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding); + static const char *skipWhitespace(const char *str); + static const char *skipNonWhitespace(const char *str); + static const char *parseInteger(const char *str, U64 *dest, BOOL *is_negative, U32 precision, Encoding encoding); + static const char *parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding); - BOOL isFullyDefault(); + BOOL isFullyDefault(); }; #endif // LL_LLXMLNODE diff --git a/indra/llxml/llxmlparser.cpp b/indra/llxml/llxmlparser.cpp index 1bdc283f67..ecd75bd410 100644 --- a/indra/llxml/llxmlparser.cpp +++ b/indra/llxml/llxmlparser.cpp @@ -1,31 +1,31 @@ -/** +/** * @file llxmlparser.cpp * @brief LLXmlParser implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ // llxmlparser.cpp -// +// // copyright 2002, linden research inc @@ -36,234 +36,234 @@ LLXmlParser::LLXmlParser() - : - mParser( NULL ), - mDepth( 0 ) + : + mParser( NULL ), + mDepth( 0 ) { - mAuxErrorString = "no error"; + mAuxErrorString = "no error"; + + // Override the document's declared encoding. + mParser = XML_ParserCreate(NULL); - // Override the document's declared encoding. - mParser = XML_ParserCreate(NULL); + XML_SetUserData(mParser, this); + XML_SetElementHandler( mParser, startElementHandler, endElementHandler); + XML_SetCharacterDataHandler( mParser, characterDataHandler); + XML_SetProcessingInstructionHandler( mParser, processingInstructionHandler); + XML_SetCommentHandler( mParser, commentHandler); - XML_SetUserData(mParser, this); - XML_SetElementHandler( mParser, startElementHandler, endElementHandler); - XML_SetCharacterDataHandler( mParser, characterDataHandler); - XML_SetProcessingInstructionHandler( mParser, processingInstructionHandler); - XML_SetCommentHandler( mParser, commentHandler); + XML_SetCdataSectionHandler( mParser, startCdataSectionHandler, endCdataSectionHandler); - XML_SetCdataSectionHandler( mParser, startCdataSectionHandler, endCdataSectionHandler); + // This sets the default handler but does not inhibit expansion of internal entities. + // The entity reference will not be passed to the default handler. + XML_SetDefaultHandlerExpand( mParser, defaultDataHandler); - // This sets the default handler but does not inhibit expansion of internal entities. - // The entity reference will not be passed to the default handler. - XML_SetDefaultHandlerExpand( mParser, defaultDataHandler); - - XML_SetUnparsedEntityDeclHandler( mParser, unparsedEntityDeclHandler); + XML_SetUnparsedEntityDeclHandler( mParser, unparsedEntityDeclHandler); } LLXmlParser::~LLXmlParser() { - XML_ParserFree( mParser ); + XML_ParserFree( mParser ); } BOOL LLXmlParser::parseFile(const std::string &path) { - llassert( !mDepth ); - - BOOL success = TRUE; - - LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */ - if( !file ) - { - mAuxErrorString = llformat( "Couldn't open file %s", path.c_str()); - success = FALSE; - } - else - { - S32 bytes_read = 0; - - fseek(file, 0L, SEEK_END); - S32 buffer_size = ftell(file); - fseek(file, 0L, SEEK_SET); - - void* buffer = XML_GetBuffer(mParser, buffer_size); - if( !buffer ) - { - mAuxErrorString = llformat( "Unable to allocate XML buffer while reading file %s", path.c_str() ); - success = FALSE; - goto exit_label; - } - - bytes_read = (S32)fread(buffer, 1, buffer_size, file); - if( bytes_read <= 0 ) - { - mAuxErrorString = llformat( "Error while reading file %s", path.c_str() ); - success = FALSE; - goto exit_label; - } - - if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) - { - mAuxErrorString = llformat( "Error while parsing file %s", path.c_str() ); - success = FALSE; - } - -exit_label: - fclose( file ); - } - - - if( success ) - { - llassert( !mDepth ); - } - mDepth = 0; - - if( !success ) - { - LL_WARNS() << mAuxErrorString << LL_ENDL; - } - - return success; + llassert( !mDepth ); + + BOOL success = TRUE; + + LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */ + if( !file ) + { + mAuxErrorString = llformat( "Couldn't open file %s", path.c_str()); + success = FALSE; + } + else + { + S32 bytes_read = 0; + + fseek(file, 0L, SEEK_END); + S32 buffer_size = ftell(file); + fseek(file, 0L, SEEK_SET); + + void* buffer = XML_GetBuffer(mParser, buffer_size); + if( !buffer ) + { + mAuxErrorString = llformat( "Unable to allocate XML buffer while reading file %s", path.c_str() ); + success = FALSE; + goto exit_label; + } + + bytes_read = (S32)fread(buffer, 1, buffer_size, file); + if( bytes_read <= 0 ) + { + mAuxErrorString = llformat( "Error while reading file %s", path.c_str() ); + success = FALSE; + goto exit_label; + } + + if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) + { + mAuxErrorString = llformat( "Error while parsing file %s", path.c_str() ); + success = FALSE; + } + +exit_label: + fclose( file ); + } + + + if( success ) + { + llassert( !mDepth ); + } + mDepth = 0; + + if( !success ) + { + LL_WARNS() << mAuxErrorString << LL_ENDL; + } + + return success; } -// Parses some input. Returns 0 if a fatal error is detected. -// The last call must have isFinal true; -// len may be zero for this call (or any other). +// Parses some input. Returns 0 if a fatal error is detected. +// The last call must have isFinal true; +// len may be zero for this call (or any other). S32 LLXmlParser::parse( const char* buf, int len, int isFinal ) { - return XML_Parse(mParser, buf, len, isFinal); + return XML_Parse(mParser, buf, len, isFinal); } const char* LLXmlParser::getErrorString() { - const char* error_string = XML_ErrorString(XML_GetErrorCode( mParser )); - if( !error_string ) - { - error_string = mAuxErrorString.c_str(); - } - return error_string; + const char* error_string = XML_ErrorString(XML_GetErrorCode( mParser )); + if( !error_string ) + { + error_string = mAuxErrorString.c_str(); + } + return error_string; } S32 LLXmlParser::getCurrentLineNumber() { - return XML_GetCurrentLineNumber( mParser ); + return XML_GetCurrentLineNumber( mParser ); } S32 LLXmlParser::getCurrentColumnNumber() { - return XML_GetCurrentColumnNumber(mParser); + return XML_GetCurrentColumnNumber(mParser); } /////////////////////////////////////////////////////////////////////////////// // Pseudo-private methods. These are only used by internal callbacks. -// static +// static void LLXmlParser::startElementHandler( - void *userData, - const XML_Char *name, - const XML_Char **atts) + void *userData, + const XML_Char *name, + const XML_Char **atts) { - LLXmlParser* self = (LLXmlParser*) userData; - self->startElement( name, atts ); - self->mDepth++; + LLXmlParser* self = (LLXmlParser*) userData; + self->startElement( name, atts ); + self->mDepth++; } -// static +// static void LLXmlParser::endElementHandler( - void *userData, - const XML_Char *name) + void *userData, + const XML_Char *name) { - LLXmlParser* self = (LLXmlParser*) userData; - self->mDepth--; - self->endElement( name ); + LLXmlParser* self = (LLXmlParser*) userData; + self->mDepth--; + self->endElement( name ); } // s is not 0 terminated. -// static +// static void LLXmlParser::characterDataHandler( - void *userData, - const XML_Char *s, - int len) + void *userData, + const XML_Char *s, + int len) { - LLXmlParser* self = (LLXmlParser*) userData; - self->characterData( s, len ); + LLXmlParser* self = (LLXmlParser*) userData; + self->characterData( s, len ); } // target and data are 0 terminated -// static +// static void LLXmlParser::processingInstructionHandler( - void *userData, - const XML_Char *target, - const XML_Char *data) + void *userData, + const XML_Char *target, + const XML_Char *data) { - LLXmlParser* self = (LLXmlParser*) userData; - self->processingInstruction( target, data ); + LLXmlParser* self = (LLXmlParser*) userData; + self->processingInstruction( target, data ); } -// data is 0 terminated +// data is 0 terminated // static void LLXmlParser::commentHandler(void *userData, const XML_Char *data) { - LLXmlParser* self = (LLXmlParser*) userData; - self->comment( data ); + LLXmlParser* self = (LLXmlParser*) userData; + self->comment( data ); } // static void LLXmlParser::startCdataSectionHandler(void *userData) { - LLXmlParser* self = (LLXmlParser*) userData; - self->mDepth++; - self->startCdataSection(); + LLXmlParser* self = (LLXmlParser*) userData; + self->mDepth++; + self->startCdataSection(); } // static void LLXmlParser::endCdataSectionHandler(void *userData) { - LLXmlParser* self = (LLXmlParser*) userData; - self->endCdataSection(); - self->mDepth++; + LLXmlParser* self = (LLXmlParser*) userData; + self->endCdataSection(); + self->mDepth++; } -// This is called for any characters in the XML document for -// which there is no applicable handler. This includes both -// characters that are part of markup which is of a kind that is -// not reported (comments, markup declarations), or characters -// that are part of a construct which could be reported but -// for which no handler has been supplied. The characters are passed -// exactly as they were in the XML document except that -// they will be encoded in UTF-8. Line boundaries are not normalized. -// Note that a byte order mark character is not passed to the default handler. -// There are no guarantees about how characters are divided between calls -// to the default handler: for example, a comment might be split between -// multiple calls. - -// static +// This is called for any characters in the XML document for +// which there is no applicable handler. This includes both +// characters that are part of markup which is of a kind that is +// not reported (comments, markup declarations), or characters +// that are part of a construct which could be reported but +// for which no handler has been supplied. The characters are passed +// exactly as they were in the XML document except that +// they will be encoded in UTF-8. Line boundaries are not normalized. +// Note that a byte order mark character is not passed to the default handler. +// There are no guarantees about how characters are divided between calls +// to the default handler: for example, a comment might be split between +// multiple calls. + +// static void LLXmlParser::defaultDataHandler( - void *userData, - const XML_Char *s, - int len) + void *userData, + const XML_Char *s, + int len) { - LLXmlParser* self = (LLXmlParser*) userData; - self->defaultData( s, len ); + LLXmlParser* self = (LLXmlParser*) userData; + self->defaultData( s, len ); } -// This is called for a declaration of an unparsed (NDATA) -// entity. The base argument is whatever was set by XML_SetBase. -// The entityName, systemId and notationName arguments will never be null. -// The other arguments may be. -// static +// This is called for a declaration of an unparsed (NDATA) +// entity. The base argument is whatever was set by XML_SetBase. +// The entityName, systemId and notationName arguments will never be null. +// The other arguments may be. +// static void LLXmlParser::unparsedEntityDeclHandler( - void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName) + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName) { - LLXmlParser* self = (LLXmlParser*) userData; - self->unparsedEntityDecl( entityName, base, systemId, publicId, notationName ); + LLXmlParser* self = (LLXmlParser*) userData; + self->unparsedEntityDecl( entityName, base, systemId, publicId, notationName ); } @@ -277,110 +277,110 @@ class LLXmlDOMParser : public LLXmlParser { public: - LLXmlDOMParser() {} - virtual ~LLXmlDOMParser() {} - - void tabs() - { - for ( int i = 0; i < getDepth(); i++) - { - putchar(' '); - } - } - - virtual void startElement(const char *name, const char **atts) - { - tabs(); - printf("startElement %s\n", name); - - S32 i = 0; - while( atts[i] && atts[i+1] ) - { - tabs(); - printf( "\t%s=%s\n", atts[i], atts[i+1] ); - i += 2; - } - - if( atts[i] ) - { - tabs(); - printf( "\ttrailing attribute: %s\n", atts[i] ); - } - } - - virtual void endElement(const char *name) - { - tabs(); - printf("endElement %s\n", name); - } - - virtual void characterData(const char *s, int len) - { - tabs(); - - char* str = new char[len+1]; - strncpy( str, s, len ); - str[len] = '\0'; - printf("CharacterData %s\n", str); - delete str; - } - - virtual void processingInstruction(const char *target, const char *data) - { - tabs(); - printf("processingInstruction %s\n", data); - } - virtual void comment(const char *data) - { - tabs(); - printf("comment %s\n", data); - } - - virtual void startCdataSection() - { - tabs(); - printf("startCdataSection\n"); - } - - virtual void endCdataSection() - { - tabs(); - printf("endCdataSection\n"); - } - - virtual void defaultData(const char *s, int len) - { - tabs(); - - char* str = new char[len+1]; - strncpy( str, s, len ); - str[len] = '\0'; - printf("defaultData %s\n", str); - delete str; - } - - virtual void unparsedEntityDecl( - const char *entityName, - const char *base, - const char *systemId, - const char *publicId, - const char *notationName) - { - tabs(); - - printf( - "unparsed entity:\n" - "\tentityName %s\n" - "\tbase %s\n" - "\tsystemId %s\n" - "\tpublicId %s\n" - "\tnotationName %s\n", - entityName, - base, - systemId, - publicId, - notationName ); - } + LLXmlDOMParser() {} + virtual ~LLXmlDOMParser() {} + + void tabs() + { + for ( int i = 0; i < getDepth(); i++) + { + putchar(' '); + } + } + + virtual void startElement(const char *name, const char **atts) + { + tabs(); + printf("startElement %s\n", name); + + S32 i = 0; + while( atts[i] && atts[i+1] ) + { + tabs(); + printf( "\t%s=%s\n", atts[i], atts[i+1] ); + i += 2; + } + + if( atts[i] ) + { + tabs(); + printf( "\ttrailing attribute: %s\n", atts[i] ); + } + } + + virtual void endElement(const char *name) + { + tabs(); + printf("endElement %s\n", name); + } + + virtual void characterData(const char *s, int len) + { + tabs(); + + char* str = new char[len+1]; + strncpy( str, s, len ); + str[len] = '\0'; + printf("CharacterData %s\n", str); + delete str; + } + + virtual void processingInstruction(const char *target, const char *data) + { + tabs(); + printf("processingInstruction %s\n", data); + } + virtual void comment(const char *data) + { + tabs(); + printf("comment %s\n", data); + } + + virtual void startCdataSection() + { + tabs(); + printf("startCdataSection\n"); + } + + virtual void endCdataSection() + { + tabs(); + printf("endCdataSection\n"); + } + + virtual void defaultData(const char *s, int len) + { + tabs(); + + char* str = new char[len+1]; + strncpy( str, s, len ); + str[len] = '\0'; + printf("defaultData %s\n", str); + delete str; + } + + virtual void unparsedEntityDecl( + const char *entityName, + const char *base, + const char *systemId, + const char *publicId, + const char *notationName) + { + tabs(); + + printf( + "unparsed entity:\n" + "\tentityName %s\n" + "\tbase %s\n" + "\tsystemId %s\n" + "\tpublicId %s\n" + "\tnotationName %s\n", + entityName, + base, + systemId, + publicId, + notationName ); + } }; @@ -391,7 +391,7 @@ int main() LLFILE* file = LLFile::fopen("test.xml", "rb"); if( !file ) { - return 1; + return 1; } LLXmlDOMParser parser; @@ -400,11 +400,11 @@ int main() size_t len = fread(buf, 1, sizeof(buf), file); done = len < sizeof(buf); if( 0 == parser.parse( buf, len, done) ) - { + { fprintf(stderr, - "%s at line %d\n", - parser.getErrorString(), - parser.getCurrentLineNumber() ); + "%s at line %d\n", + parser.getErrorString(), + parser.getCurrentLineNumber() ); return 1; } } while (!done); diff --git a/indra/llxml/llxmlparser.h b/indra/llxml/llxmlparser.h index a5b210404f..3a8a927350 100644 --- a/indra/llxml/llxmlparser.h +++ b/indra/llxml/llxmlparser.h @@ -1,25 +1,25 @@ -/** +/** * @file llxmlparser.h * @brief LLXmlParser class definition * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,95 +39,95 @@ class LLXmlParser { public: - LLXmlParser(); - virtual ~LLXmlParser(); + LLXmlParser(); + virtual ~LLXmlParser(); + + // Parses entire file + BOOL parseFile(const std::string &path); - // Parses entire file - BOOL parseFile(const std::string &path); + // Parses some input. Returns 0 if a fatal error is detected. + // The last call must have isFinal true; + // len may be zero for this call (or any other). + S32 parse( const char* buf, int len, int isFinal ); - // Parses some input. Returns 0 if a fatal error is detected. - // The last call must have isFinal true; - // len may be zero for this call (or any other). - S32 parse( const char* buf, int len, int isFinal ); + const char* getErrorString(); - const char* getErrorString(); - - S32 getCurrentLineNumber(); + S32 getCurrentLineNumber(); - S32 getCurrentColumnNumber(); + S32 getCurrentColumnNumber(); - S32 getDepth() { return mDepth; } + S32 getDepth() { return mDepth; } protected: - // atts is array of name/value pairs, terminated by 0; - // names and values are 0 terminated. - virtual void startElement(const char *name, const char **atts) {} - - virtual void endElement(const char *name) {} - - // s is not 0 terminated. - virtual void characterData(const char *s, int len) {} - - // target and data are 0 terminated - virtual void processingInstruction(const char *target, const char *data) {} - - // data is 0 terminated - virtual void comment(const char *data) {} - - virtual void startCdataSection() {} - - virtual void endCdataSection() {} - - // This is called for any characters in the XML document for - // which there is no applicable handler. This includes both - // characters that are part of markup which is of a kind that is - // not reported (comments, markup declarations), or characters - // that are part of a construct which could be reported but - // for which no handler has been supplied. The characters are passed - // exactly as they were in the XML document except that - // they will be encoded in UTF-8. Line boundaries are not normalized. - // Note that a byte order mark character is not passed to the default handler. - // There are no guarantees about how characters are divided between calls - // to the default handler: for example, a comment might be split between - // multiple calls. - virtual void defaultData(const char *s, int len) {} - - // This is called for a declaration of an unparsed (NDATA) - // entity. The base argument is whatever was set by XML_SetBase. - // The entityName, systemId and notationName arguments will never be null. - // The other arguments may be. - virtual void unparsedEntityDecl( - const char *entityName, - const char *base, - const char *systemId, - const char *publicId, - const char *notationName) {} + // atts is array of name/value pairs, terminated by 0; + // names and values are 0 terminated. + virtual void startElement(const char *name, const char **atts) {} + + virtual void endElement(const char *name) {} + + // s is not 0 terminated. + virtual void characterData(const char *s, int len) {} + + // target and data are 0 terminated + virtual void processingInstruction(const char *target, const char *data) {} + + // data is 0 terminated + virtual void comment(const char *data) {} + + virtual void startCdataSection() {} + + virtual void endCdataSection() {} + + // This is called for any characters in the XML document for + // which there is no applicable handler. This includes both + // characters that are part of markup which is of a kind that is + // not reported (comments, markup declarations), or characters + // that are part of a construct which could be reported but + // for which no handler has been supplied. The characters are passed + // exactly as they were in the XML document except that + // they will be encoded in UTF-8. Line boundaries are not normalized. + // Note that a byte order mark character is not passed to the default handler. + // There are no guarantees about how characters are divided between calls + // to the default handler: for example, a comment might be split between + // multiple calls. + virtual void defaultData(const char *s, int len) {} + + // This is called for a declaration of an unparsed (NDATA) + // entity. The base argument is whatever was set by XML_SetBase. + // The entityName, systemId and notationName arguments will never be null. + // The other arguments may be. + virtual void unparsedEntityDecl( + const char *entityName, + const char *base, + const char *systemId, + const char *publicId, + const char *notationName) {} public: - /////////////////////////////////////////////////////////////////////////////// - // Pseudo-private methods. These are only used by internal callbacks. - - static void startElementHandler(void *userData, const XML_Char *name, const XML_Char **atts); - static void endElementHandler(void *userData, const XML_Char *name); - static void characterDataHandler(void *userData, const XML_Char *s, int len); - static void processingInstructionHandler(void *userData, const XML_Char *target, const XML_Char *data); - static void commentHandler(void *userData, const XML_Char *data); - static void startCdataSectionHandler(void *userData); - static void endCdataSectionHandler(void *userData); - static void defaultDataHandler( void *userData, const XML_Char *s, int len); - static void unparsedEntityDeclHandler( - void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); + /////////////////////////////////////////////////////////////////////////////// + // Pseudo-private methods. These are only used by internal callbacks. + + static void startElementHandler(void *userData, const XML_Char *name, const XML_Char **atts); + static void endElementHandler(void *userData, const XML_Char *name); + static void characterDataHandler(void *userData, const XML_Char *s, int len); + static void processingInstructionHandler(void *userData, const XML_Char *target, const XML_Char *data); + static void commentHandler(void *userData, const XML_Char *data); + static void startCdataSectionHandler(void *userData); + static void endCdataSectionHandler(void *userData); + static void defaultDataHandler( void *userData, const XML_Char *s, int len); + static void unparsedEntityDeclHandler( + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); protected: - XML_Parser mParser; - int mDepth; - std::string mAuxErrorString; + XML_Parser mParser; + int mDepth; + std::string mAuxErrorString; }; #endif // LL_LLXMLPARSER_H diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp index ed9c07e1db..baf2e6a951 100644 --- a/indra/llxml/llxmltree.cpp +++ b/indra/llxml/llxmltree.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llxmltree.cpp * @brief LLXmlTree implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -43,156 +43,156 @@ LLStdStringTable LLXmlTree::sAttributeKeys(1024); LLXmlTree::LLXmlTree() - : mRoot( NULL ), - mNodeNames(512) + : mRoot( NULL ), + mNodeNames(512) { } LLXmlTree::~LLXmlTree() { - cleanup(); + cleanup(); } void LLXmlTree::cleanup() { - delete mRoot; - mRoot = NULL; - mNodeNames.cleanup(); + delete mRoot; + mRoot = NULL; + mNodeNames.cleanup(); } BOOL LLXmlTree::parseFile(const std::string &path, BOOL keep_contents) { - delete mRoot; - mRoot = NULL; + delete mRoot; + mRoot = NULL; - LLXmlTreeParser parser(this); - BOOL success = parser.parseFile( path, &mRoot, keep_contents ); - if( !success ) - { - S32 line_number = parser.getCurrentLineNumber(); - const char* error = parser.getErrorString(); - LL_WARNS() << "LLXmlTree parse failed. Line " << line_number << ": " << error << LL_ENDL; - } - return success; + LLXmlTreeParser parser(this); + BOOL success = parser.parseFile( path, &mRoot, keep_contents ); + if( !success ) + { + S32 line_number = parser.getCurrentLineNumber(); + const char* error = parser.getErrorString(); + LL_WARNS() << "LLXmlTree parse failed. Line " << line_number << ": " << error << LL_ENDL; + } + return success; } void LLXmlTree::dump() { - if( mRoot ) - { - dumpNode( mRoot, " " ); - } + if( mRoot ) + { + dumpNode( mRoot, " " ); + } } void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix ) { - node->dump( prefix ); + node->dump( prefix ); - std::string new_prefix = prefix + " "; - for( LLXmlTreeNode* child = node->getFirstChild(); child; child = node->getNextChild() ) - { - dumpNode( child, new_prefix ); - } + std::string new_prefix = prefix + " "; + for( LLXmlTreeNode* child = node->getFirstChild(); child; child = node->getNextChild() ) + { + dumpNode( child, new_prefix ); + } } ////////////////////////////////////////////////////////////// // LLXmlTreeNode LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree ) - : mName(name), - mParent(parent), - mTree(tree) + : mName(name), + mParent(parent), + mTree(tree) { } LLXmlTreeNode::~LLXmlTreeNode() { - attribute_map_t::iterator iter; - for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++) - delete iter->second; + attribute_map_t::iterator iter; + for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++) + delete iter->second; for(LLXmlTreeNode* node : mChildren) { delete node; } mChildren.clear(); } - + void LLXmlTreeNode::dump( const std::string& prefix ) { - LL_INFOS() << prefix << mName ; - if( !mContents.empty() ) - { - LL_CONT << " contents = \"" << mContents << "\""; - } - attribute_map_t::iterator iter; - for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++) - { - LLStdStringHandle key = iter->first; - const std::string* value = iter->second; - LL_CONT << prefix << " " << key << "=" << (value->empty() ? "NULL" : *value); - } - LL_CONT << LL_ENDL; -} + LL_INFOS() << prefix << mName ; + if( !mContents.empty() ) + { + LL_CONT << " contents = \"" << mContents << "\""; + } + attribute_map_t::iterator iter; + for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++) + { + LLStdStringHandle key = iter->first; + const std::string* value = iter->second; + LL_CONT << prefix << " " << key << "=" << (value->empty() ? "NULL" : *value); + } + LL_CONT << LL_ENDL; +} BOOL LLXmlTreeNode::hasAttribute(const std::string& name) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - attribute_map_t::iterator iter = mAttributes.find(canonical_name); - return (iter == mAttributes.end()) ? false : true; + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + attribute_map_t::iterator iter = mAttributes.find(canonical_name); + return (iter == mAttributes.end()) ? false : true; } void LLXmlTreeNode::addAttribute(const std::string& name, const std::string& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - const std::string *newstr = new std::string(value); - mAttributes[canonical_name] = newstr; // insert + copy + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + const std::string *newstr = new std::string(value); + mAttributes[canonical_name] = newstr; // insert + copy } -LLXmlTreeNode* LLXmlTreeNode::getFirstChild() +LLXmlTreeNode* LLXmlTreeNode::getFirstChild() { - mChildrenIter = mChildren.begin(); - return getNextChild(); + mChildrenIter = mChildren.begin(); + return getNextChild(); } -LLXmlTreeNode* LLXmlTreeNode::getNextChild() +LLXmlTreeNode* LLXmlTreeNode::getNextChild() { - if (mChildrenIter == mChildren.end()) - return 0; - else - return *mChildrenIter++; + if (mChildrenIter == mChildren.end()) + return 0; + else + return *mChildrenIter++; } LLXmlTreeNode* LLXmlTreeNode::getChildByName(const std::string& name) { - LLStdStringHandle tableptr = mTree->mNodeNames.checkString(name); - mChildMapIter = mChildMap.lower_bound(tableptr); - mChildMapEndIter = mChildMap.upper_bound(tableptr); - return getNextNamedChild(); + LLStdStringHandle tableptr = mTree->mNodeNames.checkString(name); + mChildMapIter = mChildMap.lower_bound(tableptr); + mChildMapEndIter = mChildMap.upper_bound(tableptr); + return getNextNamedChild(); } LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild() { - if (mChildMapIter == mChildMapEndIter) - return NULL; - else - return (mChildMapIter++)->second; + if (mChildMapIter == mChildMapEndIter) + return NULL; + else + return (mChildMapIter++)->second; } void LLXmlTreeNode::appendContents(const std::string& str) { - mContents.append( str ); + mContents.append( str ); } void LLXmlTreeNode::addChild(LLXmlTreeNode* child) { - llassert( child ); - mChildren.push_back( child ); + llassert( child ); + mChildren.push_back( child ); + + // Add a name mapping to this node + LLStdStringHandle tableptr = mTree->mNodeNames.insert(child->mName); + mChildMap.insert( child_map_t::value_type(tableptr, child)); - // Add a name mapping to this node - LLStdStringHandle tableptr = mTree->mNodeNames.insert(child->mName); - mChildMap.insert( child_map_t::value_type(tableptr, child)); - - child->mParent = this; + child->mParent = this; } ////////////////////////////////////////////////////////////// @@ -201,110 +201,110 @@ void LLXmlTreeNode::addChild(LLXmlTreeNode* child) BOOL LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, BOOL& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToBOOL( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToBOOL( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeU8(LLStdStringHandle canonical_name, U8& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToU8( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToU8( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToS8( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToS8( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeS16(LLStdStringHandle canonical_name, S16& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToS16( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToS16( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToU16( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToU16( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeU32(LLStdStringHandle canonical_name, U32& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToU32( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToU32( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToS32( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToS32( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeF32(LLStdStringHandle canonical_name, F32& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToF32( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToF32( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& value) { - const std::string *s = getAttribute( canonical_name ); - return s && LLStringUtil::convertToF64( *s, value ); + const std::string *s = getAttribute( canonical_name ); + return s && LLStringUtil::convertToF64( *s, value ); } BOOL LLXmlTreeNode::getFastAttributeColor(LLStdStringHandle canonical_name, LLColor4& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLColor4::parseColor(*s, &value) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLColor4::parseColor(*s, &value) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name, LLColor4& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLColor4::parseColor4(*s, &value) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLColor4::parseColor4(*s, &value) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeColor4U(LLStdStringHandle canonical_name, LLColor4U& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLColor4U::parseColor4U(*s, &value ) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLColor4U::parseColor4U(*s, &value ) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name, LLVector3& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLVector3::parseVector3(*s, &value ) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLVector3::parseVector3(*s, &value ) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeVector3d(LLStdStringHandle canonical_name, LLVector3d& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLVector3d::parseVector3d(*s, &value ) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLVector3d::parseVector3d(*s, &value ) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name, LLQuaternion& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLQuaternion::parseQuat(*s, &value ) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLQuaternion::parseQuat(*s, &value ) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeUUID(LLStdStringHandle canonical_name, LLUUID& value) { - const std::string *s = getAttribute( canonical_name ); - return s ? LLUUID::parseUUID(*s, &value ) : FALSE; + const std::string *s = getAttribute( canonical_name ); + return s ? LLUUID::parseUUID(*s, &value ) : FALSE; } BOOL LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, std::string& value) { - const std::string *s = getAttribute( canonical_name ); - if( !s ) - { - return FALSE; - } + const std::string *s = getAttribute( canonical_name ); + if( !s ) + { + return FALSE; + } - value = *s; - return TRUE; + value = *s; + return TRUE; } @@ -312,104 +312,104 @@ BOOL LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, std BOOL LLXmlTreeNode::getAttributeBOOL(const std::string& name, BOOL& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeBOOL(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeBOOL(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeU8(const std::string& name, U8& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeU8(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeU8(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeS8(const std::string& name, S8& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeS8(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeS8(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeS16(const std::string& name, S16& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeS16(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeS16(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeU16(const std::string& name, U16& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeU16(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeU16(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeU32(const std::string& name, U32& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeU32(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeU32(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeS32(const std::string& name, S32& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeS32(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeS32(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeF32(const std::string& name, F32& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeF32(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeF32(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeF64(const std::string& name, F64& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeF64(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeF64(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeColor(const std::string& name, LLColor4& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeColor(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeColor(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeColor4(const std::string& name, LLColor4& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeColor4(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeColor4(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeColor4U(const std::string& name, LLColor4U& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeColor4U(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeColor4U(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeVector3(const std::string& name, LLVector3& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeVector3(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeVector3(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeVector3d(const std::string& name, LLVector3d& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeVector3d(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeVector3d(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeQuat(const std::string& name, LLQuaternion& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeQuat(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeQuat(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeUUID(const std::string& name, LLUUID& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeUUID(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeUUID(canonical_name, value); } BOOL LLXmlTreeNode::getAttributeString(const std::string& name, std::string& value) { - LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); - return getFastAttributeString(canonical_name, value); + LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name ); + return getFastAttributeString(canonical_name, value); } /* @@ -417,278 +417,278 @@ BOOL LLXmlTreeNode::getAttributeString(const std::string& name, std::string& val "The quick brown fox\n Jumps over the lazy dog" 1. HTML paragraph format: - <message> - <p>The quick brown fox</p> - <p> Jumps over the lazy dog</p> - </message> + <message> + <p>The quick brown fox</p> + <p> Jumps over the lazy dog</p> + </message> 2. Each quoted section -> paragraph: - <message> - "The quick brown fox" - " Jumps over the lazy dog" - </message> + <message> + "The quick brown fox" + " Jumps over the lazy dog" + </message> 3. Literal text with beginning and trailing whitespace removed: - <message> + <message> The quick brown fox Jumps over the lazy dog - </message> - + </message> + */ std::string LLXmlTreeNode::getTextContents() { - std::string msg; - LLXmlTreeNode* p = getChildByName("p"); - if (p) - { - // Case 1: node has <p>text</p> tags - while (p) - { - msg += p->getContents() + "\n"; - p = getNextNamedChild(); - } - } - else - { - std::string::size_type n = mContents.find_first_not_of(" \t\n"); - if (n != std::string::npos && mContents[n] == '\"') - { - // Case 2: node has quoted text - S32 num_lines = 0; - while(1) - { - // mContents[n] == '"' - ++n; - std::string::size_type t = n; - std::string::size_type m = 0; - // fix-up escaped characters - while(1) - { - m = mContents.find_first_of("\\\"", t); // find first \ or " - if ((m == std::string::npos) || (mContents[m] == '\"')) - { - break; - } - mContents.erase(m,1); - t = m+1; - } - if (m == std::string::npos) - { - break; - } - // mContents[m] == '"' - num_lines++; - msg += mContents.substr(n,m-n) + "\n"; - n = mContents.find_first_of("\"", m+1); - if (n == std::string::npos) - { - if (num_lines == 1) - { - msg.erase(msg.size()-1); // remove "\n" if only one line - } - break; - } - } - } - else - { - // Case 3: node has embedded text (beginning and trailing whitespace trimmed) - msg = mContents; - } - } - return msg; -} - + std::string msg; + LLXmlTreeNode* p = getChildByName("p"); + if (p) + { + // Case 1: node has <p>text</p> tags + while (p) + { + msg += p->getContents() + "\n"; + p = getNextNamedChild(); + } + } + else + { + std::string::size_type n = mContents.find_first_not_of(" \t\n"); + if (n != std::string::npos && mContents[n] == '\"') + { + // Case 2: node has quoted text + S32 num_lines = 0; + while(1) + { + // mContents[n] == '"' + ++n; + std::string::size_type t = n; + std::string::size_type m = 0; + // fix-up escaped characters + while(1) + { + m = mContents.find_first_of("\\\"", t); // find first \ or " + if ((m == std::string::npos) || (mContents[m] == '\"')) + { + break; + } + mContents.erase(m,1); + t = m+1; + } + if (m == std::string::npos) + { + break; + } + // mContents[m] == '"' + num_lines++; + msg += mContents.substr(n,m-n) + "\n"; + n = mContents.find_first_of("\"", m+1); + if (n == std::string::npos) + { + if (num_lines == 1) + { + msg.erase(msg.size()-1); // remove "\n" if only one line + } + break; + } + } + } + else + { + // Case 3: node has embedded text (beginning and trailing whitespace trimmed) + msg = mContents; + } + } + return msg; +} + ////////////////////////////////////////////////////////////// // LLXmlTreeParser -LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree) - : mTree(tree), - mRoot( NULL ), - mCurrent( NULL ), - mDump( FALSE ), - mKeepContents(FALSE) +LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree) + : mTree(tree), + mRoot( NULL ), + mCurrent( NULL ), + mDump( FALSE ), + mKeepContents(FALSE) { } -LLXmlTreeParser::~LLXmlTreeParser() +LLXmlTreeParser::~LLXmlTreeParser() { } BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents) { - llassert( !mRoot ); - llassert( !mCurrent ); + llassert( !mRoot ); + llassert( !mCurrent ); - mKeepContents = keep_contents; + mKeepContents = keep_contents; - BOOL success = LLXmlParser::parseFile(path); + BOOL success = LLXmlParser::parseFile(path); - *root = mRoot; - mRoot = NULL; + *root = mRoot; + mRoot = NULL; - if( success ) - { - llassert( !mCurrent ); - } - mCurrent = NULL; - - return success; + if( success ) + { + llassert( !mCurrent ); + } + mCurrent = NULL; + + return success; } const std::string& LLXmlTreeParser::tabs() { - static std::string s; - s = ""; - S32 num_tabs = getDepth() - 1; - for( S32 i = 0; i < num_tabs; i++) - { - s += " "; - } - return s; -} - -void LLXmlTreeParser::startElement(const char* name, const char **atts) -{ - if( mDump ) - { - LL_INFOS() << tabs() << "startElement " << name << LL_ENDL; - - S32 i = 0; - while( atts[i] && atts[i+1] ) - { - LL_INFOS() << tabs() << "attribute: " << atts[i] << "=" << atts[i+1] << LL_ENDL; - i += 2; - } - } - - LLXmlTreeNode* child = CreateXmlTreeNode( std::string(name), mCurrent ); - - S32 i = 0; - while( atts[i] && atts[i+1] ) - { - child->addAttribute( atts[i], atts[i+1] ); - i += 2; - } - - if( mCurrent ) - { - mCurrent->addChild( child ); - - } - else - { - llassert( !mRoot ); - mRoot = child; - } - mCurrent = child; + static std::string s; + s = ""; + S32 num_tabs = getDepth() - 1; + for( S32 i = 0; i < num_tabs; i++) + { + s += " "; + } + return s; +} + +void LLXmlTreeParser::startElement(const char* name, const char **atts) +{ + if( mDump ) + { + LL_INFOS() << tabs() << "startElement " << name << LL_ENDL; + + S32 i = 0; + while( atts[i] && atts[i+1] ) + { + LL_INFOS() << tabs() << "attribute: " << atts[i] << "=" << atts[i+1] << LL_ENDL; + i += 2; + } + } + + LLXmlTreeNode* child = CreateXmlTreeNode( std::string(name), mCurrent ); + + S32 i = 0; + while( atts[i] && atts[i+1] ) + { + child->addAttribute( atts[i], atts[i+1] ); + i += 2; + } + + if( mCurrent ) + { + mCurrent->addChild( child ); + + } + else + { + llassert( !mRoot ); + mRoot = child; + } + mCurrent = child; } LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent) { - return new LLXmlTreeNode(name, parent, mTree); + return new LLXmlTreeNode(name, parent, mTree); } -void LLXmlTreeParser::endElement(const char* name) +void LLXmlTreeParser::endElement(const char* name) { - if( mDump ) - { - LL_INFOS() << tabs() << "endElement " << name << LL_ENDL; - } + if( mDump ) + { + LL_INFOS() << tabs() << "endElement " << name << LL_ENDL; + } - if( !mCurrent->mContents.empty() ) - { - LLStringUtil::trim(mCurrent->mContents); - LLStringUtil::removeCRLF(mCurrent->mContents); - } + if( !mCurrent->mContents.empty() ) + { + LLStringUtil::trim(mCurrent->mContents); + LLStringUtil::removeCRLF(mCurrent->mContents); + } - mCurrent = mCurrent->getParent(); + mCurrent = mCurrent->getParent(); } -void LLXmlTreeParser::characterData(const char *s, int len) +void LLXmlTreeParser::characterData(const char *s, int len) { - std::string str; - if (s) str = std::string(s, len); - if( mDump ) - { - LL_INFOS() << tabs() << "CharacterData " << str << LL_ENDL; - } + std::string str; + if (s) str = std::string(s, len); + if( mDump ) + { + LL_INFOS() << tabs() << "CharacterData " << str << LL_ENDL; + } - if (mKeepContents) - { - mCurrent->appendContents( str ); - } + if (mKeepContents) + { + mCurrent->appendContents( str ); + } } void LLXmlTreeParser::processingInstruction(const char *target, const char *data) { - if( mDump ) - { - LL_INFOS() << tabs() << "processingInstruction " << data << LL_ENDL; - } + if( mDump ) + { + LL_INFOS() << tabs() << "processingInstruction " << data << LL_ENDL; + } } void LLXmlTreeParser::comment(const char *data) { - if( mDump ) - { - LL_INFOS() << tabs() << "comment " << data << LL_ENDL; - } + if( mDump ) + { + LL_INFOS() << tabs() << "comment " << data << LL_ENDL; + } } void LLXmlTreeParser::startCdataSection() { - if( mDump ) - { - LL_INFOS() << tabs() << "startCdataSection" << LL_ENDL; - } + if( mDump ) + { + LL_INFOS() << tabs() << "startCdataSection" << LL_ENDL; + } } void LLXmlTreeParser::endCdataSection() { - if( mDump ) - { - LL_INFOS() << tabs() << "endCdataSection" << LL_ENDL; - } + if( mDump ) + { + LL_INFOS() << tabs() << "endCdataSection" << LL_ENDL; + } } void LLXmlTreeParser::defaultData(const char *s, int len) { - if( mDump ) - { - std::string str; - if (s) str = std::string(s, len); - LL_INFOS() << tabs() << "defaultData " << str << LL_ENDL; - } + if( mDump ) + { + std::string str; + if (s) str = std::string(s, len); + LL_INFOS() << tabs() << "defaultData " << str << LL_ENDL; + } } void LLXmlTreeParser::unparsedEntityDecl( - const char* entity_name, - const char* base, - const char* system_id, - const char* public_id, - const char* notation_name) -{ - if( mDump ) - { - LL_INFOS() << tabs() << "unparsed entity:" << LL_ENDL; - LL_INFOS() << tabs() << " entityName " << entity_name << LL_ENDL; - LL_INFOS() << tabs() << " base " << base << LL_ENDL; - LL_INFOS() << tabs() << " systemId " << system_id << LL_ENDL; - LL_INFOS() << tabs() << " publicId " << public_id << LL_ENDL; - LL_INFOS() << tabs() << " notationName " << notation_name<< LL_ENDL; - } + const char* entity_name, + const char* base, + const char* system_id, + const char* public_id, + const char* notation_name) +{ + if( mDump ) + { + LL_INFOS() << tabs() << "unparsed entity:" << LL_ENDL; + LL_INFOS() << tabs() << " entityName " << entity_name << LL_ENDL; + LL_INFOS() << tabs() << " base " << base << LL_ENDL; + LL_INFOS() << tabs() << " systemId " << system_id << LL_ENDL; + LL_INFOS() << tabs() << " publicId " << public_id << LL_ENDL; + LL_INFOS() << tabs() << " notationName " << notation_name<< LL_ENDL; + } } void test_llxmltree() { - LLXmlTree tree; - BOOL success = tree.parseFile( "test.xml" ); - if( success ) - { - tree.dump(); - } + LLXmlTree tree; + BOOL success = tree.parseFile( "test.xml" ); + if( success ) + { + tree.dump(); + } } diff --git a/indra/llxml/llxmltree.h b/indra/llxml/llxmltree.h index 3e425c3870..0f7361c554 100644 --- a/indra/llxml/llxmltree.h +++ b/indra/llxml/llxmltree.h @@ -1,4 +1,4 @@ -/** +/** * @file llxmltree.h * @author Aaron Yonas, Richard Nelson * @brief LLXmlTree class definition @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -48,34 +48,34 @@ class LLXmlTreeParser; class LLXmlTree { - friend class LLXmlTreeNode; - + friend class LLXmlTreeNode; + public: - LLXmlTree(); - virtual ~LLXmlTree(); - void cleanup(); + LLXmlTree(); + virtual ~LLXmlTree(); + void cleanup(); + + virtual BOOL parseFile(const std::string &path, BOOL keep_contents = TRUE); - virtual BOOL parseFile(const std::string &path, BOOL keep_contents = TRUE); + LLXmlTreeNode* getRoot() { return mRoot; } - LLXmlTreeNode* getRoot() { return mRoot; } + void dump(); + void dumpNode( LLXmlTreeNode* node, const std::string& prefix ); - void dump(); - void dumpNode( LLXmlTreeNode* node, const std::string& prefix ); + static LLStdStringHandle addAttributeString( const std::string& name) + { + return sAttributeKeys.addString( name ); + } - static LLStdStringHandle addAttributeString( const std::string& name) - { - return sAttributeKeys.addString( name ); - } - public: - // global - static LLStdStringTable sAttributeKeys; - + // global + static LLStdStringTable sAttributeKeys; + protected: - LLXmlTreeNode* mRoot; + LLXmlTreeNode* mRoot; - // local - LLStdStringTable mNodeNames; + // local + LLStdStringTable mNodeNames; }; ////////////////////////////////////////////////////////////// @@ -83,111 +83,111 @@ protected: class LLXmlTreeNode { - friend class LLXmlTree; - friend class LLXmlTreeParser; + friend class LLXmlTree; + friend class LLXmlTreeParser; protected: - // Protected since nodes are only created and destroyed by friend classes and other LLXmlTreeNodes - LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree ); - + // Protected since nodes are only created and destroyed by friend classes and other LLXmlTreeNodes + LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree ); + public: - virtual ~LLXmlTreeNode(); - - const std::string& getName() - { - return mName; - } - BOOL hasName( const std::string& name ) - { - return mName == name; - } - - BOOL hasAttribute( const std::string& name ); - - // Fast versions use cannonical_name handlee to entru in LLXmlTree::sAttributeKeys string table - BOOL getFastAttributeBOOL( LLStdStringHandle cannonical_name, BOOL& value ); - BOOL getFastAttributeU8( LLStdStringHandle cannonical_name, U8& value ); - BOOL getFastAttributeS8( LLStdStringHandle cannonical_name, S8& value ); - BOOL getFastAttributeU16( LLStdStringHandle cannonical_name, U16& value ); - BOOL getFastAttributeS16( LLStdStringHandle cannonical_name, S16& value ); - BOOL getFastAttributeU32( LLStdStringHandle cannonical_name, U32& value ); - BOOL getFastAttributeS32( LLStdStringHandle cannonical_name, S32& value ); - BOOL getFastAttributeF32( LLStdStringHandle cannonical_name, F32& value ); - BOOL getFastAttributeF64( LLStdStringHandle cannonical_name, F64& value ); - BOOL getFastAttributeColor( LLStdStringHandle cannonical_name, LLColor4& value ); - BOOL getFastAttributeColor4( LLStdStringHandle cannonical_name, LLColor4& value ); - BOOL getFastAttributeColor4U( LLStdStringHandle cannonical_name, LLColor4U& value ); - BOOL getFastAttributeVector3( LLStdStringHandle cannonical_name, LLVector3& value ); - BOOL getFastAttributeVector3d( LLStdStringHandle cannonical_name, LLVector3d& value ); - BOOL getFastAttributeQuat( LLStdStringHandle cannonical_name, LLQuaternion& value ); - BOOL getFastAttributeUUID( LLStdStringHandle cannonical_name, LLUUID& value ); - BOOL getFastAttributeString( LLStdStringHandle cannonical_name, std::string& value ); - - // Normal versions find 'name' in LLXmlTree::sAttributeKeys then call fast versions - virtual BOOL getAttributeBOOL( const std::string& name, BOOL& value ); - virtual BOOL getAttributeU8( const std::string& name, U8& value ); - virtual BOOL getAttributeS8( const std::string& name, S8& value ); - virtual BOOL getAttributeU16( const std::string& name, U16& value ); - virtual BOOL getAttributeS16( const std::string& name, S16& value ); - virtual BOOL getAttributeU32( const std::string& name, U32& value ); - virtual BOOL getAttributeS32( const std::string& name, S32& value ); - virtual BOOL getAttributeF32( const std::string& name, F32& value ); - virtual BOOL getAttributeF64( const std::string& name, F64& value ); - virtual BOOL getAttributeColor( const std::string& name, LLColor4& value ); - virtual BOOL getAttributeColor4( const std::string& name, LLColor4& value ); - virtual BOOL getAttributeColor4U( const std::string& name, LLColor4U& value ); - virtual BOOL getAttributeVector3( const std::string& name, LLVector3& value ); - virtual BOOL getAttributeVector3d( const std::string& name, LLVector3d& value ); - virtual BOOL getAttributeQuat( const std::string& name, LLQuaternion& value ); - virtual BOOL getAttributeUUID( const std::string& name, LLUUID& value ); - virtual BOOL getAttributeString( const std::string& name, std::string& value ); - - const std::string& getContents() - { - return mContents; - } - std::string getTextContents(); - - LLXmlTreeNode* getParent() { return mParent; } - LLXmlTreeNode* getFirstChild(); - LLXmlTreeNode* getNextChild(); - S32 getChildCount() { return (S32)mChildren.size(); } - LLXmlTreeNode* getChildByName( const std::string& name ); // returns first child with name, NULL if none - LLXmlTreeNode* getNextNamedChild(); // returns next child with name, NULL if none + virtual ~LLXmlTreeNode(); + + const std::string& getName() + { + return mName; + } + BOOL hasName( const std::string& name ) + { + return mName == name; + } + + BOOL hasAttribute( const std::string& name ); + + // Fast versions use cannonical_name handlee to entru in LLXmlTree::sAttributeKeys string table + BOOL getFastAttributeBOOL( LLStdStringHandle cannonical_name, BOOL& value ); + BOOL getFastAttributeU8( LLStdStringHandle cannonical_name, U8& value ); + BOOL getFastAttributeS8( LLStdStringHandle cannonical_name, S8& value ); + BOOL getFastAttributeU16( LLStdStringHandle cannonical_name, U16& value ); + BOOL getFastAttributeS16( LLStdStringHandle cannonical_name, S16& value ); + BOOL getFastAttributeU32( LLStdStringHandle cannonical_name, U32& value ); + BOOL getFastAttributeS32( LLStdStringHandle cannonical_name, S32& value ); + BOOL getFastAttributeF32( LLStdStringHandle cannonical_name, F32& value ); + BOOL getFastAttributeF64( LLStdStringHandle cannonical_name, F64& value ); + BOOL getFastAttributeColor( LLStdStringHandle cannonical_name, LLColor4& value ); + BOOL getFastAttributeColor4( LLStdStringHandle cannonical_name, LLColor4& value ); + BOOL getFastAttributeColor4U( LLStdStringHandle cannonical_name, LLColor4U& value ); + BOOL getFastAttributeVector3( LLStdStringHandle cannonical_name, LLVector3& value ); + BOOL getFastAttributeVector3d( LLStdStringHandle cannonical_name, LLVector3d& value ); + BOOL getFastAttributeQuat( LLStdStringHandle cannonical_name, LLQuaternion& value ); + BOOL getFastAttributeUUID( LLStdStringHandle cannonical_name, LLUUID& value ); + BOOL getFastAttributeString( LLStdStringHandle cannonical_name, std::string& value ); + + // Normal versions find 'name' in LLXmlTree::sAttributeKeys then call fast versions + virtual BOOL getAttributeBOOL( const std::string& name, BOOL& value ); + virtual BOOL getAttributeU8( const std::string& name, U8& value ); + virtual BOOL getAttributeS8( const std::string& name, S8& value ); + virtual BOOL getAttributeU16( const std::string& name, U16& value ); + virtual BOOL getAttributeS16( const std::string& name, S16& value ); + virtual BOOL getAttributeU32( const std::string& name, U32& value ); + virtual BOOL getAttributeS32( const std::string& name, S32& value ); + virtual BOOL getAttributeF32( const std::string& name, F32& value ); + virtual BOOL getAttributeF64( const std::string& name, F64& value ); + virtual BOOL getAttributeColor( const std::string& name, LLColor4& value ); + virtual BOOL getAttributeColor4( const std::string& name, LLColor4& value ); + virtual BOOL getAttributeColor4U( const std::string& name, LLColor4U& value ); + virtual BOOL getAttributeVector3( const std::string& name, LLVector3& value ); + virtual BOOL getAttributeVector3d( const std::string& name, LLVector3d& value ); + virtual BOOL getAttributeQuat( const std::string& name, LLQuaternion& value ); + virtual BOOL getAttributeUUID( const std::string& name, LLUUID& value ); + virtual BOOL getAttributeString( const std::string& name, std::string& value ); + + const std::string& getContents() + { + return mContents; + } + std::string getTextContents(); + + LLXmlTreeNode* getParent() { return mParent; } + LLXmlTreeNode* getFirstChild(); + LLXmlTreeNode* getNextChild(); + S32 getChildCount() { return (S32)mChildren.size(); } + LLXmlTreeNode* getChildByName( const std::string& name ); // returns first child with name, NULL if none + LLXmlTreeNode* getNextNamedChild(); // returns next child with name, NULL if none protected: - const std::string* getAttribute( LLStdStringHandle name) - { - attribute_map_t::iterator iter = mAttributes.find(name); - return (iter == mAttributes.end()) ? 0 : iter->second; - } + const std::string* getAttribute( LLStdStringHandle name) + { + attribute_map_t::iterator iter = mAttributes.find(name); + return (iter == mAttributes.end()) ? 0 : iter->second; + } private: - void addAttribute( const std::string& name, const std::string& value ); - void appendContents( const std::string& str ); - void addChild( LLXmlTreeNode* child ); + void addAttribute( const std::string& name, const std::string& value ); + void appendContents( const std::string& str ); + void addChild( LLXmlTreeNode* child ); - void dump( const std::string& prefix ); + void dump( const std::string& prefix ); protected: - typedef std::map<LLStdStringHandle, const std::string*> attribute_map_t; - attribute_map_t mAttributes; + typedef std::map<LLStdStringHandle, const std::string*> attribute_map_t; + attribute_map_t mAttributes; private: - std::string mName; - std::string mContents; - - typedef std::vector<class LLXmlTreeNode *> children_t; - children_t mChildren; - children_t::iterator mChildrenIter; - - typedef std::multimap<LLStdStringHandle, LLXmlTreeNode *> child_map_t; - child_map_t mChildMap; // for fast name lookups - child_map_t::iterator mChildMapIter; - child_map_t::iterator mChildMapEndIter; - - LLXmlTreeNode* mParent; - LLXmlTree* mTree; + std::string mName; + std::string mContents; + + typedef std::vector<class LLXmlTreeNode *> children_t; + children_t mChildren; + children_t::iterator mChildrenIter; + + typedef std::multimap<LLStdStringHandle, LLXmlTreeNode *> child_map_t; + child_map_t mChildMap; // for fast name lookups + child_map_t::iterator mChildMapIter; + child_map_t::iterator mChildMapEndIter; + + LLXmlTreeNode* mParent; + LLXmlTree* mTree; }; ////////////////////////////////////////////////////////////// @@ -196,39 +196,39 @@ private: class LLXmlTreeParser : public LLXmlParser { public: - LLXmlTreeParser(LLXmlTree* tree); - virtual ~LLXmlTreeParser(); + LLXmlTreeParser(LLXmlTree* tree); + virtual ~LLXmlTreeParser(); - BOOL parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents ); + BOOL parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents ); protected: - const std::string& tabs(); - - // Overrides from LLXmlParser - virtual void startElement(const char *name, const char **attributes); - virtual void endElement(const char *name); - virtual void characterData(const char *s, int len); - virtual void processingInstruction(const char *target, const char *data); - virtual void comment(const char *data); - virtual void startCdataSection(); - virtual void endCdataSection(); - virtual void defaultData(const char *s, int len); - virtual void unparsedEntityDecl( - const char* entity_name, - const char* base, - const char* system_id, - const char* public_id, - const char* notation_name); - - //template method pattern - virtual LLXmlTreeNode* CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent); + const std::string& tabs(); + + // Overrides from LLXmlParser + virtual void startElement(const char *name, const char **attributes); + virtual void endElement(const char *name); + virtual void characterData(const char *s, int len); + virtual void processingInstruction(const char *target, const char *data); + virtual void comment(const char *data); + virtual void startCdataSection(); + virtual void endCdataSection(); + virtual void defaultData(const char *s, int len); + virtual void unparsedEntityDecl( + const char* entity_name, + const char* base, + const char* system_id, + const char* public_id, + const char* notation_name); + + //template method pattern + virtual LLXmlTreeNode* CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent); protected: - LLXmlTree* mTree; - LLXmlTreeNode* mRoot; - LLXmlTreeNode* mCurrent; - BOOL mDump; // Dump parse tree to LL_INFOS() as it is read. - BOOL mKeepContents; + LLXmlTree* mTree; + LLXmlTreeNode* mRoot; + LLXmlTreeNode* mCurrent; + BOOL mDump; // Dump parse tree to LL_INFOS() as it is read. + BOOL mKeepContents; }; #endif // LL_LLXMLTREE_H diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp index f7e43d6def..f5f8b285f7 100644 --- a/indra/llxml/tests/llcontrol_test.cpp +++ b/indra/llxml/tests/llcontrol_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llcontrol_tut.cpp * @date February 2008 * @brief control group unit tests @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,117 +38,117 @@ namespace tut { - struct control_group - { - std::unique_ptr<LLControlGroup> mCG; - std::string mTestConfigDir; - std::string mTestConfigFile; - std::vector<std::string> mCleanups; - static bool mListenerFired; - control_group() - { - mCG.reset(new LLControlGroup("foo")); - LLUUID random; - random.generate(); - // generate temp dir - mTestConfigDir = STRINGIZE(LLFile::tmpdir() << "llcontrol-test-" << random << "/"); - mTestConfigFile = mTestConfigDir + "settings.xml"; - LLFile::mkdir(mTestConfigDir); - LLSD config; - config["TestSetting"]["Comment"] = "Dummy setting used for testing"; - config["TestSetting"]["Persist"] = 1; - config["TestSetting"]["Type"] = "U32"; - config["TestSetting"]["Value"] = 12; - writeSettingsFile(config); - } - ~control_group() - { - //Remove test files - for (auto filename : mCleanups) - { - LLFile::remove(filename); - } - LLFile::remove(mTestConfigFile); - LLFile::rmdir(mTestConfigDir); - } - void writeSettingsFile(const LLSD& config) - { - llofstream file(mTestConfigFile.c_str()); - if (file.is_open()) - { - LLSDSerialize::toPrettyXML(config, file); - } - file.close(); - } - static bool handleListenerTest() - { - control_group::mListenerFired = true; - return true; - } - }; + struct control_group + { + std::unique_ptr<LLControlGroup> mCG; + std::string mTestConfigDir; + std::string mTestConfigFile; + std::vector<std::string> mCleanups; + static bool mListenerFired; + control_group() + { + mCG.reset(new LLControlGroup("foo")); + LLUUID random; + random.generate(); + // generate temp dir + mTestConfigDir = STRINGIZE(LLFile::tmpdir() << "llcontrol-test-" << random << "/"); + mTestConfigFile = mTestConfigDir + "settings.xml"; + LLFile::mkdir(mTestConfigDir); + LLSD config; + config["TestSetting"]["Comment"] = "Dummy setting used for testing"; + config["TestSetting"]["Persist"] = 1; + config["TestSetting"]["Type"] = "U32"; + config["TestSetting"]["Value"] = 12; + writeSettingsFile(config); + } + ~control_group() + { + //Remove test files + for (auto filename : mCleanups) + { + LLFile::remove(filename); + } + LLFile::remove(mTestConfigFile); + LLFile::rmdir(mTestConfigDir); + } + void writeSettingsFile(const LLSD& config) + { + llofstream file(mTestConfigFile.c_str()); + if (file.is_open()) + { + LLSDSerialize::toPrettyXML(config, file); + } + file.close(); + } + static bool handleListenerTest() + { + control_group::mListenerFired = true; + return true; + } + }; + + bool control_group::mListenerFired = false; - bool control_group::mListenerFired = false; + typedef test_group<control_group> control_group_test; + typedef control_group_test::object control_group_t; + control_group_test tut_control_group("control_group"); - typedef test_group<control_group> control_group_test; - typedef control_group_test::object control_group_t; - control_group_test tut_control_group("control_group"); + //load settings from files - LLSD + template<> template<> + void control_group_t::test<1>() + { + int results = mCG->loadFromFile(mTestConfigFile.c_str()); + ensure("number of settings", (results == 1)); + ensure("value of setting", (mCG->getU32("TestSetting") == 12)); + } - //load settings from files - LLSD - template<> template<> - void control_group_t::test<1>() - { - int results = mCG->loadFromFile(mTestConfigFile.c_str()); - ensure("number of settings", (results == 1)); - ensure("value of setting", (mCG->getU32("TestSetting") == 12)); - } + //save settings to files + template<> template<> + void control_group_t::test<2>() + { + int results = mCG->loadFromFile(mTestConfigFile.c_str()); + mCG->setU32("TestSetting", 13); + ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13); + LLControlGroup test_cg("foo2"); + std::string temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml"); + mCleanups.push_back(temp_test_file); + mCG->saveToFile(temp_test_file.c_str(), TRUE); + results = test_cg.loadFromFile(temp_test_file.c_str()); + ensure("number of changed settings loaded", (results == 1)); + ensure("value of changed settings loaded", (test_cg.getU32("TestSetting") == 13)); + } - //save settings to files - template<> template<> - void control_group_t::test<2>() - { - int results = mCG->loadFromFile(mTestConfigFile.c_str()); - mCG->setU32("TestSetting", 13); - ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13); - LLControlGroup test_cg("foo2"); - std::string temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml"); - mCleanups.push_back(temp_test_file); - mCG->saveToFile(temp_test_file.c_str(), TRUE); - results = test_cg.loadFromFile(temp_test_file.c_str()); - ensure("number of changed settings loaded", (results == 1)); - ensure("value of changed settings loaded", (test_cg.getU32("TestSetting") == 13)); - } - - //priorities - template<> template<> - void control_group_t::test<3>() - { - // Pass default_values = true. This tells loadFromFile() we're loading - // a default settings file that declares variables, rather than a user - // settings file. When loadFromFile() encounters an unrecognized user - // settings variable, it forcibly preserves it (CHOP-962). - int results = mCG->loadFromFile(mTestConfigFile.c_str(), true); - LLControlVariable* control = mCG->getControl("TestSetting"); - LLSD new_value = 13; - control->setValue(new_value, FALSE); - ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13); - LLControlGroup test_cg("foo3"); - std::string temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml"); - mCleanups.push_back(temp_test_file); - mCG->saveToFile(temp_test_file.c_str(), TRUE); - results = test_cg.loadFromFile(temp_test_file.c_str()); - //If we haven't changed any settings, then we shouldn't have any settings to load - ensure("number of non-persisted changed settings loaded", (results == 0)); - } + //priorities + template<> template<> + void control_group_t::test<3>() + { + // Pass default_values = true. This tells loadFromFile() we're loading + // a default settings file that declares variables, rather than a user + // settings file. When loadFromFile() encounters an unrecognized user + // settings variable, it forcibly preserves it (CHOP-962). + int results = mCG->loadFromFile(mTestConfigFile.c_str(), true); + LLControlVariable* control = mCG->getControl("TestSetting"); + LLSD new_value = 13; + control->setValue(new_value, FALSE); + ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13); + LLControlGroup test_cg("foo3"); + std::string temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml"); + mCleanups.push_back(temp_test_file); + mCG->saveToFile(temp_test_file.c_str(), TRUE); + results = test_cg.loadFromFile(temp_test_file.c_str()); + //If we haven't changed any settings, then we shouldn't have any settings to load + ensure("number of non-persisted changed settings loaded", (results == 0)); + } - //listeners - template<> template<> - void control_group_t::test<4>() - { - int results = mCG->loadFromFile(mTestConfigFile.c_str()); - ensure("number of settings", (results == 1)); - mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest)); - mCG->setU32("TestSetting", 13); - ensure("listener fired on changed setting", mListenerFired); - } + //listeners + template<> template<> + void control_group_t::test<4>() + { + int results = mCG->loadFromFile(mTestConfigFile.c_str()); + ensure("number of settings", (results == 1)); + mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest)); + mCG->setU32("TestSetting", 13); + ensure("listener fired on changed setting", mListenerFired); + } } |