From e61569d71422931e0d1f8d7e2f6e4db13d8b03ba Mon Sep 17 00:00:00 2001
From: Richard Nelson <richard@lindenlab.com>
Date: Mon, 10 Oct 2011 14:08:14 -0700
Subject: added compound LLSD parsing to param blocks reviewed by Leslie

---
 indra/llui/llnotifications.cpp       |  72 ++++------
 indra/llui/llsdparam.cpp             | 255 ++++++++++++++++++-----------------
 indra/llui/llsdparam.h               |  66 ++++-----
 indra/llui/tests/llurlentry_stub.cpp |   2 +-
 indra/llui/tests/llurlentry_test.cpp |   1 -
 indra/llui/tests/llurlmatch_test.cpp |   4 +-
 indra/llxuixml/llinitparam.cpp       |  52 ++++---
 indra/llxuixml/llinitparam.h         | 155 ++++++++++++---------
 indra/llxuixml/llxuiparser.cpp       |  50 ++++---
 indra/llxuixml/llxuiparser.h         |  36 +++--
 indra/newview/llappviewer.cpp        |  47 +++----
 11 files changed, 376 insertions(+), 364 deletions(-)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index ffe5908a9d..8f7025a9a6 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -46,6 +46,7 @@
 
 #include <algorithm>
 #include <boost/regex.hpp>
+#include <boost/foreach.hpp>
 
 
 const std::string NOTIFICATION_PERSIST_VERSION = "0.93";
@@ -416,23 +417,17 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
 		mSoundEffect = LLUUID(LLUI::sSettingGroups["config"]->getString(p.sound));
 	}
 
-	for(LLInitParam::ParamIterator<LLNotificationTemplate::UniquenessContext>::const_iterator it = p.unique.contexts.begin(),
-			end_it = p.unique.contexts.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(const LLNotificationTemplate::UniquenessContext& context, p.unique.contexts)
 	{
-		mUniqueContext.push_back(it->value);
+		mUniqueContext.push_back(context.value);
 	}
 	
 	lldebugs << "notification \"" << mName << "\": tag count is " << p.tags.size() << llendl;
 	
-	for(LLInitParam::ParamIterator<LLNotificationTemplate::Tag>::const_iterator it = p.tags.begin(),
-			end_it = p.tags.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(const LLNotificationTemplate::Tag& tag, p.tags)
 	{
-		lldebugs << "    tag \"" << std::string(it->value) << "\"" << llendl;
-		mTags.push_back(it->value);
+		lldebugs << "    tag \"" << std::string(tag.value) << "\"" << llendl;
+		mTags.push_back(tag.value);
 	}
 
 	mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form));
@@ -1397,14 +1392,12 @@ void replaceFormText(LLNotificationForm::Params& form, const std::string& patter
 	{
 		form.ignore.text = replace;
 	}
-	for (LLInitParam::ParamIterator<LLNotificationForm::FormElement>::iterator it = form.form_elements.elements.begin(),
-			end_it = form.form_elements.elements.end();
-		it != end_it;
-		++it)
+
+	BOOST_FOREACH(LLNotificationForm::FormElement& element, form.form_elements.elements)
 	{
-		if (it->button.isChosen() && it->button.text() == pattern)
+		if (element.button.isChosen() && element.button.text() == pattern)
 		{
-			it->button.text = replace;
+			element.button.text = replace;
 		}
 	}
 }
@@ -1453,48 +1446,42 @@ bool LLNotifications::loadTemplates()
 
 	mTemplates.clear();
 
