summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRichard Nelson <none@none>2010-10-06 16:56:38 -0700
committerRichard Nelson <none@none>2010-10-06 16:56:38 -0700
commit5647e745989d6c3e4387ec990a35c4308dd6b929 (patch)
tree18b17faf6c2c7c03ba24445ee1e6018fff49413f /indra
parentb285fd4d0abf9113fc416c30ac115db06c9f2ebf (diff)
added param block support for empty/undefined elements in XML/LLSD respectively.
This way <foo/> or LLSD["foo"]; both define a default constructed value for the parameter named foo, useful in the Multiple<T> case
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llsdparam.cpp27
-rw-r--r--indra/llui/llsdparam.h2
-rw-r--r--indra/llxuixml/llinitparam.cpp7
-rw-r--r--indra/llxuixml/llinitparam.h3
-rw-r--r--indra/llxuixml/llxuiparser.cpp63
-rw-r--r--indra/llxuixml/llxuiparser.h6
6 files changed, 103 insertions, 5 deletions
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index f97f80ab6c..fae20a473e 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -45,6 +45,7 @@ LLParamSDParser::LLParamSDParser()
if (sReadFuncs.empty())
{
+ registerParserFuncs<LLInitParam::NoValue>(readNoValue, &LLParamSDParser::writeNoValue);
registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
@@ -71,6 +72,18 @@ bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const voi
return true;
}
+bool LLParamSDParser::writeNoValue(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
+{
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
+
+ LLSD* sd_to_write = sdparser.getSDWriteNode(name_stack);
+ if (!sd_to_write) return false;
+
+ return true;
+}
+
+
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
{
mCurReadSD = NULL;
@@ -87,6 +100,8 @@ void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
block.serializeBlock(*this);
}
+const LLSD NO_VALUE_MARKER;
+
void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block)
{
if (sd.isMap())
@@ -110,6 +125,11 @@ void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block
readSDValues(*it, block);
}
}
+ else if (sd.isUndefined())
+ {
+ mCurReadSD = &NO_VALUE_MARKER;
+ block.submitValue(mNameStack, *this);
+ }
else
{
mCurReadSD = &sd;
@@ -206,6 +226,13 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
return sd_to_write;
}
+bool LLParamSDParser::readNoValue(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ return self.mCurReadSD == &NO_VALUE_MARKER;
+}
+
+
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index 97e8b58e49..69dab2b411 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -63,7 +63,9 @@ private:
LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);
static bool writeU32Param(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack);
+ static bool writeNoValue(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack);
+ static bool readNoValue(Parser& parser, void* val_ptr);
static bool readS32(Parser& parser, void* val_ptr);
static bool readU32(Parser& parser, void* val_ptr);
static bool readF32(Parser& parser, void* val_ptr);
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index 2c92539387..7ffcd91879 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -312,6 +312,13 @@ namespace LLInitParam
}
}
+ // if no match, and no names left on stack, this is just an existence assertion of this block
+ // verify by calling readValue with NoValue type, an inherently unparseable type
+ if (!names_left)
+ {
+ return p.readValue(NoValue());
+ }
+
return false;
}
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index ad9b584632..66ef8e65cd 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -278,6 +278,9 @@ namespace LLInitParam
S32 mParseGeneration;
};
+ // used to indicate no matching value to a given name when parsing
+ struct NoValue{};
+
class BaseBlock;
class Param
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index e1ad9a5c71..723a20f382 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -382,6 +382,7 @@ LLXUIParser::LLXUIParser()
{
if (sXUIReadFuncs.empty())
{
+ registerParserFuncs<LLInitParam::NoValue>(readNoValue, writeNoValue);
registerParserFuncs<bool>(readBoolValue, writeBoolValue);
registerParserFuncs<std::string>(readStringValue, writeStringValue);
registerParserFuncs<U8>(readU8Value, writeU8Value);
@@ -400,6 +401,7 @@ LLXUIParser::LLXUIParser()
}
static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
+const LLXMLNodePtr DUMMY_NODE = new LLXMLNode();
void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent)
{
@@ -426,6 +428,17 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
boost::char_separator<char> sep(".");
bool values_parsed = false;
+ bool silent = mCurReadDepth > 0;
+
+ if (nodep->getFirstChild().isNull()
+ && nodep->mAttributes.empty()
+ && nodep->getSanitizedValue().empty())
+ {
+ // empty node, just parse as NoValue
+ mCurReadNode = DUMMY_NODE;
+ return block.submitValue(mNameStack, *this, silent);
+ }
+
// submit attributes for current node
values_parsed |= readAttributes(nodep, block);
@@ -438,7 +451,6 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
// child nodes are not necessarily valid parameters (could be a child widget)
// so don't complain once we've recursed
- bool silent = mCurReadDepth > 0;
if (!block.submitValue(mNameStack, *this, true))
{
mNameStack.pop_back();
@@ -543,6 +555,7 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo
boost::char_separator<char> sep(".");
bool any_parsed = false;
+ bool silent = mCurReadDepth > 0;
for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin();
attribute_it != nodep->mAttributes.end();
@@ -561,7 +574,6 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo
}
// child nodes are not necessarily valid attributes, so don't complain once we've recursed
- bool silent = mCurReadDepth > 0;
any_parsed |= block.submitValue(mNameStack, *this, silent);
while(num_tokens_pushed-- > 0)
@@ -628,6 +640,19 @@ LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node);
}
+bool LLXUIParser::readNoValue(Parser& parser, void* val_ptr)
+{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode == DUMMY_NODE;
+}
+
+bool LLXUIParser::writeNoValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+{
+ // just create node
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
+ return node.notNull();
+}
bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
@@ -1043,6 +1068,8 @@ static LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
static LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
static LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;
+const char* NO_VALUE_MARKER = "no_value";
+
LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
: Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
mLastWriteGeneration(-1),
@@ -1051,6 +1078,7 @@ LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t
{
if (sSimpleXUIReadFuncs.empty())
{
+ registerParserFuncs<LLInitParam::NoValue>(readNoValue);
registerParserFuncs<bool>(readBoolValue);
registerParserFuncs<std::string>(readStringValue);
registerParserFuncs<U8>(readU8Value);
@@ -1114,6 +1142,8 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl
return false;
}
+ mEmptyLeafNode.push_back(false);
+
if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
{
LL_WARNS("ReadXUI") << "Error while parsing file " << filename << LL_ENDL;
@@ -1121,6 +1151,8 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl
return false;
}
+ mEmptyLeafNode.pop_back();
+
XML_ParserFree( mParser );
return true;
}
@@ -1205,8 +1237,14 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
}
}
+ // parent node is not empty
+ mEmptyLeafNode.back() = false;
+ // we are empty if we have no attributes
+ mEmptyLeafNode.push_back(atts[0] == NULL);
+
mTokenSizeStack.push_back(num_tokens_pushed);
readAttributes(atts);
+
}
bool LLSimpleXUIParser::readAttributes(const char **atts)
@@ -1240,7 +1278,7 @@ bool LLSimpleXUIParser::readAttributes(const char **atts)
return any_parsed;
}
-void LLSimpleXUIParser::processText()
+bool LLSimpleXUIParser::processText()
{
if (!mTextContents.empty())
{
@@ -1253,12 +1291,22 @@ void LLSimpleXUIParser::processText()
mNameStack.pop_back();
}
mTextContents.clear();
+ return true;
}
+ return false;
}
void LLSimpleXUIParser::endElement(const char *name)
{
- processText();
+ bool has_text = processText();
+
+ // no text, attributes, or children
+ if (!has_text && mEmptyLeafNode.back())
+ {
+ // submit this as a valueless name (even though there might be text contents we haven't seen yet)
+ mCurAttributeValueBegin = NO_VALUE_MARKER;
+ mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+ }
if (--mOutputStack.back().second == 0)
{
@@ -1276,6 +1324,7 @@ void LLSimpleXUIParser::endElement(const char *name)
mNameStack.pop_back();
}
mScope.pop_back();
+ mEmptyLeafNode.pop_back();
}
void LLSimpleXUIParser::characterData(const char *s, int len)
@@ -1322,6 +1371,12 @@ void LLSimpleXUIParser::parserError(const std::string& message)
#endif
}
+bool LLSimpleXUIParser::readNoValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return self.mCurAttributeValueBegin == NO_VALUE_MARKER;
+}
+
bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 5c613b0c69..7a748d8aea 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -116,6 +116,7 @@ private:
bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
//reader helper functions
+ static bool readNoValue(Parser& parser, void* val_ptr);
static bool readBoolValue(Parser& parser, void* val_ptr);
static bool readStringValue(Parser& parser, void* val_ptr);
static bool readU8Value(Parser& parser, void* val_ptr);
@@ -132,6 +133,7 @@ private:
static bool readSDValue(Parser& parser, void* val_ptr);
//writer helper functions
+ static bool writeNoValue(Parser& parser, const void* val_ptr, const name_stack_t&);
static bool writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t&);
static bool writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t&);
static bool writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
@@ -194,6 +196,7 @@ public:
private:
//reader helper functions
+ static bool readNoValue(Parser&, void* val_ptr);
static bool readBoolValue(Parser&, void* val_ptr);
static bool readStringValue(Parser&, void* val_ptr);
static bool readU8Value(Parser&, void* val_ptr);
@@ -218,7 +221,7 @@ private:
void endElement(const char *name);
void characterData(const char *s, int len);
bool readAttributes(const char **atts);
- void processText();
+ bool processText();
Parser::name_stack_t mNameStack;
struct XML_ParserStruct* mParser;
@@ -230,6 +233,7 @@ private:
const char* mCurAttributeValueBegin;
std::vector<S32> mTokenSizeStack;
std::vector<std::string> mScope;
+ std::vector<bool> mEmptyLeafNode;
element_start_callback_t mElementCB;
std::vector<std::pair<LLInitParam::BaseBlock*, S32> > mOutputStack;