123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- /**
- * @file llxmltree.cpp
- * @brief LLXmlTree implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-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$
- */
- #include "linden_common.h"
- #include "llxmltree.h"
- #include "llcolor3.h"
- #include "llcolor4.h"
- #include "llcolor4u.h"
- #include "llquaternion.h"
- #include "llvector3.h"
- #include "llvector3d.h"
- #include "llvector4.h"
- ///////////////////////////////////////////////////////////////////////////////
- // LLXmlTree class
- ///////////////////////////////////////////////////////////////////////////////
- //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();
- llwarns << "Parse file failed line " << line_number << " with error: "
- << error << llendl;
- }
- 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 class
- ///////////////////////////////////////////////////////////////////////////////
- LLXmlTreeNode::LLXmlTreeNode(const char* name, LLXmlTreeNode* parent,
- LLXmlTree* tree)
- : mName(name),
- mParent(parent),
- mTree(tree)
- {
- }
- LLXmlTreeNode::~LLXmlTreeNode()
- {
- for (attribute_map_t::iterator it = mAttributes.begin(),
- end = mAttributes.end();
- it != end; ++it)
- {
- delete it->second;
- }
- for (S32 i = 0, count = mChildren.size(); i < count; ++i)
- {
- delete mChildren[i];
- }
- mChildren.clear();
- }
- void LLXmlTreeNode::dump(const std::string& prefix)
- {
- llinfos << prefix << mName;
- if (!mContents.empty())
- {
- llcont << " 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;
- llcont << prefix << " " << key << "="
- << (value->empty() ? "NULL" : *value);
- }
- llcont << llendl;
- }
- 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 char* 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()
- {
- return mChildrenIter == mChildren.end() ? 0 : *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.emplace(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);
- }
- bool LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name,
- LLColor4& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLColor4::parseColor4(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeColor4U(LLStdStringHandle canonical_name,
- LLColor4U& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLColor4U::parseColor4U(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name,
- LLVector3& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLVector3::parseVector3(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeVector3d(LLStdStringHandle canonical_name,
- LLVector3d& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLVector3d::parseVector3d(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name,
- LLQuaternion& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLQuaternion::parseQuat(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeUUID(LLStdStringHandle canonical_name,
- LLUUID& value)
- {
- const std::string* s = getAttribute(canonical_name);
- return s && LLUUID::parseUUID(*s, &value);
- }
- bool LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name,
- std::string& value)
- {
- const std::string* s = getAttribute(canonical_name);
- if (s)
- {
- value = *s;
- return true;
- }
- else
- {
- return false;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool LLXmlTreeNode::getAttributeBool(const char* name, bool& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeBool(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeU8(const char* name, U8& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeU8(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeS8(const char* name, S8& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeS8(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeS16(const char* name, S16& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeS16(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeU16(const char* name, U16& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeU16(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeU32(const char* name, U32& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeU32(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeS32(const char* name, S32& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeS32(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeF32(const char* name, F32& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeF32(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeF64(const char* name, F64& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeF64(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeColor(const char* name, LLColor4& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeColor(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeColor4(const char* name, LLColor4& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeColor4(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeColor4U(const char* name, LLColor4U& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeColor4U(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeVector3(const char* name, LLVector3& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeVector3(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeVector3d(const char* name, LLVector3d& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeVector3d(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeQuat(const char* name, LLQuaternion& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeQuat(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeUUID(const char* name, LLUUID& value)
- {
- LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
- return getFastAttributeUUID(canonical_name, value);
- }
- bool LLXmlTreeNode::getAttributeString(const char* 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 (true)
- {
- // mContents[n] == '"'
- std::string::size_type t = ++n;
- std::string::size_type m = 0;
- // fix-up escaped characters
- while (true)
- {
- // Find first of \ or "
- m = mContents.find_first_of("\\\"", t);
- 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)
- {
- // Remove "\n" if only 1 line
- msg.erase(msg.size() - 1);
- }
- break;
- }
- }
- }
- else
- {
- // Case 3: node has embedded text (beginning and trailing
- // whitespace trimmed)
- msg = mContents;
- }
- }
- return msg;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLXmlTreeParser class
- ///////////////////////////////////////////////////////////////////////////////
- LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree)
- : mTree(tree),
- mRoot(NULL),
- mCurrent(NULL),
- mDump(false),
- mKeepContents(false)
- {
- }
- 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 && mCurrent)
- {
- llwarns << "mCurrent not null after parsing: " << path << llendl;
- llassert(false);
- }
- mCurrent = NULL;
- return success;
- }
- const std::string& LLXmlTreeParser::tabs()
- {
- static std::string s;
- s.clear();
- 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)
- {
- llinfos << tabs() << "startElement " << name << llendl;
- for (S32 i = 0; atts[i] && atts[i + 1]; i += 2)
- {
- llinfos << tabs() << "attribute: " << atts[i] << "="
- << atts[i + 1] << llendl;
- }
- }
- LLXmlTreeNode* child = createXmlTreeNode(name, mCurrent);
- for (S32 i = 0; atts[i] && atts[i + 1]; i += 2)
- {
- child->addAttribute(atts[i], atts[i + 1]);
- }
- if (mCurrent)
- {
- mCurrent->addChild(child);
- }
- else
- {
- llassert(!mRoot);
- mRoot = child;
- }
- mCurrent = child;
- }
- LLXmlTreeNode* LLXmlTreeParser::createXmlTreeNode(const char* name,
- LLXmlTreeNode* parent)
- {
- return new LLXmlTreeNode(name, parent, mTree);
- }
- void LLXmlTreeParser::endElement(const char* name)
- {
- if (mDump)
- {
- llinfos << tabs() << "endElement " << name << llendl;
- }
- if (mCurrent && !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)
- {
- llinfos << tabs() << "CharacterData " << str << llendl;
- }
- if (mKeepContents)
- {
- mCurrent->appendContents(str);
- }
- }
- void LLXmlTreeParser::processingInstruction(const char* target,
- const char* data)
- {
- if (mDump)
- {
- llinfos << tabs() << "processingInstruction " << data << llendl;
- }
- }
- void LLXmlTreeParser::comment(const char* data)
- {
- if (mDump)
- {
- llinfos << tabs() << "comment " << data << llendl;
- }
- }
- void LLXmlTreeParser::startCdataSection()
- {
- if (mDump)
- {
- llinfos << tabs() << "startCdataSection" << llendl;
- }
- }
- void LLXmlTreeParser::endCdataSection()
- {
- if (mDump)
- {
- llinfos << tabs() << "endCdataSection" << llendl;
- }
- }
- void LLXmlTreeParser::defaultData(const char* s, int len)
- {
- if (mDump)
- {
- std::string str;
- if (s)
- {
- str = std::string(s, len);
- }
- llinfos << tabs() << "defaultData " << str << llendl;
- }
- }
- void LLXmlTreeParser::unparsedEntityDecl(const char* entity_name,
- const char* base,
- const char* system_id,
- const char* public_id,
- const char* notation_name)
- {
- if (mDump)
- {
- llinfos << tabs() << "Unparsed entity:" << llendl;
- llinfos << tabs() << " entityName " << entity_name << llendl;
- llinfos << tabs() << " base " << base << llendl;
- llinfos << tabs() << " systemId " << system_id << llendl;
- llinfos << tabs() << " publicId " << public_id << llendl;
- llinfos << tabs() << " notationName " << notation_name << llendl;
- }
- }
|