-	for(LLInitParam::ParamIterator<LLNotificationTemplate::GlobalString>::const_iterator it = params.strings.begin(), end_it = params.strings.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(LLNotificationTemplate::GlobalString& string, params.strings)
 	{
-		mGlobalStrings[it->name] = it->value;
+		mGlobalStrings[string.name] = string.value;
 	}
 
 	std::map<std::string, LLNotificationForm::Params> form_templates;
 
-	for(LLInitParam::ParamIterator<LLNotificationTemplate::Template>::const_iterator it = params.templates.begin(), end_it = params.templates.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(LLNotificationTemplate::Template& notification_template, params.templates)
 	{
-		form_templates[it->name] = it->form;
+		form_templates[notification_template.name] = notification_template.form;
 	}
 
-	for(LLInitParam::ParamIterator<LLNotificationTemplate::Params>::iterator it = params.notifications.begin(), end_it = params.notifications.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(LLNotificationTemplate::Params& notification, params.notifications)
 	{
-		if (it->form_ref.form_template.isChosen())
+		if (notification.form_ref.form_template.isChosen())
 		{
 			// replace form contents from template
-			it->form_ref.form = form_templates[it->form_ref.form_template.name];
-			if(it->form_ref.form_template.yes_text.isProvided())
+			notification.form_ref.form = form_templates[notification.form_ref.form_template.name];
+			if(notification.form_ref.form_template.yes_text.isProvided())
 			{
-				replaceFormText(it->form_ref.form, "$yestext", it->form_ref.form_template.yes_text);
+				replaceFormText(notification.form_ref.form, "$yestext", notification.form_ref.form_template.yes_text);
 			}
-			if(it->form_ref.form_template.no_text.isProvided())
+			if(notification.form_ref.form_template.no_text.isProvided())
 			{
-				replaceFormText(it->form_ref.form, "$notext", it->form_ref.form_template.no_text);
+				replaceFormText(notification.form_ref.form, "$notext", notification.form_ref.form_template.no_text);
 			}
-			if(it->form_ref.form_template.cancel_text.isProvided())
+			if(notification.form_ref.form_template.cancel_text.isProvided())
 			{
-				replaceFormText(it->form_ref.form, "$canceltext", it->form_ref.form_template.cancel_text);
+				replaceFormText(notification.form_ref.form, "$canceltext", notification.form_ref.form_template.cancel_text);
 			}
-			if(it->form_ref.form_template.ignore_text.isProvided())
+			if(notification.form_ref.form_template.ignore_text.isProvided())
 			{
-				replaceFormText(it->form_ref.form, "$ignoretext", it->form_ref.form_template.ignore_text);
+				replaceFormText(notification.form_ref.form, "$ignoretext", notification.form_ref.form_template.ignore_text);
 			}
 		}
-		mTemplates[it->name] = LLNotificationTemplatePtr(new LLNotificationTemplate(*it));
+		mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification));
 	}
 
 	return true;
@@ -1517,12 +1504,9 @@ bool LLNotifications::loadVisibilityRules()
 
 	mVisibilityRules.clear();
 
-	for(LLInitParam::ParamIterator<LLNotificationVisibilityRule::Rule>::iterator it = params.rules.begin(), 
-			end_it = params.rules.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(LLNotificationVisibilityRule::Rule& rule, params.rules)
 	{
-		mVisibilityRules.push_back(LLNotificationVisibilityRulePtr(new LLNotificationVisibilityRule(*it)));
+		mVisibilityRules.push_back(LLNotificationVisibilityRulePtr(new LLNotificationVisibilityRule(rule)));
 	}
 
 	return true;
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 4b69360e33..83bed3e745 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -34,6 +34,7 @@
 static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
 static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
 static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+static const LLSD NO_VALUE_MARKER;
 
 //
 // LLParamSDParser
@@ -60,29 +61,32 @@ LLParamSDParser::LLParamSDParser()
 }
 
 // special case handling of U32 due to ambiguous LLSD::assign overload
-bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
+bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, 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;
+	LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, std::make_pair(name_stack.begin(), name_stack.end()));
+	sd_to_write.assign((S32)*((const U32*)val_ptr));
 
-	sd_to_write->assign((S32)*((const U32*)val_ptr));
 	return true;
 }
 
-bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
+bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, 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;
+	LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, std::make_pair(name_stack.begin(), name_stack.end()));
 
 	return true;
 }
 
+void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
+{
+	mCurReadSD = &sd;
+	block.submitValue(name_stack, *this);
+}
 
 void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
 {
@@ -90,7 +94,8 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
 	mNameStack.clear();
 	setParseSilently(silent);
 
-	readSDValues(sd, block);
+	LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
+	//readSDValues(sd, block);
 }
 
 void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
@@ -100,43 +105,6 @@ 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())
-	{
-		for (LLSD::map_const_iterator it = sd.beginMap();
-			it != sd.endMap();
-			++it)
-		{
-			mNameStack.push_back(make_pair(it->first, newParseGeneration()));
-			readSDValues(it->second, block);
-			mNameStack.pop_back();
-		}
-	}
-	else if (sd.isArray())
-	{
-		for (LLSD::array_const_iterator it = sd.beginArray();
-			it != sd.endArray();
-			++it)
-		{
-			mNameStack.back().second = newParseGeneration();
-			readSDValues(*it, block);
-		}
-	}
-	else if (sd.isUndefined())
-	{
-		mCurReadSD = &NO_VALUE_MARKER;
-		block.submitValue(mNameStack, *this);
-	}
-	else
-	{
-		mCurReadSD = &sd;
-		block.submitValue(mNameStack, *this);
-	}
-}
-
 /*virtual*/ std::string LLParamSDParser::getCurrentElementName()
 {
 	std::string full_name = "sd";
@@ -150,81 +118,6 @@ void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block
 	return full_name;
 }
 
-LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
-{
-	//TODO: implement nested LLSD writing
-	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 = it->first.empty() ? sd_to_write : &(*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;
-	
-	//llinfos << ll_pretty_print_sd(*mWriteRootSD) << llendl;
-	return sd_to_write;
-}
 
 bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
 {
@@ -312,3 +205,125 @@ bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
 	*((LLSD*)val_ptr) = *self.mCurReadSD;
     return true;
 }
+
+// static
+LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
+{
+	LLSD* sd_to_write = &input;
+	
+	for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
+		it != name_stack_range.second;
+		++it)
+	{
+		bool new_traversal = it->second;
+
+		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*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_traversal 
+				&& child_sd->isDefined() 
+				&& !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;
+			}
+		}
+		it->second = false;
+	}
+	
+	return *sd_to_write;
+}
+
+//static
+void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
+{
+	if (sd.isMap())
+	{
+		for (LLSD::map_const_iterator it = sd.beginMap();
+			it != sd.endMap();
+			++it)
+		{
+			stack.push_back(make_pair(it->first, true));
+			readSDValues(cb, it->second, stack);
+			stack.pop_back();
+		}
+	}
+	else if (sd.isArray())
+	{
+		for (LLSD::array_const_iterator it = sd.beginArray();
+			it != sd.endArray();
+			++it)
+		{
+			stack.back().second = true;
+			readSDValues(cb, *it, stack);
+		}
+	}
+	else if (sd.isUndefined())
+	{
+		if (!cb.empty())
+		{
+			cb(NO_VALUE_MARKER, stack);
+		}
+	}
+	else
+	{
+		if (!cb.empty())
+		{
+			cb(sd, stack);
+		}
+	}
+}
+
+namespace LLInitParam
+{
+	// LLSD specialization
+	// block param interface
+	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
+	{
+		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
+
+		LLSD::String string;
+
+		if (p.readValue<LLSD::String>(string))
+		{
+			sd = string;
+			return true;
+		}
+		return false;
+	}
+
+	//static
+	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
+	{
+		p.writeValue<LLSD::String>(sd.asString(), name_stack);
+	}
+
+	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t name_stack, const BaseBlock* diff_block) const
+	{
+		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
+		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue);
+	}
+}
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index a371c28f68..265993ffb5 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -29,6 +29,15 @@
 #define LL_LLSDPARAM_H
 
 #include "llinitparam.h"
+#include "boost/function.hpp"
+
+struct LLParamSDParserUtilities
+{
+	static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
+
+	typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
+	static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack = LLInitParam::Parser::name_stack_t());
+};
 
 class LLParamSDParser 
 :	public LLInitParam::Parser
@@ -45,25 +54,22 @@ public:
 	/*virtual*/ std::string getCurrentElementName();
 
 private:
-	void readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block);
+	void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
 
 	template<typename T>
-	static bool writeTypedValue(Parser& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
+	static bool writeTypedValue(Parser& parser, const void* val_ptr, 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;
+		LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, std::make_pair(name_stack.begin(), name_stack.end()));
 
-		sd_to_write->assign(*((const T*)val_ptr));
+		sd_to_write.assign(*((const T*)val_ptr));
 		return true;
 	}
 
-	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 writeFlag(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack);
+	static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
+	static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
 
 	static bool readFlag(Parser& parser, void* val_ptr);
 	static bool readS32(Parser& parser, void* val_ptr);
@@ -85,29 +91,29 @@ private:
 
 template<typename T>
 class LLSDParamAdapter : public T
+{
+public:
+	LLSDParamAdapter() {}
+	LLSDParamAdapter(const LLSD& sd)
 	{
-	public:
-		LLSDParamAdapter() {}
-		LLSDParamAdapter(const LLSD& sd)
-		{
-			LLParamSDParser parser;
-			parser.readSD(sd, *this);
-		}
-
-		operator LLSD() const
-		{
-			LLParamSDParser parser;
-			LLSD sd;
-			parser.writeSD(sd, *this);
-			return sd;
-		}
+		LLParamSDParser parser;
+		parser.readSD(sd, *this);
+	}
+
+	operator LLSD() const
+	{
+		LLParamSDParser parser;
+		LLSD sd;
+		parser.writeSD(sd, *this);
+		return sd;
+	}
 		
-		LLSDParamAdapter(const T& val)
-		: T(val)
-		{
-			T::operator=(val);
-		}
-	};
+	LLSDParamAdapter(const T& val)
+	: T(val)
+	{
+		T::operator=(val);
+	}
+};
 
 #endif // LL_LLSDPARAM_H
 
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index d522123260..c8303bfc89 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -124,7 +124,7 @@ namespace LLInitParam
 	{
 		descriptor.mCurrentBlockPtr = this;
 	}
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; }
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; }
 	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {}
 	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; }
 	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 2f814f4200..c1fb050206 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -72,7 +72,6 @@ S32 LLUIImage::getHeight() const
 
 namespace LLInitParam
 {
-	S32 Parser::sNextParseGeneration = 0;
 	BlockDescriptor::BlockDescriptor() {}
 	ParamDescriptor::ParamDescriptor(param_handle_t p, 
 						merge_func_t merge_func, 
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index fb6a2eabf1..9dbccf125a 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -66,8 +66,6 @@ namespace LLInitParam
 	BaseBlock::BaseBlock() {}
 	BaseBlock::~BaseBlock() {}
 
-	S32 Parser::sNextParseGeneration = 0;
-
 	BlockDescriptor::BlockDescriptor() {}
 	ParamDescriptor::ParamDescriptor(param_handle_t p, 
 						merge_func_t merge_func, 
@@ -98,7 +96,7 @@ namespace LLInitParam
 		mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
 	}
 
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; }
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; }
 	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {}
 	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; }
 	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index 99016205c8..2520502cf1 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -62,7 +62,6 @@ namespace LLInitParam
 		mInspectFunc(inspect_func),
 		mMinCount(min_count),
 		mMaxCount(max_count),
