diff options
author | Andrew Meadows <andrew@lindenlab.com> | 2010-12-22 09:54:45 -0800 |
---|---|---|
committer | Andrew Meadows <andrew@lindenlab.com> | 2010-12-22 09:54:45 -0800 |
commit | 740bd8dbfd791bdd548064912abad8c0bf230f4c (patch) | |
tree | bd237c8141a0b5643038640f4bc24d1fb6d5fd65 /indra/llxuixml | |
parent | 049b00a6f10d50609055810b0800f49476b351d2 (diff) | |
parent | ab100825bd0064dc64b9ef8bea1c70bc04090716 (diff) |
merge
Diffstat (limited to 'indra/llxuixml')
-rw-r--r-- | indra/llxuixml/llinitparam.cpp | 8 | ||||
-rw-r--r-- | indra/llxuixml/llinitparam.h | 5 | ||||
-rw-r--r-- | indra/llxuixml/llregistry.h | 5 | ||||
-rw-r--r-- | indra/llxuixml/llxuiparser.cpp | 63 | ||||
-rw-r--r-- | indra/llxuixml/llxuiparser.h | 6 |
5 files changed, 81 insertions, 6 deletions
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 2c92539387..fcdbaa4309 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -312,6 +312,14 @@ 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 NoParamValue type, an inherently unparseable type + if (!names_left) + { + NoParamValue no_value; + return p.readValue(no_value); + } + return false; } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 8cb5bd80fc..1f9045754a 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 NoParamValue{}; + class BaseBlock; class Param @@ -303,8 +306,8 @@ namespace LLInitParam private: friend class BaseBlock; - bool mIsProvided; U16 mEnclosingBlockOffset; + bool mIsProvided; }; // various callbacks and constraints associated with an individual param diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h index eee9933739..36ce6a97b7 100644 --- a/indra/llxuixml/llregistry.h +++ b/indra/llxuixml/llregistry.h @@ -343,4 +343,9 @@ private: ScopedRegistrar* mStaticScope; }; +// helper macro for doing static registration +#define GLUED_TOKEN(x, y) x ## y +#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y) +#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE); + #endif diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 9942af6b37..72a7bb7af5 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -388,6 +388,7 @@ LLXUIParser::LLXUIParser() { if (sXUIReadFuncs.empty()) { + registerParserFuncs<LLInitParam::NoParamValue>(readNoValue, writeNoValue); registerParserFuncs<bool>(readBoolValue, writeBoolValue); registerParserFuncs<std::string>(readStringValue, writeStringValue); registerParserFuncs<U8>(readU8Value, writeU8Value); @@ -406,6 +407,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) { @@ -432,6 +434,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); @@ -444,7 +457,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(); @@ -549,6 +561,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(); @@ -567,7 +580,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) @@ -634,6 +646,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) { @@ -1049,6 +1074,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), @@ -1057,6 +1084,7 @@ LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t { if (sSimpleXUIReadFuncs.empty()) { + registerParserFuncs<LLInitParam::NoParamValue>(readNoValue); registerParserFuncs<bool>(readBoolValue); registerParserFuncs<std::string>(readStringValue); registerParserFuncs<U8>(readU8Value); @@ -1120,6 +1148,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; @@ -1127,6 +1157,8 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl return false; } + mEmptyLeafNode.pop_back(); + XML_ParserFree( mParser ); return true; } @@ -1211,8 +1243,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) @@ -1246,7 +1284,7 @@ bool LLSimpleXUIParser::readAttributes(const char **atts) return any_parsed; } -void LLSimpleXUIParser::processText() +bool LLSimpleXUIParser::processText() { if (!mTextContents.empty()) { @@ -1259,12 +1297,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) { @@ -1282,6 +1330,7 @@ void LLSimpleXUIParser::endElement(const char *name) mNameStack.pop_back(); } mScope.pop_back(); + mEmptyLeafNode.pop_back(); } void LLSimpleXUIParser::characterData(const char *s, int len) @@ -1328,6 +1377,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; |