diff options
Diffstat (limited to 'indra/llxml/llxmlnode.cpp')
-rw-r--r-- | indra/llxml/llxmlnode.cpp | 148 |
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; +} |