-		mGeneration(0),
 		mUserData(NULL)
 	{}
 
@@ -75,7 +74,6 @@ namespace LLInitParam
 		mInspectFunc(NULL),
 		mMinCount(0),
 		mMaxCount(0),
-		mGeneration(0),
 		mUserData(NULL)
 	{}
 
@@ -87,8 +85,6 @@ namespace LLInitParam
 	//
 	// Parser
 	//
-	S32 Parser::sNextParseGeneration = 0;
-
 	Parser::~Parser()
 	{}
 
@@ -162,9 +158,9 @@ namespace LLInitParam
 		return (param_address - baseblock_address);
 	}
 
-	bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent)
+	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
 	{
-		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), -1))
+		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
 		{
 			if (!silent)
 			{
@@ -213,8 +209,7 @@ namespace LLInitParam
 				// each param descriptor remembers its serial number
 				// so we can inspect the same param under different names
 				// and see that it has the same number
-				(*it)->mGeneration = parser.newParseGeneration();
-				name_stack.push_back(std::make_pair("", (*it)->mGeneration));
+				name_stack.push_back(std::make_pair("", true));
 				serialize_func(*param, parser, name_stack, diff_param);
 				name_stack.pop_back();
 			}
@@ -250,12 +245,7 @@ namespace LLInitParam
 					continue;
 				}
 
-				if (!duplicate)
-				{
-					it->second->mGeneration = parser.newParseGeneration();
-				}
-
-				name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
 				serialize_func(*param, parser, name_stack, diff_param);
 				name_stack.pop_back();
@@ -278,8 +268,7 @@ namespace LLInitParam
 			ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
 			if (inspect_func)
 			{
-				(*it)->mGeneration = parser.newParseGeneration();
-				name_stack.push_back(std::make_pair("", (*it)->mGeneration));
+				name_stack.push_back(std::make_pair("", true));
 				inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
 				name_stack.pop_back();
 			}
@@ -307,11 +296,7 @@ namespace LLInitParam
 					}
 				}
 
-				if (!duplicate)
-				{
-					it->second->mGeneration = parser.newParseGeneration();
-				}
-				name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
 				inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
 				name_stack.pop_back();
 			}
@@ -320,16 +305,18 @@ namespace LLInitParam
 		return true;
 	}
 
-	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 parent_generation)
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
 	{
 		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-		bool names_left = name_stack.first != name_stack.second;
+		bool names_left = name_stack_range.first != name_stack_range.second;
 
-		S32 parse_generation = name_stack.first == name_stack.second ? -1 : name_stack.first->second;
+		bool new_name = names_left
+						? name_stack_range.first->second
+						: true;
 
 		if (names_left)
 		{
-			const std::string& top_name = name_stack.first->first;
+			const std::string& top_name = name_stack_range.first->first;
 
 			ParamDescriptor::deserialize_func_t deserialize_func = NULL;
 			Param* paramp = NULL;
@@ -341,9 +328,18 @@ namespace LLInitParam
 				paramp = getParamFromHandle(found_it->second->mParamHandle);
 				deserialize_func = found_it->second->mDeserializeFunc;
 					
-				Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);
+				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
 				++new_name_stack.first;
-				return deserialize_func(*paramp, p, new_name_stack, parse_generation);
+				if (deserialize_func(*paramp, p, new_name_stack, new_name))
+				{
+					// value is no longer new, we know about it now
+					name_stack_range.first->second = false;
+					return true;
+				}
+				else
+				{
+					return false;
+				}
 			}
 		}
 
@@ -355,7 +351,7 @@ namespace LLInitParam
 			Param* paramp = getParamFromHandle((*it)->mParamHandle);
 			ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
 
-			if (deserialize_func && deserialize_func(*paramp, p, name_stack, parse_generation))
+			if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
 			{
 				return true;
 			}
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index 1a131d15a3..9245f588d9 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -214,13 +214,13 @@ namespace LLInitParam
 			}
 		};
 
-		typedef std::vector<std::pair<std::string, S32> >								name_stack_t;
-		typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator>	name_stack_range_t;
-		typedef std::vector<std::string>												possible_values_t;
+		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
+		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
+		typedef std::vector<std::string>									possible_values_t;
 
 		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
-		typedef bool (*parser_write_func_t)(Parser& parser, const void*, const name_stack_t&);
-		typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
+		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
+		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
 		typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID>		parser_read_func_map_t;
 		typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID>		parser_write_func_map_t;
@@ -228,7 +228,6 @@ namespace LLInitParam
 
 		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),
-			mParseGeneration(sNextParseGeneration),
 			mParserReadFuncs(&read_map),
 			mParserWriteFuncs(&write_map),
 			mParserInspectFuncs(&inspect_map)
@@ -245,7 +244,7 @@ namespace LLInitParam
 		    return false;
 	    }
 
