summaryrefslogtreecommitdiff
path: root/indra/llxml
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-09-05 11:00:11 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-09-05 11:00:11 -0400
commit000a23ba0534fdf9bfc4a1b051b7cee0adceef3e (patch)
tree776fe10c7aaf76371a889f79c48c3c9405fd5a4e /indra/llxml
parent7ac4c3b56e5246fceaa73e7c9c665d3c04827d6c (diff)
parentbacf9cfeab90bd1ffad827fa3c34ced985c768a2 (diff)
Merge branch 'develop' into release/luau-scripting
Diffstat (limited to 'indra/llxml')
-rw-r--r--indra/llxml/llcontrol.cpp4
-rw-r--r--indra/llxml/llcontrol.h28
-rw-r--r--indra/llxml/llxmlnode.cpp209
-rw-r--r--indra/llxml/llxmlnode.h21
-rw-r--r--indra/llxml/llxmltree.cpp10
5 files changed, 210 insertions, 62 deletions
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index ab5f26d10b..6d02cbaa34 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -348,7 +348,7 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(std::string_view name)
incrCount(name);
}
- ctrl_name_table_t::iterator iter = mNameTable.find(name.data());
+ ctrl_name_table_t::iterator iter = mNameTable.find(name);
return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second;
}
@@ -657,7 +657,7 @@ LLSD LLControlGroup::asLLSD(bool diffs_only)
return result;
}
-bool LLControlGroup::controlExists(const std::string& name)
+bool LLControlGroup::controlExists(std::string_view name)
{
ctrl_name_table_t::iterator iter = mNameTable.find(name);
return iter != mNameTable.end();
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 996feb49a6..a614ff216b 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -36,32 +36,8 @@
#include <vector>
-// *NOTE: boost::visit_each<> generates warning 4675 on .net 2003
-// Disable the warning for the boost includes.
-#if LL_WINDOWS
-# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
-# pragma warning(push)
-# pragma warning( disable : 4675 )
-# endif
-#endif
-
#include <boost/bind.hpp>
-
-#if LL_WINDOWS
- #pragma warning (push)
- #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
- #pragma warning (disable : 4264)
-#endif
#include <boost/signals2.hpp>
-#if LL_WINDOWS
- #pragma warning (pop)
-#endif
-
-#if LL_WINDOWS
-# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
-# pragma warning(pop)
-# endif
-#endif
class LLVector3;
class LLVector3d;
@@ -189,7 +165,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
LOG_CLASS(LLControlGroup);
protected:
- typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
+ typedef std::map<std::string, LLControlVariablePtr, std::less<> > ctrl_name_table_t;
ctrl_name_table_t mNameTable;
static const std::string mTypeString[TYPE_COUNT];
@@ -295,7 +271,7 @@ public:
}
}
- bool controlExists(const std::string& name);
+ bool controlExists(std::string_view name);
// Returns number of controls loaded, 0 if failed
// If require_declaration is false, will auto-declare controls it finds
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 0fd4516844..e695035461 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -38,7 +38,9 @@
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
+#include "llbase64.h"
#include "llquaternion.h"
+#include "llsd.h"
#include "llstring.h"
#include "lluuid.h"
#include "lldir.h"
@@ -653,32 +655,24 @@ bool LLXMLNode::updateNode(
// static
bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree)
{
- // Read file
- LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL;
- LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
- if (fp == NULL)
+ std::string xml = LLFile::getContents(filename);
+ if (xml.empty())
{
- node = NULL ;
- return false;
+ LL_WARNS("XMLNode") << "no XML file: " << filename << LL_ENDL;
+ }
+ else if (parseBuffer(xml.data(), xml.size(), node, defaults_tree))
+ {
+ return true;
}
- fseek(fp, 0, SEEK_END);
- U32 length = ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
- U8* buffer = new U8[length+1];
- size_t nread = fread(buffer, 1, length, fp);
- buffer[nread] = 0;
- fclose(fp);
- bool rv = parseBuffer(buffer, static_cast<U32>(nread), node, defaults_tree);
- delete [] buffer;
- return rv;
+ node = nullptr;
+ return false;
}
// static
bool LLXMLNode::parseBuffer(
- U8* buffer,
- U32 length,
+ const char* buffer,
+ U64 length,
LLXMLNodePtr& node,
LLXMLNode* defaults)
{
@@ -693,20 +687,25 @@ bool LLXMLNode::parseBuffer(
file_node->mParser = &my_parser;
- XML_SetUserData(my_parser, (void *)file_node_ptr);
+ XML_SetUserData(my_parser, file_node_ptr);
// Do the parsing
- if (XML_Parse(my_parser, (const char *)buffer, length, true) != XML_STATUS_OK)
+ bool success = XML_STATUS_OK == XML_Parse(my_parser, buffer, (int)length, true);
+ if (!success)
{
LL_WARNS() << "Error parsing xml error code: "
<< XML_ErrorString(XML_GetErrorCode(my_parser))
<< " on line " << XML_GetCurrentLineNumber(my_parser)
+ << ", column " << XML_GetCurrentColumnNumber(my_parser)
<< LL_ENDL;
}
// Deinit
XML_ParserFree(my_parser);
+ if (!success)
+ return false;
+
if (!file_node->mChildren || file_node->mChildren->map.size() != 1)
{
LL_WARNS() << "Parse failure - wrong number of top-level nodes xml."
@@ -3266,3 +3265,171 @@ S32 LLXMLNode::getLineNumber()
{
return mLineNumber;
}
+
+bool LLXMLNode::parseXmlRpcArrayValue(LLSD& target)
+{
+ LLXMLNode* datap = getFirstChild().get();
+ if (!datap)
+ {
+ LL_WARNS() << "No inner XML element." << LL_ENDL;
+ return false;
+ }
+ if (!datap->hasName("data"))
+ {
+ LL_WARNS() << "No inner XML element (<data> expected, got: "
+ << datap->mName->mString << ")" << LL_ENDL;
+ return false;
+ }
+ if (datap->getNextSibling().get())
+ {
+ LL_WARNS() << "Multiple inner XML elements (single <data> expected)"
+ << LL_ENDL;
+ return false;
+ }
+ for (LLXMLNode* itemp = datap->getFirstChild().get(); itemp;
+ itemp = itemp->getNextSibling().get())
+ {
+ LLSD value;
+ if (!itemp->fromXMLRPCValue(value))
+ {
+ return false;
+ }
+ target.append(value);
+ }
+ return true;
+}
+
+bool LLXMLNode::parseXmlRpcStructValue(LLSD& target)
+{
+ std::string name;
+ LLSD value;
+ for (LLXMLNode* itemp = getFirstChild().get(); itemp;
+ itemp = itemp->getNextSibling().get())
+ {
+ if (!itemp->hasName("member"))
+ {
+ LL_WARNS() << "Invalid inner XML element (<member> expected, got: <"
+ << itemp->mName->mString << ">" << LL_ENDL;
+ return false;
+ }
+ name.clear();
+ value.clear();
+ for (LLXMLNode* chilp = itemp->getFirstChild().get(); chilp;
+ chilp = chilp->getNextSibling().get())
+ {
+ if (chilp->hasName("name"))
+ {
+ name = LLStringFn::xml_decode(chilp->getTextContents());
+ }
+ else if (!chilp->fromXMLRPCValue(value))
+ {
+ return false;
+ }
+ }
+ if (name.empty())
+ {
+ LL_WARNS() << "Empty struct member name" << LL_ENDL;
+ return false;
+ }
+ target.insert(name, value);
+ }
+ return true;
+}
+
+bool LLXMLNode::fromXMLRPCValue(LLSD& target)
+{
+ target.clear();
+
+ if (!hasName("value"))
+ {
+ LL_WARNS() << "Invalid XML element (<value> expected), got: <"
+ << mName->mString << ">" << LL_ENDL;
+ return false;
+ }
+
+ LLXMLNode* childp = getFirstChild().get();
+ if (!childp)
+ {
+ LL_WARNS() << "No inner XML element (value type expected)" << LL_ENDL;
+ // Value with no type qualifier is treated as string
+ target.assign(LLStringFn::xml_decode(getTextContents()));
+ return true;
+ }
+
+ if (childp->getNextSibling())
+ {
+ LL_WARNS() << "Multiple inner XML elements (single expected)"
+ << LL_ENDL;
+ return false;
+ }
+
+ if (childp->hasName("string"))
+ {
+ target.assign(LLStringFn::xml_decode(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("int") || childp->hasName("i4"))
+ {
+ target.assign(std::stoi(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("double"))
+ {
+ target.assign(std::stod(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("boolean"))
+ {
+ target.assign(std::stoi(childp->getTextContents()) != 0);
+ return true;
+ }
+
+ if (childp->hasName("dateTime.iso8601"))
+ {
+ target.assign(LLSD::Date(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("base64"))
+ {
+ std::string decoded =
+ LLBase64::decodeAsString(childp->getTextContents());
+ size_t size = decoded.size();
+ LLSD::Binary binary(size);
+ if (size)
+ {
+ memcpy((void*)binary.data(), (void*)decoded.data(), size);
+ }
+ target.assign(binary);
+ return true;
+ }
+
+ if (childp->hasName("array"))
+ {
+ if (!childp->parseXmlRpcArrayValue(target))
+ {
+ target.clear();
+ return false;
+ }
+ return true;
+ }
+
+ if (childp->hasName("struct"))
+ {
+ if (!childp->parseXmlRpcStructValue(target))
+ {
+ target.clear();
+ return false;
+ }
+ return true;
+ }
+
+ LL_WARNS() << "Unknown inner XML element (known value type expected)"
+ << LL_ENDL;
+ // Value with unknown type qualifier is treated as string
+ target.assign(LLStringFn::xml_decode(childp->getTextContents()));
+ return true;
+}
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index b8e29bbfef..3769ec8293 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -50,6 +50,7 @@ class LLVector3d;
class LLQuaternion;
class LLColor4;
class LLColor4U;
+class LLSD;
struct CompareAttributes
@@ -129,20 +130,20 @@ public:
void addChild(LLXMLNodePtr& new_child);
void setParent(LLXMLNodePtr& new_parent); // reparent if necessary
- // Serialization
+ // Deserialization
static bool parseFile(
const std::string& filename,
LLXMLNodePtr& node,
- LLXMLNode* defaults_tree);
+ LLXMLNode* defaults = nullptr);
static bool parseBuffer(
- U8* buffer,
- U32 length,
+ const char* buffer,
+ U64 length,
LLXMLNodePtr& node,
- LLXMLNode* defaults);
+ LLXMLNode* defaults = nullptr);
static bool parseStream(
std::istream& str,
LLXMLNodePtr& node,
- LLXMLNode* defaults);
+ LLXMLNode* defaults = nullptr);
static bool updateNode(
LLXMLNodePtr& node,
LLXMLNodePtr& update_node);
@@ -284,12 +285,18 @@ public:
void setAttributes(ValueType type, U32 precision, Encoding encoding, U32 length);
// void appendValue(const std::string& value); // Unused
+ bool fromXMLRPCValue(LLSD& target);
+
// Unit Testing
void createUnitTest(S32 max_num_children);
bool performUnitTest(std::string &error_buffer);
protected:
bool removeChild(LLXMLNode* child);
+ bool isFullyDefault();
+
+ bool parseXmlRpcArrayValue(LLSD& target);
+ bool parseXmlRpcStructValue(LLSD& target);
public:
std::string mID; // The ID attribute of this node
@@ -328,8 +335,6 @@ protected:
static const char *skipNonWhitespace(const char *str);
static const char *parseInteger(const char *str, U64 *dest, bool *is_negative, U32 precision, Encoding encoding);
static const char *parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding);
-
- bool isFullyDefault();
};
#endif // LL_LLXMLNODE
diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp
index 0ace1baf2a..164b3156e1 100644
--- a/indra/llxml/llxmltree.cpp
+++ b/indra/llxml/llxmltree.cpp
@@ -111,11 +111,11 @@ 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();
+ for(LLXmlTreeNode* node : mChildren)
+ {
+ delete node;
+ }
+ mChildren.clear();
}
void LLXmlTreeNode::dump( const std::string& prefix )