summaryrefslogtreecommitdiff
path: root/indra/llxml/llxmlnode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llxml/llxmlnode.cpp')
-rw-r--r--indra/llxml/llxmlnode.cpp148
1 files changed, 117 insertions, 31 deletions
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 800b13573f..e97aa55190 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -47,6 +47,7 @@
#include "llquaternion.h"
#include "llstring.h"
#include "lluuid.h"
+#include "lldir.h"
const S32 MAX_COLUMN_WIDTH = 80;
@@ -64,6 +65,7 @@ LLXMLNode::LLXMLNode() :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -85,6 +87,7 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -106,6 +109,7 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -226,6 +230,10 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
{
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;
@@ -387,6 +395,7 @@ void XMLCALL StartXMLNode(void *userData,
{
// 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;
@@ -401,7 +410,8 @@ void XMLCALL StartXMLNode(void *userData,
}
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);
@@ -492,6 +502,7 @@ void XMLCALL StartXMLNode(void *userData,
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);
@@ -836,12 +847,66 @@ BOOL LLXMLNode::isFullyDefault()
}
// static
-void LLXMLNode::writeHeaderToFile(LLFILE *fOut)
+bool LLXMLNode::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
+ const std::vector<std::string>& paths)
+{
+ std::string full_filename = gDirUtilp->findSkinnedFilename(paths.front(), xui_filename);
+ if (full_filename.empty())
+ {
+ return false;
+ }
+
+ if (!LLXMLNode::parseFile(full_filename, root, NULL))
+ {
+ // try filename as passed in since sometimes we load an xml file from a user-supplied path
+ if (!LLXMLNode::parseFile(xui_filename, root, NULL))
+ {
+ llwarns << "Problem reading UI description file: " << xui_filename << llendl;
+ return false;
+ }
+ }
+
+ LLXMLNodePtr updateRoot;
+
+ std::vector<std::string>::const_iterator itor;
+
+ for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
+ {
+ std::string nodeName;
+ std::string updateName;
+
+ std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename);
+ if(layer_filename.empty())
+ {
+ // no localized version of this file, that's ok, keep looking
+ continue;
+ }
+
+ if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
+ {
+ llwarns << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
+ return false;
+ }
+
+ updateRoot->getAttributeString("name", updateName);
+ root->getAttributeString("name", nodeName);
+
+ if (updateName == nodeName)
+ {
+ LLXMLNode::updateNode(root, updateRoot);
+ }
+ }
+
+ return true;
+}
+
+// static
+void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
{
- fprintf(fOut, "<?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 *fOut, const std::string& indent)
+void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent)
{
if (isFullyDefault())
{
@@ -852,7 +917,8 @@ void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
std::ostringstream ostream;
writeToOstream(ostream, indent);
std::string outstring = ostream.str();
- if (fwrite(outstring.c_str(), 1, outstring.length(), fOut) != outstring.length())
+ size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);
+ if (written != outstring.length())
{
llwarns << "Short write" << llendl;
}
@@ -872,12 +938,12 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength);
// stream the name
- output_stream << indent << "<" << mName->mString;
+ output_stream << indent << "<" << mName->mString << "\n";
// ID
if (mID != "")
{
- output_stream << " id=\"" << mID << "\"";
+ output_stream << indent << " id=\"" << mID << "\"\n";
}
// Type
@@ -886,22 +952,22 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
switch (mType)
{
case TYPE_BOOLEAN:
- output_stream << " type=\"boolean\"";
+ output_stream << indent << " type=\"boolean\"\n";
break;
case TYPE_INTEGER:
- output_stream << " type=\"integer\"";
+ output_stream << indent << " type=\"integer\"\n";
break;
case TYPE_FLOAT:
- output_stream << " type=\"float\"";
+ output_stream << indent << " type=\"float\"\n";
break;
case TYPE_STRING:
- output_stream << " type=\"string\"";
+ output_stream << indent << " type=\"string\"\n";
break;
case TYPE_UUID:
- output_stream << " type=\"uuid\"";
+ output_stream << indent << " type=\"uuid\"\n";
break;
case TYPE_NODEREF:
- output_stream << " type=\"noderef\"";
+ output_stream << indent << " type=\"noderef\"\n";
break;
default:
// default on switch(enum) eliminates a warning on linux
@@ -915,13 +981,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
switch (mEncoding)
{
case ENCODING_DECIMAL:
- output_stream << " encoding=\"decimal\"";
+ output_stream << indent << " encoding=\"decimal\"\n";
break;
case ENCODING_HEX:
- output_stream << " encoding=\"hex\"";
+ output_stream << indent << " encoding=\"hex\"\n";
break;
/*case ENCODING_BASE32:
- output_stream << " encoding=\"base32\"";
+ output_stream << indent << " encoding=\"base32\"\n";
break;*/
default:
// default on switch(enum) eliminates a warning on linux
@@ -932,24 +998,23 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
// Precision
if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
{
- output_stream << " precision=\"" << mPrecision << "\"";
+ output_stream << indent << " precision=\"" << mPrecision << "\"\n";
}
// Version
if (mVersionMajor > 0 || mVersionMinor > 0)
{
- output_stream << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"";
+ output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n";
}
// Array length
if (!has_default_length && mLength > 0)
{
- output_stream << " length=\"" << mLength << "\"";
+ output_stream << indent << " length=\"" << mLength << "\"\n";
}
{
// Write out attributes
- S32 col_pos = 0;
LLXMLAttribList::const_iterator attr_itr;
LLXMLAttribList::const_iterator attr_end = mAttributes.end();
for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr)
@@ -971,17 +1036,14 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
std::string attr_str = llformat(" %s=\"%s\"",
attr.c_str(),
escapeXML(child->mValue).c_str());
- if (col_pos + (S32)attr_str.length() > MAX_COLUMN_WIDTH)
- {
- output_stream << "\n" << indent << " ";
- col_pos = 4;
- }
- col_pos += attr_str.length();
- output_stream << attr_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";
@@ -993,7 +1055,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (mChildren.notNull())
{
// stream non-attributes
- std::string next_indent = indent + "\t";
+ std::string next_indent = indent + " ";
for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())
{
child->writeToOstream(output_stream, next_indent);
@@ -1002,7 +1064,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (!mValue.empty())
{
std::string contents = getTextContents();
- output_stream << indent << "\t" << escapeXML(contents) << "\n";
+ output_stream << indent << " " << escapeXML(contents) << "\n";
}
output_stream << indent << "</" << mName->mString << ">\n";
}
@@ -2475,14 +2537,15 @@ std::string LLXMLNode::escapeXML(const std::string& xml)
return out;
}
-void LLXMLNode::setStringValue(U32 length, const std::string *array)
+void LLXMLNode::setStringValue(U32 length, const std::string *strings)
{
if (length == 0) return;
std::string new_value;
for (U32 pos=0; pos<length; ++pos)
{
- new_value.append(escapeXML(array[pos]));
+ // *NOTE: Do not escape strings here - do it on output
+ new_value.append( strings[pos] );
if (pos < length-1) new_value.append(" ");
}
@@ -3150,6 +3213,19 @@ LLXMLNodePtr LLXMLNode::getNextSibling() const
return ret;
}
+std::string LLXMLNode::getSanitizedValue() const
+{
+ if (mIsAttribute)
+ {
+ return getValue() ;
+ }
+ else
+ {
+ return getTextContents();
+ }
+}
+
+
std::string LLXMLNode::getTextContents() const
{
std::string msg;
@@ -3215,3 +3291,13 @@ std::string LLXMLNode::getTextContents() const
}
return msg;
}
+
+void LLXMLNode::setLineNumber(S32 line_number)
+{
+ mLineNumber = line_number;
+}
+
+S32 LLXMLNode::getLineNumber()
+{
+ return mLineNumber;
+}