-		template <typename T> bool writeValue(const T& param, const name_stack_t& name_stack)
+		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
 		{
 		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
 		    if (found_it != mParserWriteFuncs->end())
@@ -256,7 +255,7 @@ namespace LLInitParam
 		}
 
 		// dispatch inspection to registered inspection functions, for each parameter in a param block
-		template <typename T> bool inspectValue(const name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
+		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 		{
 		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
 		    if (found_it != mParserInspectFuncs->end())
@@ -272,10 +271,6 @@ namespace LLInitParam
 		virtual void parserError(const std::string& message);
 		void setParseSilently(bool silent) { mParseSilently = silent; }
 
-		S32 getParseGeneration() { return mParseGeneration; }
-		S32 newParseGeneration() { return mParseGeneration = ++sNextParseGeneration; }
-
-
 	protected:
 		template <typename T>
 		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
@@ -296,9 +291,6 @@ namespace LLInitParam
 		parser_read_func_map_t*		mParserReadFuncs;
 		parser_write_func_map_t*	mParserWriteFuncs;
 		parser_inspect_func_map_t*	mParserInspectFuncs;
-		S32	mParseGeneration;
-
-		static S32					sNextParseGeneration;
 	};
 
 	class BaseBlock;
@@ -341,7 +333,7 @@ namespace LLInitParam
 		};
 
 		typedef bool(*merge_func_t)(Param&, const Param&, bool);
-		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, S32);
+		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
 		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
 		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
 		typedef bool(*validation_func_t)(const Param*);
@@ -366,7 +358,6 @@ namespace LLInitParam
 		validation_func_t	mValidationFunc;
 		S32					mMinCount;
 		S32					mMaxCount;
-		S32					mGeneration;
 		S32					mNumRefs;
 		UserData*			mUserData;
 	};
@@ -447,7 +438,7 @@ namespace LLInitParam
 
 		BaseBlock();
 		virtual ~BaseBlock();
-		bool submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
+		bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
 
 		param_handle_t getHandleFromParam(const Param* param) const;
 		bool validateBlock(bool emit_errors = true) const;
@@ -473,7 +464,7 @@ namespace LLInitParam
 
 		S32 getLastChangeVersion() const { return mChangeVersion; }
 
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation);
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
 		void serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 
@@ -593,8 +584,7 @@ namespace LLInitParam
 			mKeyVersion(0),
 			mValidatedVersion(-1),
 			mValidated(false)
