From ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Thu, 30 Apr 2009 13:04:20 -0500 Subject: Second Life viewer sources 1.23.0-RC --- linden/indra/llxml/CMakeLists.txt | 1 + linden/indra/llxml/llcontrol.cpp | 56 +++++++-- linden/indra/llxml/llcontrol.h | 16 ++- linden/indra/llxml/llcontrolgroupreader.h | 74 ++++++++++++ linden/indra/llxml/llxmlnode.cpp | 188 +++++++++++++++++++++++++----- linden/indra/llxml/llxmlnode.h | 29 +++-- linden/indra/llxml/llxmlparser.cpp | 3 +- linden/indra/llxml/llxmlparser.h | 3 +- linden/indra/llxml/llxmltree.cpp | 3 +- linden/indra/llxml/llxmltree.h | 3 +- 10 files changed, 317 insertions(+), 59 deletions(-) create mode 100644 linden/indra/llxml/llcontrolgroupreader.h (limited to 'linden/indra/llxml') diff --git a/linden/indra/llxml/CMakeLists.txt b/linden/indra/llxml/CMakeLists.txt index 9febd97..487c5b9 100644 --- a/linden/indra/llxml/CMakeLists.txt +++ b/linden/indra/llxml/CMakeLists.txt @@ -23,6 +23,7 @@ set(llxml_HEADER_FILES CMakeLists.txt llcontrol.h + llcontrolgroupreader.h llxmlnode.h llxmlparser.h llxmltree.h diff --git a/linden/indra/llxml/llcontrol.cpp b/linden/indra/llxml/llcontrol.cpp index 81c3e78..d9ed45a 100644 --- a/linden/indra/llxml/llcontrol.cpp +++ b/linden/indra/llxml/llcontrol.cpp @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -101,11 +102,12 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) LLControlVariable::LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist) + bool persist, bool hidefromsettingseditor) : mName(name), mComment(comment), mType(type), - mPersist(persist) + mPersist(persist), + mHideFromSettingsEditor(hidefromsettingseditor) { if (mPersist && mComment.empty()) { @@ -212,6 +214,11 @@ void LLControlVariable::setPersist(bool state) mPersist = state; } +void LLControlVariable::setHiddenFromSettingsEditor(bool hide) +{ + mHideFromSettingsEditor = hide; +} + void LLControlVariable::setComment(const std::string& comment) { mComment = comment; @@ -295,17 +302,27 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum) return mTypeString[typeenum]; } -BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist) +BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor) { - if(mNameTable.find(name) != mNameTable.end()) - { - llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl; - mNameTable[name]->setValue(initial_val); - return TRUE; + LLControlVariable* existing_control = getControl(name); + if (existing_control) + { + if (persist && existing_control->isType(type)) + { + // Sometimes we need to declare a control *after* it has been loaded from a settings file. + LLSD cur_value = existing_control->getValue(); // get the current value + existing_control->setDefaultValue(initial_val); // set the default to the declared value + existing_control->setValue(cur_value); // now set to the loaded value + } + else + { + llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl; + } + return TRUE; } // if not, create the control and add it to the name table - LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist); + LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor); mNameTable[name] = control; return TRUE; } @@ -1042,7 +1059,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } U32 validitems = 0; - bool persist = false; + bool persist = true; + bool hidefromsettingseditor = false; for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr) { name = (*itr).first; @@ -1053,6 +1071,18 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v persist = control_map["Persist"].asInteger(); } + // Sometimes we want to use the settings system to provide cheap persistence, but we + // don't want the settings themselves to be easily manipulated in the UI because + // doing so can cause support problems. So we have this option: + if(control_map.has("HideFromEditor")) + { + hidefromsettingseditor = control_map["HideFromEditor"].asInteger(); + } + else + { + hidefromsettingseditor = false; + } + // If the control exists just set the value from the input file. LLControlVariable* existing_control = getControl(name); if(existing_control) @@ -1066,6 +1096,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v { existing_control->setDefaultValue(control_map["Value"]); existing_control->setPersist(persist); + existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor); existing_control->setComment(control_map["Comment"].asString()); } else @@ -1089,7 +1120,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v typeStringToEnum(control_map["Type"].asString()), control_map["Value"], control_map["Comment"].asString(), - persist + persist, + hidefromsettingseditor ); } diff --git a/linden/indra/llxml/llcontrol.h b/linden/indra/llxml/llcontrol.h index 7b327ef..ba0a1c7 100644 --- a/linden/indra/llxml/llcontrol.h +++ b/linden/indra/llxml/llcontrol.h @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -38,6 +39,8 @@ #include "llstring.h" #include "llrect.h" +#include "llcontrolgroupreader.h" + #include // *NOTE: boost::visit_each<> generates warning 4675 on .net 2003 @@ -92,7 +95,8 @@ private: std::string mName; std::string mComment; eControlType mType; - bool mPersist; + bool mPersist; + bool mHideFromSettingsEditor; std::vector mValues; signal_t mSignal; @@ -100,7 +104,7 @@ private: public: LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist = true); + bool persist = true, bool hidefromsettingseditor = false); virtual ~LLControlVariable(); @@ -117,6 +121,7 @@ public: bool isDefault() { return (mValues.size() == 1); } bool isSaveValueDefault(); bool isPersisted() { return mPersist; } + bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; } LLSD get() const { return getValue(); } LLSD getValue() const { return mValues.back(); } LLSD getDefault() const { return mValues.front(); } @@ -126,6 +131,7 @@ public: void setValue(const LLSD& value, bool saved_value = TRUE); void setDefaultValue(const LLSD& value); void setPersist(bool state); + void setHiddenFromSettingsEditor(bool hide); void setComment(const std::string& comment); void firePropertyChanged() @@ -139,7 +145,7 @@ private: }; //const U32 STRING_CACHE_SIZE = 10000; -class LLControlGroup +class LLControlGroup : public LLControlGroupReader { protected: typedef std::map > ctrl_name_table_t; @@ -163,7 +169,7 @@ public: }; void applyToAll(ApplyFunctor* func); - BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist); + BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE); BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE); BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE); BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE); diff --git a/linden/indra/llxml/llcontrolgroupreader.h b/linden/indra/llxml/llcontrolgroupreader.h new file mode 100644 index 0000000..c4c04b9 --- /dev/null +++ b/linden/indra/llxml/llcontrolgroupreader.h @@ -0,0 +1,74 @@ +/** + * @file llcontrolgroupreader.h + * @brief Interface providing readonly access to LLControlGroup (intended for unit testing) + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONTROLGROUPREADER_H +#define LL_LLCONTROLGROUPREADER_H + +#include "stdtypes.h" +#include + +// Many of the types below are commented out because for the purposes of the early testing we're doing, +// we don't need them and we don't want to pull in all the machinery to support them. +// But the model is here for future unit test extensions. + +class LLControlGroupReader +{ +public: + LLControlGroupReader() {} + virtual ~LLControlGroupReader() {} + + virtual std::string getString(const std::string& name) = 0; + //virtual LLWString getWString(const std::string& name) = 0; + virtual std::string getText(const std::string& name) = 0; + //virtual LLVector3 getVector3(const std::string& name) = 0; + //virtual LLVector3d getVector3d(const std::string& name) = 0; + //virtual LLRect getRect(const std::string& name) = 0; + virtual BOOL getBOOL(const std::string& name) = 0; + virtual S32 getS32(const std::string& name) = 0; + virtual F32 getF32(const std::string& name) = 0; + virtual U32 getU32(const std::string& name) = 0; + //virtual LLSD getLLSD(const std::string& name) = 0; + + //virtual LLColor4 getColor(const std::string& name) = 0; + //virtual LLColor4U getColor4U(const std::string& name) = 0; + //virtual LLColor4 getColor4(const std::string& name) = 0; + //virtual LLColor3 getColor3(const std::string& name) = 0; +}; + +#endif /* LL_LLCONTROLGROUPREADER_H */ + + + + + + + diff --git a/linden/indra/llxml/llxmlnode.cpp b/linden/indra/llxml/llxmlnode.cpp index 7464529..800b135 100644 --- a/linden/indra/llxml/llxmlnode.cpp +++ b/linden/indra/llxml/llxmlnode.cpp @@ -18,7 +18,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -65,6 +66,9 @@ LLXMLNode::LLXMLNode() : mEncoding(ENCODING_DEFAULT), mParent(NULL), mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), mName(NULL), mValue(""), mDefault(NULL) @@ -83,6 +87,9 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) : mEncoding(ENCODING_DEFAULT), mParent(NULL), mChildren(NULL), + mAttributes(), + mPrev(NULL), + mNext(NULL), mValue(""), mDefault(NULL) { @@ -101,17 +108,65 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) : mEncoding(ENCODING_DEFAULT), 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), + 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) + { + newnode->addChild(iter->second->deepCopy()); + } + } + for (LLXMLAttribList::iterator iter = mAttributes.begin(); + iter != mAttributes.end(); ++iter) + { + newnode->addChild(iter->second->deepCopy()); + } + + return newnode; +} + // virtual LLXMLNode::~LLXMLNode() { // Strictly speaking none of this should be required execept 'delete mChildren'... - if (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) @@ -124,7 +179,7 @@ LLXMLNode::~LLXMLNode() mChildren->map.clear(); mChildren->head = NULL; mChildren->tail = NULL; - delete mChildren; + mChildren = NULL; } for (LLXMLAttribList::iterator iter = mAttributes.begin(); iter != mAttributes.end(); ++iter) @@ -160,7 +215,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) return TRUE; } } - else if (mChildren) + else if (mChildren.notNull()) { LLXMLChildList::iterator children_itr = mChildren->map.find(target_child->mName); while (children_itr != mChildren->map.end()) @@ -183,7 +238,6 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) mChildren->map.erase(children_itr); if (mChildren->map.empty()) { - delete mChildren; mChildren = NULL; } return TRUE; @@ -201,7 +255,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) return FALSE; } -void LLXMLNode::addChild(LLXMLNodePtr new_child) +void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) { if (new_child->mParent != NULL) { @@ -219,7 +273,7 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child) } else { - if (!mChildren) + if (mChildren.isNull()) { mChildren = new LLXMLChildren(); mChildren->head = new_child; @@ -227,11 +281,33 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child) } mChildren->map.insert(std::make_pair(new_child->mName, new_child)); - if (mChildren->tail != new_child) + // if after_child is specified, it damn well better be in the list of children + // for this node. I'm not going to assert that, because it would be expensive, + // but don't specify that parameter if you didn't get the value for it from the + // list of children of this node! + if (after_child.isNull()) { - mChildren->tail->mNext = new_child; - new_child->mPrev = mChildren->tail; - mChildren->tail = new_child; + if (mChildren->tail != new_child) + { + mChildren->tail->mNext = new_child; + new_child->mPrev = mChildren->tail; + mChildren->tail = new_child; + } + } + else + { + if (after_child->mNext.notNull()) + { + // if after_child was not the last item, fix up some pointers + after_child->mNext->mPrev = new_child; + new_child->mNext = after_child->mNext; + } + new_child->mPrev = after_child; + after_child->mNext = new_child; + if (mChildren->tail == after_child) + { + mChildren->tail = new_child; + } } } @@ -293,7 +369,7 @@ void LLXMLNode::updateDefault() } } - if (mChildren) + if (mChildren.notNull()) { LLXMLChildList::const_iterator children_itr; LLXMLChildList::const_iterator children_end = mChildren->map.end(); @@ -566,6 +642,24 @@ bool LLXMLNode::updateNode( } +// static +LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node) +{ + if (!node || !update_node) + { + llwarns << "Node invalid" << llendl; + return node; + } + + LLXMLNodePtr cloned_node = update_node->deepCopy(); + node->mParent->addChild(cloned_node, node); // add after node + LLXMLNodePtr parent = node->mParent; + parent->removeChild(node); + parent->updateDefault(); + + return cloned_node; +} + // static @@ -618,7 +712,7 @@ bool LLXMLNode::parseBuffer( { llwarns << "Error parsing xml error code: " << XML_ErrorString(XML_GetErrorCode(my_parser)) - << " on lne " << XML_GetCurrentLineNumber(my_parser) + << " on line " << XML_GetCurrentLineNumber(my_parser) << llendl; } @@ -722,7 +816,7 @@ BOOL LLXMLNode::isFullyDefault() && has_default_length && has_default_attribute) { - if (mChildren) + if (mChildren.notNull()) { LLXMLChildList::const_iterator children_itr; LLXMLChildList::const_iterator children_end = mChildren->map.end(); @@ -888,7 +982,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i } } - if (!mChildren && mValue == "") + if (mChildren.isNull() && mValue == "") { output_stream << " />\n"; return; @@ -896,7 +990,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i else { output_stream << ">\n"; - if (mChildren) + if (mChildren.notNull()) { // stream non-attributes std::string next_indent = indent + "\t"; @@ -922,7 +1016,7 @@ void LLXMLNode::findName(const std::string& name, LLXMLNodeList &results) results.insert(std::make_pair(this->mName->mString, this)); return; } - if (mChildren) + if (mChildren.notNull()) { LLXMLChildList::const_iterator children_itr; LLXMLChildList::const_iterator children_end = mChildren->map.end(); @@ -941,7 +1035,7 @@ void LLXMLNode::findName(LLStringTableEntry* name, LLXMLNodeList &results) results.insert(std::make_pair(this->mName->mString, this)); return; } - if (mChildren) + if (mChildren.notNull()) { LLXMLChildList::const_iterator children_itr; LLXMLChildList::const_iterator children_end = mChildren->map.end(); @@ -960,7 +1054,7 @@ void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results) results.insert(std::make_pair(this->mName->mString, this)); return; } - if (mChildren) + if (mChildren.notNull()) { LLXMLChildList::const_iterator children_itr; LLXMLChildList::const_iterator children_end = mChildren->map.end(); @@ -974,11 +1068,11 @@ void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results) void LLXMLNode::scrubToTree(LLXMLNode *tree) { - if (!tree || !tree->mChildren) + if (!tree || tree->mChildren.isNull()) { return; } - if (mChildren) + if (mChildren.notNull()) { std::vector to_delete_list; LLXMLChildList::iterator itor = mChildren->map.begin(); @@ -1023,7 +1117,7 @@ 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) + if (mChildren.notNull()) { LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); if (child_itr != mChildren->map.end()) @@ -1047,7 +1141,7 @@ 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) + if (mChildren.notNull()) { LLXMLChildList::const_iterator child_itr = mChildren->map.find(name); if (child_itr != mChildren->map.end()) @@ -1071,6 +1165,25 @@ void LLXMLNode::getChildren(const LLStringTableEntry* name, LLXMLNodeList &child } } +// 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); + } + } +} + bool LLXMLNode::getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing) { return getAttribute(gStringTable.checkStringEntry(name), node, use_default_if_missing); @@ -1111,6 +1224,23 @@ BOOL LLXMLNode::hasAttribute(const char* name ) return getAttribute(name, node); } +// the structure of these getAttribute_ functions is ugly, but it's because the +// underlying system is based on BOOL and LLString; if we change +// so that they're based on more generic mechanisms, these will be +// simplified. +bool LLXMLNode::getAttribute_bool(const char* name, bool& value ) +{ + LLXMLNodePtr node; + if (!getAttribute(name, node)) + { + return false; + } + BOOL temp; + bool retval = node->getBoolValue(1, &temp); + value = temp; + return retval; +} + BOOL LLXMLNode::getAttributeBOOL(const char* name, BOOL& value ) { LLXMLNodePtr node; @@ -2521,7 +2651,7 @@ void LLXMLNode::setName(LLStringTableEntry* name) U32 LLXMLNode::getChildCount() const { - if (mChildren) + if (mChildren.notNull()) { return mChildren->map.size(); } @@ -2540,7 +2670,7 @@ U32 get_rand(U32 max_value) LLXMLNode *get_rand_node(LLXMLNode *node) { - if (node->mChildren) + if (node->mChildren.notNull()) { U32 num_children = node->mChildren->map.size(); if (get_rand(2) == 0) @@ -2748,7 +2878,7 @@ void LLXMLNode::createUnitTest(S32 max_num_children) BOOL LLXMLNode::performUnitTest(std::string &error_buffer) { - if (!mChildren) + if (mChildren.isNull()) { error_buffer.append(llformat("ERROR Node %s: No children found.\n", mName->mString)); return FALSE; @@ -3007,14 +3137,14 @@ BOOL LLXMLNode::performUnitTest(std::string &error_buffer) return TRUE; } -LLXMLNodePtr LLXMLNode::getFirstChild() +LLXMLNodePtr LLXMLNode::getFirstChild() const { - if (!mChildren) return NULL; + if (mChildren.isNull()) return NULL; LLXMLNodePtr ret = mChildren->head; return ret; } -LLXMLNodePtr LLXMLNode::getNextSibling() +LLXMLNodePtr LLXMLNode::getNextSibling() const { LLXMLNodePtr ret = mNext; return ret; diff --git a/linden/indra/llxml/llxmlnode.h b/linden/indra/llxml/llxmlnode.h index e73b4b1..d4e127b 100644 --- a/linden/indra/llxml/llxmlnode.h +++ b/linden/indra/llxml/llxmlnode.h @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -87,12 +88,13 @@ class LLVector3d; class LLVector4; class LLVector4U; -struct LLXMLChildren +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 }; +typedef LLPointer LLXMLChildrenPtr; class LLXMLNode : public LLThreadSafeRefCount { @@ -124,11 +126,13 @@ public: LLXMLNode(); LLXMLNode(const char* name, BOOL is_attribute); LLXMLNode(LLStringTableEntry* name, BOOL is_attribute); + LLXMLNode(const LLXMLNode& rhs); + LLXMLNodePtr deepCopy(); BOOL isNull(); BOOL deleteChild(LLXMLNode* child); - void addChild(LLXMLNodePtr new_parent); + void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL)); void setParent(LLXMLNodePtr new_parent); // reparent if necessary // Serialization @@ -146,8 +150,9 @@ public: LLXMLNodePtr& node, LLXMLNode* defaults); static bool updateNode( - LLXMLNodePtr& node, - LLXMLNodePtr& update_node); + LLXMLNodePtr& node, + LLXMLNodePtr& update_node); + static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node); static void writeHeaderToFile(LLFILE *fOut); void writeToFile(LLFILE *fOut, const std::string& indent = std::string()); void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string()); @@ -176,6 +181,10 @@ public: 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 ); @@ -211,13 +220,16 @@ 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); // The following skip over attributes - LLXMLNodePtr getFirstChild(); - LLXMLNodePtr getNextSibling(); + LLXMLNodePtr getFirstChild() const; + LLXMLNodePtr getNextSibling() const; LLXMLNodePtr getRoot(); @@ -251,7 +263,6 @@ public: void setName(LLStringTableEntry* name); // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt) - // TomY TODO: Make this private static std::string escapeXML(const std::string& xml); // Set the default node corresponding to this default node @@ -291,7 +302,7 @@ public: Encoding mEncoding; // The value encoding LLXMLNode* mParent; // The parent node - LLXMLChildren* mChildren; // The child nodes + LLXMLChildrenPtr mChildren; // The child nodes LLXMLAttribList mAttributes; // The attribute nodes LLXMLNodePtr mPrev; // Double-linked list previous node LLXMLNodePtr mNext; // Double-linked list next node diff --git a/linden/indra/llxml/llxmlparser.cpp b/linden/indra/llxml/llxmlparser.cpp index 3e87947..7d887f4 100644 --- a/linden/indra/llxml/llxmlparser.cpp +++ b/linden/indra/llxml/llxmlparser.cpp @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/linden/indra/llxml/llxmlparser.h b/linden/indra/llxml/llxmlparser.h index 325bf04..d7595f6 100644 --- a/linden/indra/llxml/llxmlparser.h +++ b/linden/indra/llxml/llxmlparser.h @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/linden/indra/llxml/llxmltree.cpp b/linden/indra/llxml/llxmltree.cpp index bd1e743..1bce5d2 100644 --- a/linden/indra/llxml/llxmltree.cpp +++ b/linden/indra/llxml/llxmltree.cpp @@ -17,7 +17,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/linden/indra/llxml/llxmltree.h b/linden/indra/llxml/llxmltree.h index 23ec57d..1a020f2 100644 --- a/linden/indra/llxml/llxmltree.h +++ b/linden/indra/llxml/llxmltree.h @@ -18,7 +18,8 @@ * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, -- cgit v1.1