summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llsdparam.cpp99
-rw-r--r--indra/llui/llsdparam.h5
2 files changed, 98 insertions, 6 deletions
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index bc1a0fd645..e3cadf4998 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -48,7 +48,7 @@ LLParamSDParser::LLParamSDParser()
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
- registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<F32>);
+ registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
@@ -61,7 +61,7 @@ LLParamSDParser::LLParamSDParser()
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
- if (!sdparser.mWriteSD) return false;
+ if (!sdparser.mWriteRootSD) return false;
LLSD* sd_to_write = sdparser.getSDWriteNode(name_stack);
if (!sd_to_write) return false;
@@ -81,7 +81,8 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
{
- mWriteSD = &sd;
+ mNameStack.clear();
+ mWriteRootSD = &sd;
block.serializeBlock(*this);
}
@@ -131,7 +132,97 @@ void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block
LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
{
//TODO: implement nested LLSD writing
- return mWriteSD;
+ LLSD* sd_to_write = mWriteRootSD;
+ bool new_traversal = false;
+ for (name_stack_t::const_iterator it = name_stack.begin(), prev_it = mNameStack.begin();
+ it != name_stack.end();
+ ++it)
+ {
+ bool new_array_entry = false;
+ if (prev_it == mNameStack.end())
+ {
+ new_traversal = true;
+ }
+ else
+ {
+ if (!new_traversal // have not diverged yet from previous trace
+ && prev_it->first == it->first // names match
+ && prev_it->second != it->second) // versions differ
+ {
+ // name stacks match, but version numbers differ in last place.
+ // create a different entry at this point using an LLSD array
+ new_array_entry = true;
+ }
+ if (prev_it->first != it->first // names differ
+ || prev_it->second != it->second) // versions differ
+ {
+ // at this point we have diverged from our last trace
+ // so any elements referenced here are new
+ new_traversal = true;
+ }
+ }
+
+ LLSD* child_sd = NULL;
+ if (it->first.empty())
+ {
+ if (sd_to_write->isUndefined())
+ {
+ *sd_to_write = LLSD::emptyArray();
+ child_sd = sd_to_write;
+ }
+ else if (sd_to_write->isArray())
+ {
+ child_sd = sd_to_write;
+ }
+ else
+ {
+ // go ahead and use the empty string as a map key
+ child_sd = &(*sd_to_write)[""];
+ }
+ }
+ else
+ {
+ child_sd = &(*sd_to_write)[it->first];
+ }
+
+ if (child_sd->isArray())
+ {
+ if (new_traversal)
+ {
+ // write to new element at end
+ sd_to_write = &(*child_sd)[child_sd->size()];
+ }
+ else
+ {
+ // write to last of existing elements, or first element if empty
+ sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
+ }
+ }
+ else
+ {
+ if (new_array_entry && !child_sd->isArray())
+ {
+ // copy child contents into first element of an array
+ LLSD new_array = LLSD::emptyArray();
+ new_array.append(*child_sd);
+ // assign array to slot that previously held the single value
+ *child_sd = new_array;
+ // return next element in that array
+ sd_to_write = &((*child_sd)[1]);
+ }
+ else
+ {
+ sd_to_write = child_sd;
+ }
+ }
+ if (prev_it != mNameStack.end())
+ {
+ ++prev_it;
+ }
+ }
+ mNameStack = name_stack;
+
+ return sd_to_write;
}
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index bebf202b81..97e8b58e49 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -51,7 +51,7 @@ private:
static bool writeTypedValue(Parser& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
- if (!sdparser.mWriteSD) return false;
+ if (!sdparser.mWriteRootSD) return false;
LLSD* sd_to_write = sdparser.getSDWriteNode(name_stack);
if (!sd_to_write) return false;
@@ -77,7 +77,8 @@ private:
Parser::name_stack_t mNameStack;
const LLSD* mCurReadSD;
- LLSD* mWriteSD;
+ LLSD* mWriteRootSD;
+ LLSD* mCurWriteSD;
};
template<typename T>