-		{
-		}
+		{}
 
 		void setValue(value_assignment_t val)
 		{
@@ -672,11 +662,11 @@ namespace LLInitParam
 
 		bool isProvided() const { return Param::anyProvided(); }
 
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) 
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 		{ 
 			self_t& typed_param = static_cast<self_t&>(param);
 			// no further names in stack, attempt to parse value now
-			if (name_stack.first == name_stack.second)
+			if (name_stack_range.first == name_stack_range.second)
 			{
 				if (parser.readValue(typed_param.getValue()))
 				{
@@ -715,7 +705,7 @@ namespace LLInitParam
 
 			if (!name_stack.empty())
 			{
-				name_stack.back().second = parser.newParseGeneration();
+				name_stack.back().second = true;
 			}
 
 			std::string key = typed_param.getValueName();
@@ -811,11 +801,11 @@ namespace LLInitParam
 			}
 		}
 
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) 
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 		{ 
 			self_t& typed_param = static_cast<self_t&>(param);
 			// attempt to parse block...
-			if(typed_param.deserializeBlock(parser, name_stack, generation))
+			if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
 			{
 				typed_param.clearValueName();
 				typed_param.enclosingBlock().paramChanged(param, true);
@@ -851,7 +841,7 @@ namespace LLInitParam
 
 			if (!name_stack.empty())
 			{
-				name_stack.back().second = parser.newParseGeneration();
+				name_stack.back().second = true;
 			}
 
 			std::string key = typed_param.getValueName();
@@ -943,7 +933,7 @@ namespace LLInitParam
 	public:
 		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t;
 		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t;
-		typedef typename std::vector<param_value_t>					container_t;
+		typedef typename std::vector<param_value_t>							container_t;
 		typedef const container_t&											value_assignment_t;
 
 		typedef VALUE_TYPE													value_t;
@@ -970,12 +960,12 @@ namespace LLInitParam
 
 		bool isProvided() const { return Param::anyProvided(); }
 
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) 
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, bool new_name)
 		{ 
 			self_t& typed_param = static_cast<self_t&>(param);
 			value_t value;
 			// no further names in stack, attempt to parse value now
-			if (name_stack.first == name_stack.second)
+			if (name_stack_range.first == name_stack_range.second)
 			{
 				// attempt to read value directly
 				if (parser.readValue(value))
@@ -1015,7 +1005,7 @@ namespace LLInitParam
 				++it)
 			{
 				std::string key = it->getValue();
-				name_stack.back().second = parser.newParseGeneration();
+				name_stack.back().second = true;
 
 				if(key.empty())
 				// not parsed via name values, write out value directly
@@ -1132,8 +1122,7 @@ namespace LLInitParam
 		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;
 
 		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr),
-			mLastParseGeneration(0)
+		:	Param(block_descriptor.mCurrentBlockPtr)
 		{
 			std::copy(value.begin(), value.end(), back_inserter(mValues));
 
@@ -1153,13 +1142,12 @@ namespace LLInitParam
 
 		bool isProvided() const { return Param::anyProvided(); }
 
-		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) 
+		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
 		{ 
 			self_t& typed_param = static_cast<self_t&>(param);
 			bool new_value = false;
 
-			if (generation != typed_param.mLastParseGeneration 
-				|| typed_param.mValues.empty())
+			if (new_name || typed_param.mValues.empty())
 			{
 				new_value = true;
 				typed_param.mValues.push_back(value_t());
@@ -1168,12 +1156,8 @@ namespace LLInitParam
 			param_value_t& value = typed_param.mValues.back();
 
 			// attempt to parse block...
-			if(value.deserializeBlock(parser, name_stack, generation))
+			if(value.deserializeBlock(parser, name_stack_range, new_name))
 			{
-				if (new_value)
-				{	// successfully parsed new value, let's keep it
-					typed_param.mLastParseGeneration = generation;
-				}
 				typed_param.enclosingBlock().paramChanged(param, true);
 				typed_param.setProvided(true);
 				return true;
@@ -1187,11 +1171,6 @@ namespace LLInitParam
 					// try to parse a per type named value
 					if (name_value_lookup_t::getValueFromName(name, value.getValue()))
 					{
-						if (new_value)
-						{	// successfully parsed new value, let's keep it
-							typed_param.mLastParseGeneration = generation;
-						}
-
 						typed_param.mValues.back().setValueName(name);
 						typed_param.mValues.back().mKeyVersion = value.getLastChangeVersion();
 						typed_param.enclosingBlock().paramChanged(param, true);
@@ -1219,7 +1198,7 @@ namespace LLInitParam
 				it != end_it;
 				++it)
 			{
-				name_stack.back().second = parser.newParseGeneration();
+				name_stack.back().second = true;
 
 				std::string key = it->getValueName();
 				if (!key.empty() && it->mKeyVersion == it->getLastChangeVersion())
@@ -1317,8 +1296,6 @@ namespace LLInitParam
 		}
 
 		container_t			mValues;
-
-		S32			mLastParseGeneration;
 	};
 
 	template <typename DERIVED_BLOCK>
@@ -1625,9 +1602,9 @@ namespace LLInitParam
 				}
 			}
 			
-			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 			{
-				if (name_stack.first == name_stack.second)
+				if (name_stack_range.first == name_stack_range.second)
 				{
 					//std::string message = llformat("Deprecated value %s ignored", getName().c_str());
 					//parser.parserWarning(message);
@@ -1669,18 +1646,16 @@ namespace LLInitParam
 		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t;
 
 		BatchBlock()
-		:	mLastParseGeneration(-1)
 		{}
 
-		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation)
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
 		{
-			if (generation != mLastParseGeneration)
+			if (new_name)
 			{
 				// reset block
 				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
-				mLastParseGeneration = generation;
 			}
-			return super_t::deserializeBlock(p, name_stack, generation);
+			return super_t::deserializeBlock(p, name_stack_range, new_name);
 		}
 
 		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
@@ -1688,7 +1663,6 @@ namespace LLInitParam
 			if (overwrite)
 			{
 				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
-				mLastParseGeneration = -1;
 				// merge individual parameters into destination
 				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite);
 			}
@@ -1700,19 +1674,20 @@ namespace LLInitParam
 			static DERIVED_BLOCK default_value;
 			return default_value;
 		}
-
-		S32 mLastParseGeneration;
 	};
 
+	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class
+	// and not the derived class with the actual params
 	template<typename DERIVED_BLOCK,
 			typename BASE_BLOCK,
 			typename NAME_VALUE_LOOKUP>
 	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>,
 					NAME_VALUE_LOOKUP,
 					true>
-	:	public Param,
+	:	public NAME_VALUE_LOOKUP,
 		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK>
 	{
+	public:
 		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t;
 		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t;
 
@@ -1734,7 +1709,6 @@ namespace LLInitParam
 		void setValue(value_assignment_t val)
 		{
 			*this = val;
-			block_t::mLastParseGeneration = -1;
 		}
 
 		value_assignment_t getValue() const
@@ -1764,6 +1738,59 @@ namespace LLInitParam
 		mutable bool 	mValidated; // lazy validation flag
 	};
 
+	template <>
+	class ParamValue <LLSD,
+					TypeValues<LLSD>,
+					false>
+	:	public TypeValues<LLSD>,
+		public BaseBlock
+	{
+	public:
+		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t;
+		typedef const LLSD&	value_assignment_t;
+
+		ParamValue()
+		:	mKeyVersion(0),
+			mValidatedVersion(-1),
+			mValidated(false)
+		{}
+
+		ParamValue(value_assignment_t other)
+		:	mValue(other),
+			mKeyVersion(0),
+			mValidatedVersion(-1),
+			mValidated(false)
+		{}
+
+		void setValue(value_assignment_t val) { mValue = val; }
+
+		value_assignment_t getValue() const { return mValue; }
+		LLSD& getValue() { return mValue; }
+
+		operator value_assignment_t() const { return mValue; }
+		value_assignment_t operator()() const { return mValue; }
+		
+		S32 			mKeyVersion;
+
+		// block param interface
+		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
+		void serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const;
+		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+		{
+			//TODO: implement LLSD params as schema type Any
+			return true;
+		}
+
+	protected:
+		mutable S32 	mValidatedVersion;
+		mutable bool 	mValidated; // lazy validation flag
+
+	private:
+		static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
+
+		LLSD mValue;
+	};
+
 	template<typename T>
 	class CustomParamValue
 	:	public Block<ParamValue<T, TypeValues<T> > >,
