summaryrefslogtreecommitdiff
path: root/indra/llxml/llxmltree.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/llxml/llxmltree.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/llxml/llxmltree.cpp')
-rw-r--r--indra/llxml/llxmltree.cpp1388
1 files changed, 694 insertions, 694 deletions
diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp
index a9c702f552..626bbcabc3 100644
--- a/indra/llxml/llxmltree.cpp
+++ b/indra/llxml/llxmltree.cpp
@@ -1,694 +1,694 @@
-/**
- * @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$
- */
-
-#include "linden_common.h"
-
-#include "llxmltree.h"
-#include "v3color.h"
-#include "v4color.h"
-#include "v4coloru.h"
-#include "v3math.h"
-#include "v3dmath.h"
-#include "v4math.h"
-#include "llquaternion.h"
-#include "lluuid.h"
-
-//////////////////////////////////////////////////////////////
-// LLXmlTree
-
-// static
-LLStdStringTable LLXmlTree::sAttributeKeys(1024);
-
-LLXmlTree::LLXmlTree()
- : mRoot( NULL ),
- mNodeNames(512)
-{
-}
-
-LLXmlTree::~LLXmlTree()
-{
- cleanup();
-}
-
-void LLXmlTree::cleanup()
-{
- delete mRoot;
- mRoot = NULL;
- mNodeNames.cleanup();
-}
-
-
-bool LLXmlTree::parseFile(const std::string &path, bool keep_contents)
-{
- 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;
-}
-
-void LLXmlTree::dump()
-{
- if( mRoot )
- {
- dumpNode( mRoot, " " );
- }
-}
-
-void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix )
-{
- node->dump( 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)
-{
-}
-
-LLXmlTreeNode::~LLXmlTreeNode()
-{
- 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;
-}
-
-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();
-}
-
-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
-}
-
-LLXmlTreeNode* LLXmlTreeNode::getFirstChild()
-{
- mChildrenIter = mChildren.begin();
- return getNextChild();
-}
-LLXmlTreeNode* LLXmlTreeNode::getNextChild()
-{
- 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();
-}
-
-LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild()
-{
- if (mChildMapIter == mChildMapEndIter)
- return NULL;
- else
- return (mChildMapIter++)->second;
-}
-
-void LLXmlTreeNode::appendContents(const std::string& str)
-{
- mContents.append( str );
-}
-
-void LLXmlTreeNode::addChild(LLXmlTreeNode* 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));
-
- child->mParent = this;
-}
-
-//////////////////////////////////////////////////////////////
-
-// These functions assume that name is already in mAttritrubteKeys
-
-bool LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, bool& 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 );
-}
-
-bool LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& 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 );
-}
-
-bool LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& 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 );
-}
-
-bool LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& 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 );
-}
-
-bool LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& 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;
-}
-
-bool LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name, LLColor4& value)
-{
- 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;
-}
-
-bool LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name, LLVector3& value)
-{
- 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;
-}
-
-bool LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name, LLQuaternion& value)
-{
- 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;
-}
-
-bool LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, std::string& value)
-{
- const std::string *s = getAttribute( canonical_name );
- if( !s )
- {
- return false;
- }
-
- value = *s;
- return true;
-}
-
-
-//////////////////////////////////////////////////////////////
-
-bool LLXmlTreeNode::getAttributeBOOL(const std::string& name, bool& 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);
-}
-
-bool LLXmlTreeNode::getAttributeS8(const std::string& name, S8& 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);
-}
-
-bool LLXmlTreeNode::getAttributeU16(const std::string& name, U16& 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);
-}
-
-bool LLXmlTreeNode::getAttributeS32(const std::string& name, S32& 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);
-}
-
-bool LLXmlTreeNode::getAttributeF64(const std::string& name, F64& 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);
-}
-
-bool LLXmlTreeNode::getAttributeColor4(const std::string& name, LLColor4& 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);
-}
-
-bool LLXmlTreeNode::getAttributeVector3(const std::string& name, LLVector3& 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);
-}
-
-bool LLXmlTreeNode::getAttributeQuat(const std::string& name, LLQuaternion& 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);
-}
-
-bool LLXmlTreeNode::getAttributeString(const std::string& name, std::string& value)
-{
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
- return getFastAttributeString(canonical_name, value);
-}
-
-/*
- The following xml <message> nodes will all return the string from getTextContents():
- "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>
- 2. Each quoted section -> paragraph:
- <message>
- "The quick brown fox"
- " Jumps over the lazy dog"
- </message>
- 3. Literal text with beginning and trailing whitespace removed:
- <message>
-The quick brown fox
- Jumps over the lazy dog
- </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;
-}
-
-
-//////////////////////////////////////////////////////////////
-// LLXmlTreeParser
-
-LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree)
- : mTree(tree),
- mRoot( NULL ),
- mCurrent( NULL ),
- mDump( false ),
- mKeepContents(false)
-{
-}
-
-LLXmlTreeParser::~LLXmlTreeParser()
-{
-}
-
-bool LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, bool keep_contents)
-{
- llassert( !mRoot );
- llassert( !mCurrent );
-
- mKeepContents = keep_contents;
-
- bool success = LLXmlParser::parseFile(path);
-
- *root = mRoot;
- mRoot = NULL;
-
- 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;
-}
-
-LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent)
-{
- return new LLXmlTreeNode(name, parent, mTree);
-}
-
-
-void LLXmlTreeParser::endElement(const char* name)
-{
- if( mDump )
- {
- LL_INFOS() << tabs() << "endElement " << name << LL_ENDL;
- }
-
- if( !mCurrent->mContents.empty() )
- {
- LLStringUtil::trim(mCurrent->mContents);
- LLStringUtil::removeCRLF(mCurrent->mContents);
- }
-
- mCurrent = mCurrent->getParent();
-}
-
-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;
- }
-
- if (mKeepContents)
- {
- mCurrent->appendContents( str );
- }
-}
-
-void LLXmlTreeParser::processingInstruction(const char *target, const char *data)
-{
- if( mDump )
- {
- LL_INFOS() << tabs() << "processingInstruction " << data << LL_ENDL;
- }
-}
-
-void LLXmlTreeParser::comment(const char *data)
-{
- if( mDump )
- {
- LL_INFOS() << tabs() << "comment " << data << LL_ENDL;
- }
-}
-
-void LLXmlTreeParser::startCdataSection()
-{
- if( mDump )
- {
- LL_INFOS() << tabs() << "startCdataSection" << LL_ENDL;
- }
-}
-
-void LLXmlTreeParser::endCdataSection()
-{
- 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;
- }
-}
-
-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;
- }
-}
-
-void test_llxmltree()
-{
- LLXmlTree tree;
- bool success = tree.parseFile( "test.xml" );
- if( success )
- {
- tree.dump();
- }
-}
-
+/**
+ * @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$
+ */
+
+#include "linden_common.h"
+
+#include "llxmltree.h"
+#include "v3color.h"
+#include "v4color.h"
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "v4math.h"
+#include "llquaternion.h"
+#include "lluuid.h"
+
+//////////////////////////////////////////////////////////////
+// LLXmlTree
+
+// static
+LLStdStringTable LLXmlTree::sAttributeKeys(1024);
+
+LLXmlTree::LLXmlTree()
+ : mRoot( NULL ),
+ mNodeNames(512)
+{
+}
+
+LLXmlTree::~LLXmlTree()
+{
+ cleanup();
+}
+
+void LLXmlTree::cleanup()
+{
+ delete mRoot;
+ mRoot = NULL;
+ mNodeNames.cleanup();
+}
+
+
+bool LLXmlTree::parseFile(const std::string &path, bool keep_contents)
+{
+ 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;
+}
+
+void LLXmlTree::dump()
+{
+ if( mRoot )
+ {
+ dumpNode( mRoot, " " );
+ }
+}
+
+void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix )
+{
+ node->dump( 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)
+{
+}
+
+LLXmlTreeNode::~LLXmlTreeNode()
+{
+ 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;
+}
+
+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();
+}
+
+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
+}
+
+LLXmlTreeNode* LLXmlTreeNode::getFirstChild()
+{
+ mChildrenIter = mChildren.begin();
+ return getNextChild();
+}
+LLXmlTreeNode* LLXmlTreeNode::getNextChild()
+{
+ 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();
+}
+
+LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild()
+{
+ if (mChildMapIter == mChildMapEndIter)
+ return NULL;
+ else
+ return (mChildMapIter++)->second;
+}
+
+void LLXmlTreeNode::appendContents(const std::string& str)
+{
+ mContents.append( str );
+}
+
+void LLXmlTreeNode::addChild(LLXmlTreeNode* 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));
+
+ child->mParent = this;
+}
+
+//////////////////////////////////////////////////////////////
+
+// These functions assume that name is already in mAttritrubteKeys
+
+bool LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, bool& 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 );
+}
+
+bool LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& 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 );
+}
+
+bool LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& 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 );
+}
+
+bool LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& 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 );
+}
+
+bool LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& 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;
+}
+
+bool LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name, LLColor4& value)
+{
+ 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;
+}
+
+bool LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name, LLVector3& value)
+{
+ 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;
+}
+
+bool LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name, LLQuaternion& value)
+{
+ 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;
+}
+
+bool LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, std::string& value)
+{
+ const std::string *s = getAttribute( canonical_name );
+ if( !s )
+ {
+ return false;
+ }
+
+ value = *s;
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////
+
+bool LLXmlTreeNode::getAttributeBOOL(const std::string& name, bool& 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);
+}
+
+bool LLXmlTreeNode::getAttributeS8(const std::string& name, S8& 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);
+}
+
+bool LLXmlTreeNode::getAttributeU16(const std::string& name, U16& 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);
+}
+
+bool LLXmlTreeNode::getAttributeS32(const std::string& name, S32& 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);
+}
+
+bool LLXmlTreeNode::getAttributeF64(const std::string& name, F64& 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);
+}
+
+bool LLXmlTreeNode::getAttributeColor4(const std::string& name, LLColor4& 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);
+}
+
+bool LLXmlTreeNode::getAttributeVector3(const std::string& name, LLVector3& 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);
+}
+
+bool LLXmlTreeNode::getAttributeQuat(const std::string& name, LLQuaternion& 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);
+}
+
+bool LLXmlTreeNode::getAttributeString(const std::string& name, std::string& value)
+{
+ LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
+ return getFastAttributeString(canonical_name, value);
+}
+
+/*
+ The following xml <message> nodes will all return the string from getTextContents():
+ "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>
+ 2. Each quoted section -> paragraph:
+ <message>
+ "The quick brown fox"
+ " Jumps over the lazy dog"
+ </message>
+ 3. Literal text with beginning and trailing whitespace removed:
+ <message>
+The quick brown fox
+ Jumps over the lazy dog
+ </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;
+}
+
+
+//////////////////////////////////////////////////////////////
+// LLXmlTreeParser
+
+LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree)
+ : mTree(tree),
+ mRoot( NULL ),
+ mCurrent( NULL ),
+ mDump( false ),
+ mKeepContents(false)
+{
+}
+
+LLXmlTreeParser::~LLXmlTreeParser()
+{
+}
+
+bool LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, bool keep_contents)
+{
+ llassert( !mRoot );
+ llassert( !mCurrent );
+
+ mKeepContents = keep_contents;
+
+ bool success = LLXmlParser::parseFile(path);
+
+ *root = mRoot;
+ mRoot = NULL;
+
+ 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;
+}
+
+LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent)
+{
+ return new LLXmlTreeNode(name, parent, mTree);
+}
+
+
+void LLXmlTreeParser::endElement(const char* name)
+{
+ if( mDump )
+ {
+ LL_INFOS() << tabs() << "endElement " << name << LL_ENDL;
+ }
+
+ if( !mCurrent->mContents.empty() )
+ {
+ LLStringUtil::trim(mCurrent->mContents);
+ LLStringUtil::removeCRLF(mCurrent->mContents);
+ }
+
+ mCurrent = mCurrent->getParent();
+}
+
+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;
+ }
+
+ if (mKeepContents)
+ {
+ mCurrent->appendContents( str );
+ }
+}
+
+void LLXmlTreeParser::processingInstruction(const char *target, const char *data)
+{
+ if( mDump )
+ {
+ LL_INFOS() << tabs() << "processingInstruction " << data << LL_ENDL;
+ }
+}
+
+void LLXmlTreeParser::comment(const char *data)
+{
+ if( mDump )
+ {
+ LL_INFOS() << tabs() << "comment " << data << LL_ENDL;
+ }
+}
+
+void LLXmlTreeParser::startCdataSection()
+{
+ if( mDump )
+ {
+ LL_INFOS() << tabs() << "startCdataSection" << LL_ENDL;
+ }
+}
+
+void LLXmlTreeParser::endCdataSection()
+{
+ 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;
+ }
+}
+
+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;
+ }
+}
+
+void test_llxmltree()
+{
+ LLXmlTree tree;
+ bool success = tree.parseFile( "test.xml" );
+ if( success )
+ {
+ tree.dump();
+ }
+}
+