@@ -1790,11 +1817,11 @@ namespace LLInitParam
 			mValidated(false)
 		{}
 
-		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack, S32 generation)
+		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
 		{
 			derived_t& typed_param = static_cast<derived_t&>(*this);
 			// try to parse direct value T
-			if (name_stack.first == name_stack.second)
+			if (name_stack_range.first == name_stack_range.second)
 			{
 				if(parser.readValue(typed_param.mValue))
 				{
@@ -1808,7 +1835,7 @@ namespace LLInitParam
 			}
 
 			// fall back on parsing block components for T
-			return typed_param.BaseBlock::deserializeBlock(parser, name_stack, generation);
+			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
 		}
 
 		void serializeBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index c60f656c2c..1bb550d98f 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -513,7 +513,6 @@ static 	LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;
 //
 LLXUIParser::LLXUIParser()
 :	Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
-	mLastWriteGeneration(-1),
 	mCurReadDepth(0)
 {
 	if (sXUIReadFuncs.empty())
@@ -583,7 +582,7 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
 	if (!text_contents.empty())
 	{
 		mCurReadNode = nodep;
-		mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
+		mNameStack.push_back(std::make_pair(std::string("value"), true));
 		// child nodes are not necessarily valid parameters (could be a child widget)
 		// so don't complain once we've recursed
 		if (!block.submitValue(mNameStack, *this, true))
@@ -618,7 +617,7 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
 		// since there is no widget named "rect"
 		if (child_name.find(".") == std::string::npos) 
 		{
-			mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
+			mNameStack.push_back(std::make_pair(child_name, true));
 			num_tokens_pushed++;
 		}
 		else
@@ -654,7 +653,7 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
 			// copy remaining tokens on to our running token list
 			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
 			{
-				mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+				mNameStack.push_back(std::make_pair(*token_to_push, true));
 				num_tokens_pushed++;
 			}
 		}
@@ -704,7 +703,7 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo
 		// copy remaining tokens on to our running token list
 		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
 		{
-			mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+			mNameStack.push_back(std::make_pair(*token_to_push, true));
 			num_tokens_pushed++;
 		}
 
@@ -728,7 +727,7 @@ void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &bloc
 }
 
 // go from a stack of names to a specific XML node
-LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
+LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)
 {
 	name_stack_t name_stack;
 	for (name_stack_t::const_iterator it = stack.begin();
@@ -781,7 +780,7 @@ bool LLXUIParser::readFlag(Parser& parser, void* val_ptr)
 	return self.mCurReadNode == DUMMY_NODE;
 }
 
-bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	// just create node
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
@@ -798,7 +797,7 @@ bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
 	return success;
 }
 
-bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -817,7 +816,7 @@ bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
 	return true;
 }
 
-bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -855,7 +854,7 @@ bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
 }
 
-bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -879,7 +878,7 @@ bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -903,7 +902,7 @@ bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -927,7 +926,7 @@ bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -945,7 +944,7 @@ bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
 }
 
-bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -963,7 +962,7 @@ bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
 }
 
-bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -981,7 +980,7 @@ bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
 }
 
-bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -999,7 +998,7 @@ bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
 }
 
-bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -1023,7 +1022,7 @@ bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -1050,7 +1049,7 @@ bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -1079,7 +1078,7 @@ bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 	LLXMLNodePtr node = self.getNode(stack);
@@ -1098,7 +1097,7 @@ bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
 	return true;
 }
 
-bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
 {
 	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
 
@@ -1207,7 +1206,6 @@ const char* NO_VALUE_MARKER = "no_value";
 
 LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
 :	Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
-	mLastWriteGeneration(-1),
 	mCurReadDepth(0),
 	mElementCB(element_cb)
 {
@@ -1338,7 +1336,7 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
 	{	// compound attribute
 		if (child_name.find(".") == std::string::npos) 
 		{
-			mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
+			mNameStack.push_back(std::make_pair(child_name, true));
 			num_tokens_pushed++;
 			mScope.push_back(child_name);
 		}
@@ -1365,7 +1363,7 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
 			// copy remaining tokens on to our running token list
 			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
 			{
-				mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+				mNameStack.push_back(std::make_pair(*token_to_push, true));
 				num_tokens_pushed++;
 			}
 			mScope.push_back(mNameStack.back().first);
@@ -1398,7 +1396,7 @@ bool LLSimpleXUIParser::readAttributes(const char **atts)
 		// copy remaining tokens on to our running token list
 		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
 		{
-			mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+			mNameStack.push_back(std::make_pair(*token_to_push, true));
 			num_tokens_pushed++;
 		}
 
@@ -1420,7 +1418,7 @@ bool LLSimpleXUIParser::processText()
 		LLStringUtil::trim(mTextContents);
 		if (!mTextContents.empty())
 		{
-			mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
+			mNameStack.push_back(std::make_pair(std::string("value"), true));
 			mCurAttributeValueBegin = mTextContents.c_str();
 			mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
 			mNameStack.pop_back();
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 42a79b4100..e0402523da 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -133,23 +133,23 @@ private:
 	static bool readSDValue(Parser& parser, void* val_ptr);
 
 	//writer helper functions
-	static bool writeFlag(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&);
-	static bool writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
-	static bool writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
-
-	LLXMLNodePtr getNode(const name_stack_t& stack);
+	static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&);
+	static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&);
+
+	LLXMLNodePtr getNode(name_stack_t& stack);
 
 private:
 	Parser::name_stack_t			mNameStack;
@@ -159,7 +159,6 @@ private:
 	
 	typedef std::map<S32, LLXMLNodePtr>	out_nodes_t;
 	out_nodes_t						mOutNodes;
-	S32								mLastWriteGeneration;
 	LLXMLNodePtr					mLastWrittenChild;
 	S32								mCurReadDepth;
 	std::string						mCurFileName;
@@ -226,7 +225,6 @@ private:
 
 	Parser::name_stack_t			mNameStack;
 	struct XML_ParserStruct*		mParser;
-	S32								mLastWriteGeneration;
 	LLXMLNodePtr					mLastWrittenChild;
 	S32								mCurReadDepth;
 	std::string						mCurFileName;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index fa0b392f1b..5077a0a596 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -109,6 +109,7 @@
 
 // Third party library includes
 #include <boost/bind.hpp>
+#include <boost/foreach.hpp>
 
 
 #if LL_WINDOWS
@@ -2041,42 +2042,37 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 		llerrs << "Invalid settings location list" << llendl;
 	}
 
-	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(const SettingsGroup& group, mSettingsLocationList->groups)
 	{
 		// skip settings groups that aren't the one we requested
-		if (it->name() != location_key) continue;
+		if (group.name() != location_key) continue;
 
-		ELLPath path_index = (ELLPath)it->path_index();
+		ELLPath path_index = (ELLPath)group.path_index();
 		if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
 		{
 			llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
 			return false;
 		}
 
-		LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
-		for (file_it = it->files.begin(), end_file_it = it->files.end();
-			file_it != end_file_it;
-			++file_it)
+		BOOST_FOREACH(const SettingsFile& file, group.files)
 		{
-			llinfos << "Attempting to load settings for the group " << file_it->name()
+			llinfos << "Attempting to load settings for the group " << file.name()
 			    << " - from location " << location_key << llendl;
 
-			LLControlGroup* settings_group = LLControlGroup::getInstance(file_it->name);
+			LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);
 			if(!settings_group)
 			{
-				llwarns << "No matching settings group for name " << file_it->name() << llendl;
+				llwarns << "No matching settings group for name " << file.name() << llendl;
 				continue;
 			}
 
 			std::string full_settings_path;
 
-			if (file_it->file_name_setting.isProvided() 
-				&& gSavedSettings.controlExists(file_it->file_name_setting))
+			if (file.file_name_setting.isProvided() 
+				&& gSavedSettings.controlExists(file.file_name_setting))
 			{
 				// try to find filename stored in file_name_setting control
-				full_settings_path = gSavedSettings.getString(file_it->file_name_setting);
+				full_settings_path = gSavedSettings.getString(file.file_name_setting);
 				if (full_settings_path.empty())
 				{
 					continue;
@@ -2090,16 +2086,16 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 			else
 			{
 				// by default, use specified file name
-				full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file_it->file_name());
+				full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
 			}
 
-			if(settings_group->loadFromFile(full_settings_path, set_defaults, file_it->persistent))
+			if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
 			{	// success!
 				llinfos << "Loaded settings file " << full_settings_path << llendl;
 			}
 			else
 			{	// failed to load
-				if(file_it->required)
+				if(file.required)
 				{
 					llerrs << "Error: Cannot load required settings file from: " << full_settings_path << llendl;
 					return false;
@@ -2122,20 +2118,15 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
 											 const std::string& file)
 {
-	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
-		it != end_it;
-		++it)
+	BOOST_FOREACH(const SettingsGroup& group, mSettingsLocationList->groups)
 	{
-		if (it->name() == location_key)
+		if (group.name() == location_key)
 		{
-			LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
-			for (file_it = it->files.begin(), end_file_it = it->files.end();
-				file_it != end_file_it;
-				++file_it)
+			BOOST_FOREACH(const SettingsFile& settings_file, group.files)
 			{
-				if (file_it->name() == file)
+				if (settings_file.name() == file)
 				{
-					return file_it->file_name;
+					return settings_file.file_name;
 				}
 			}
 		}
-- 
cgit v1.2.3