PageRenderTime 8ms CodeModel.GetById 35ms app.highlight 133ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llxuixml/llinitparam.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 2294 lines | 1788 code | 355 blank | 151 comment | 159 complexity | 7b571de92f32ce2e0ecf79e16a2c9acc MD5 | raw file
Possible License(s): LGPL-2.1
   1/** 
   2 * @file llinitparam.h
   3 * @brief parameter block abstraction for creating complex objects and 
   4 * parsing construction parameters from xml and LLSD
   5 *
   6 * $LicenseInfo:firstyear=2008&license=viewerlgpl$
   7 * Second Life Viewer Source Code
   8 * Copyright (C) 2010, Linden Research, Inc.
   9 * 
  10 * This library is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU Lesser General Public
  12 * License as published by the Free Software Foundation;
  13 * version 2.1 of the License only.
  14 * 
  15 * This library is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * Lesser General Public License for more details.
  19 * 
  20 * You should have received a copy of the GNU Lesser General Public
  21 * License along with this library; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  23 * 
  24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  25 * $/LicenseInfo$
  26 */
  27
  28#ifndef LL_LLPARAM_H
  29#define LL_LLPARAM_H
  30
  31#include <vector>
  32#include <boost/function.hpp>
  33#include <boost/type_traits/is_convertible.hpp>
  34#include <boost/unordered_map.hpp>
  35#include <boost/shared_ptr.hpp>
  36
  37#include "llerror.h"
  38
  39namespace LLInitParam
  40{
  41	// used to indicate no matching value to a given name when parsing
  42	struct Flag{};
  43
  44	template<typename T> const T& defaultValue() { static T value; return value; }
  45
  46	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
  47    struct ParamCompare 
  48	{
  49    	static bool equals(const T &a, const T &b)
  50		{
  51			return a == b;
  52		}
  53    };
  54
  55	// boost function types are not comparable
  56	template<typename T>
  57	struct ParamCompare<T, true>
  58	{
  59		static bool equals(const T&a, const T &b)
  60		{
  61			return false;
  62		}
  63	};
  64
  65	template<> 
  66	struct ParamCompare<LLSD, false>
  67	{
  68		static bool equals(const LLSD &a, const LLSD &b) { return false; }
  69	};
  70
  71	template<>
  72	struct ParamCompare<Flag, false>
  73	{
  74		static bool equals(const Flag& a, const Flag& b) { return false; }
  75	};
  76
  77
  78	// helper functions and classes
  79	typedef ptrdiff_t param_handle_t;
  80
  81	// empty default implementation of key cache
  82	// leverages empty base class optimization
  83	template <typename T>
  84	class TypeValues
  85	{
  86	private:
  87		struct Inaccessable{};
  88	public:
  89		typedef std::map<std::string, T> value_name_map_t;
  90		typedef Inaccessable name_t;
  91
  92		void setValueName(const std::string& key) {}
  93		std::string getValueName() const { return ""; }
  94		std::string calcValueName(const T& value) const { return ""; }
  95		void clearValueName() const {}
  96
  97		static bool getValueFromName(const std::string& name, T& value)
  98		{
  99			return false;
 100		}
 101
 102		static bool valueNamesExist()
 103		{
 104			return false;
 105		}
 106
 107		static std::vector<std::string>* getPossibleValues()
 108		{
 109			return NULL;
 110		}
 111
 112		static value_name_map_t* getValueNames() {return NULL;}
 113	};
 114
 115	template <typename T, typename DERIVED_TYPE = TypeValues<T> >
 116	class TypeValuesHelper
 117	{
 118	public:
 119		typedef typename std::map<std::string, T> value_name_map_t;
 120		typedef std::string name_t;
 121
 122		//TODO: cache key by index to save on param block size
 123		void setValueName(const std::string& value_name) 
 124		{
 125			mValueName = value_name; 
 126		}
 127
 128		std::string getValueName() const
 129		{ 
 130			return mValueName; 
 131		}
 132
 133		std::string calcValueName(const T& value) const
 134		{
 135			value_name_map_t* map = getValueNames();
 136			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
 137				it != end_it;
 138				++it)
 139			{
 140				if (ParamCompare<T>::equals(it->second, value))
 141				{
 142					return it->first;
 143				}
 144			}
 145
 146			return "";
 147		}
 148
 149		void clearValueName() const
 150		{
 151			mValueName.clear();
 152		}
 153
 154		static bool getValueFromName(const std::string& name, T& value)
 155		{
 156			value_name_map_t* map = getValueNames();
 157			typename value_name_map_t::iterator found_it = map->find(name);
 158			if (found_it == map->end()) return false;
 159
 160			value = found_it->second;
 161			return true;
 162		}
 163
 164		static bool valueNamesExist()
 165		{
 166			return !getValueNames()->empty();
 167		}
 168	
 169		static value_name_map_t* getValueNames()
 170		{
 171			static value_name_map_t sMap;
 172			static bool sInitialized = false;
 173
 174			if (!sInitialized)
 175			{
 176				sInitialized = true;
 177				DERIVED_TYPE::declareValues();
 178			}
 179			return &sMap;
 180		}
 181
 182		static std::vector<std::string>* getPossibleValues()
 183		{
 184			static std::vector<std::string> sValues;
 185
 186			value_name_map_t* map = getValueNames();
 187			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
 188				 it != end_it;
 189				 ++it)
 190			{
 191				sValues.push_back(it->first);
 192			}
 193			return &sValues;
 194		}
 195
 196		static void declare(const std::string& name, const T& value)
 197		{
 198			(*getValueNames())[name] = value;
 199		}
 200
 201	protected:
 202		static void getName(const std::string& name, const T& value)
 203		{}
 204
 205		mutable std::string	mValueName;
 206	};
 207
 208	class Parser
 209	{
 210		LOG_CLASS(Parser);
 211
 212	public:
 213		
 214		struct CompareTypeID
 215		{
 216			bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
 217			{
 218				return lhs->before(*rhs);
 219			}
 220		};
 221
 222		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
 223		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
 224		typedef std::vector<std::string>									possible_values_t;
 225
 226		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
 227		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
 228		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 229
 230		typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID>		parser_read_func_map_t;
 231		typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID>		parser_write_func_map_t;
 232		typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID>	parser_inspect_func_map_t;
 233
 234		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 235		:	mParseSilently(false),
 236			mParserReadFuncs(&read_map),
 237			mParserWriteFuncs(&write_map),
 238			mParserInspectFuncs(&inspect_map)
 239		{}
 240		virtual ~Parser();
 241
 242		template <typename T> bool readValue(T& param)
 243	    {
 244		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
 245		    if (found_it != mParserReadFuncs->end())
 246		    {
 247			    return found_it->second(*this, (void*)&param);
 248		    }
 249		    return false;
 250	    }
 251
 252		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
 253		{
 254		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
 255		    if (found_it != mParserWriteFuncs->end())
 256		    {
 257			    return found_it->second(*this, (const void*)&param, name_stack);
 258		    }
 259		    return false;
 260		}
 261
 262		// dispatch inspection to registered inspection functions, for each parameter in a param block
 263		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 264		{
 265		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
 266		    if (found_it != mParserInspectFuncs->end())
 267		    {
 268			    found_it->second(name_stack, min_count, max_count, possible_values);
 269				return true;
 270		    }
 271			return false;
 272		}
 273
 274		virtual std::string getCurrentElementName() = 0;
 275		virtual void parserWarning(const std::string& message);
 276		virtual void parserError(const std::string& message);
 277		void setParseSilently(bool silent) { mParseSilently = silent; }
 278
 279	protected:
 280		template <typename T>
 281		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
 282		{
 283			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
 284			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
 285		}
 286
 287		template <typename T>
 288		void registerInspectFunc(parser_inspect_func_t inspect_func)
 289		{
 290			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
 291		}
 292
 293		bool				mParseSilently;
 294
 295	private:
 296		parser_read_func_map_t*		mParserReadFuncs;
 297		parser_write_func_map_t*	mParserWriteFuncs;
 298		parser_inspect_func_map_t*	mParserInspectFuncs;
 299	};
 300
 301	class Param;
 302
 303	// various callbacks and constraints associated with an individual param
 304	struct ParamDescriptor
 305	{
 306		struct UserData
 307		{
 308			virtual ~UserData() {}
 309		};
 310
 311		typedef bool(*merge_func_t)(Param&, const Param&, bool);
 312		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
 313		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
 314		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
 315		typedef bool(*validation_func_t)(const Param*);
 316
 317		ParamDescriptor(param_handle_t p, 
 318						merge_func_t merge_func, 
 319						deserialize_func_t deserialize_func, 
 320						serialize_func_t serialize_func,
 321						validation_func_t validation_func,
 322						inspect_func_t inspect_func,
 323						S32 min_count,
 324						S32 max_count);
 325
 326		ParamDescriptor();
 327		~ParamDescriptor();
 328
 329		param_handle_t		mParamHandle;
 330		merge_func_t		mMergeFunc;
 331		deserialize_func_t	mDeserializeFunc;
 332		serialize_func_t	mSerializeFunc;
 333		inspect_func_t		mInspectFunc;
 334		validation_func_t	mValidationFunc;
 335		S32					mMinCount;
 336		S32					mMaxCount;
 337		S32					mNumRefs;
 338		UserData*			mUserData;
 339	};
 340
 341	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
 342
 343	// each derived Block class keeps a static data structure maintaining offsets to various params
 344	class BlockDescriptor
 345	{
 346	public:
 347		BlockDescriptor();
 348
 349		typedef enum e_initialization_state
 350		{
 351			UNINITIALIZED,
 352			INITIALIZING,
 353			INITIALIZED
 354		} EInitializationState;
 355
 356		void aggregateBlockData(BlockDescriptor& src_block_data);
 357
 358		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t; 
 359		typedef std::vector<ParamDescriptorPtr>													param_list_t; 
 360		typedef std::list<ParamDescriptorPtr>													all_params_list_t;
 361		typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> >		param_validation_list_t;
 362
 363		param_map_t						mNamedParams;			// parameters with associated names
 364		param_list_t					mUnnamedParams;			// parameters with_out_ associated names
 365		param_validation_list_t			mValidationList;		// parameters that must be validated
 366		all_params_list_t				mAllParams;				// all parameters, owns descriptors
 367		size_t							mMaxParamOffset;
 368		EInitializationState			mInitializationState;	// whether or not static block data has been initialized
 369		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed
 370	};
 371
 372	class BaseBlock
 373	{
 374	public:
 375		//TODO: implement in terms of owned_ptr
 376		template<typename T>
 377		class Lazy
 378		{
 379		public:
 380			Lazy()
 381				: mPtr(NULL)
 382			{}
 383
 384			~Lazy()
 385			{
 386				delete mPtr;
 387			}
 388
 389			Lazy(const Lazy& other)
 390			{
 391				if (other.mPtr)
 392				{
 393					mPtr = new T(*other.mPtr);
 394				}
 395				else
 396				{
 397					mPtr = NULL;
 398				}
 399			}
 400
 401			Lazy<T>& operator = (const Lazy<T>& other)
 402			{
 403				if (other.mPtr)
 404				{
 405					mPtr = new T(*other.mPtr);
 406				}
 407				else
 408				{
 409					mPtr = NULL;
 410				}
 411				return *this;
 412			}
 413
 414			bool empty() const
 415			{
 416				return mPtr == NULL;
 417			}
 418
 419			void set(const T& other)
 420			{
 421				delete mPtr;
 422				mPtr = new T(other);
 423			}
 424
 425			const T& get() const
 426			{
 427				return ensureInstance();
 428			}
 429
 430			T& get()
 431			{
 432				return ensureInstance();
 433			}
 434
 435		private:
 436			// lazily allocate an instance of T
 437			T* ensureInstance() const
 438			{
 439				if (mPtr == NULL)
 440				{
 441					mPtr = new T();
 442				}
 443				return mPtr;
 444			}
 445
 446		private:
 447			// if you get a compilation error with this, that means you are using a forward declared struct for T
 448			// unfortunately, the type traits we rely on don't work with forward declared typed
 449			//static const int dummy = sizeof(T);
 450
 451			mutable T* mPtr;
 452		};
 453
 454		// "Multiple" constraint types, put here in root class to avoid ambiguity during use
 455		struct AnyAmount
 456		{
 457			enum { minCount = 0 };
 458			enum { maxCount = U32_MAX };
 459		};
 460
 461		template<U32 MIN_AMOUNT>
 462		struct AtLeast
 463		{
 464			enum { minCount = MIN_AMOUNT };
 465			enum { maxCount = U32_MAX };
 466		};
 467
 468		template<U32 MAX_AMOUNT>
 469		struct AtMost
 470		{
 471			enum { minCount = 0 };
 472			enum { maxCount = MAX_AMOUNT };
 473		};
 474
 475		template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
 476		struct Between
 477		{
 478			enum { minCount = MIN_AMOUNT };
 479			enum { maxCount = MAX_AMOUNT };
 480		};
 481
 482		template<U32 EXACT_COUNT>
 483		struct Exactly
 484		{
 485			enum { minCount = EXACT_COUNT };
 486			enum { maxCount = EXACT_COUNT };
 487		};
 488
 489		// this typedef identifies derived classes as being blocks
 490		typedef void baseblock_base_class_t;
 491		LOG_CLASS(BaseBlock);
 492		friend class Param;
 493
 494		virtual ~BaseBlock() {}
 495		bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
 496
 497		param_handle_t getHandleFromParam(const Param* param) const;
 498		bool validateBlock(bool emit_errors = true) const;
 499
 500		Param* getParamFromHandle(const param_handle_t param_handle)
 501		{
 502			if (param_handle == 0) return NULL;
 503
 504			U8* baseblock_address = reinterpret_cast<U8*>(this);
 505			return reinterpret_cast<Param*>(baseblock_address + param_handle);
 506		}
 507
 508		const Param* getParamFromHandle(const param_handle_t param_handle) const
 509		{
 510			const U8* baseblock_address = reinterpret_cast<const U8*>(this);
 511			return reinterpret_cast<const Param*>(baseblock_address + param_handle);
 512		}
 513
 514		void addSynonym(Param& param, const std::string& synonym);
 515
 516		// Blocks can override this to do custom tracking of changes
 517		virtual void paramChanged(const Param& changed_param, bool user_provided) {}
 518
 519		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
 520		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
 521		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 522
 523		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
 524		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
 525
 526		// take all provided params from other and apply to self
 527		bool overwriteFrom(const BaseBlock& other)
 528		{
 529			return false;
 530		}
 531
 532		// take all provided params that are not already provided, and apply to self
 533		bool fillFrom(const BaseBlock& other)
 534		{
 535			return false;
 536		}
 537
 538		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name);
 539
 540		ParamDescriptorPtr findParamDescriptor(const Param& param);
 541
 542	protected:
 543		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
 544
 545
 546		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
 547		{
 548			return mergeBlock(block_data, source, overwrite);
 549		}
 550		// take all provided params from other and apply to self
 551		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
 552
 553		static BlockDescriptor& selfBlockDescriptor()
 554		{
 555			static BlockDescriptor sBlockDescriptor;
 556			return sBlockDescriptor;
 557		}
 558
 559	private:
 560		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
 561	};
 562
 563	template<typename T>
 564	struct ParamCompare<BaseBlock::Lazy<T>, false >
 565	{
 566		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); }
 567	};
 568
 569	class Param
 570	{
 571	public:
 572		void setProvided(bool is_provided = true)
 573		{
 574			mIsProvided = is_provided;
 575			enclosingBlock().paramChanged(*this, is_provided);
 576		}
 577
 578		Param& operator =(const Param& other)
 579		{
 580			mIsProvided = other.mIsProvided;
 581			// don't change mEnclosingblockoffset
 582			return *this;
 583		}
 584	protected:
 585
 586		bool anyProvided() const { return mIsProvided; }
 587
 588		Param(BaseBlock* enclosing_block);
 589
 590		// store pointer to enclosing block as offset to reduce space and allow for quick copying
 591		BaseBlock& enclosingBlock() const
 592		{ 
 593			const U8* my_addr = reinterpret_cast<const U8*>(this);
 594			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
 595			return *const_cast<BaseBlock*>
 596				(reinterpret_cast<const BaseBlock*>
 597					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
 598		}
 599
 600	private:
 601		friend class BaseBlock;
 602
 603		U32		mEnclosingBlockOffset:31;
 604		U32		mIsProvided:1;
 605
 606	};
 607
 608	// these templates allow us to distinguish between template parameters
 609	// that derive from BaseBlock and those that don't
 610	template<typename T, typename Void = void>
 611	struct IsBlock
 612	{
 613		static const bool value = false;
 614		struct EmptyBase {};
 615		typedef EmptyBase base_class_t;
 616	};
 617
 618	template<typename T>
 619	struct IsBlock<T, typename T::baseblock_base_class_t>
 620	{
 621		static const bool value = true;
 622		typedef BaseBlock base_class_t;
 623	};
 624
 625	template<typename T>
 626	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t >
 627	{
 628		static const bool value = true;
 629		typedef BaseBlock base_class_t;
 630	};
 631
 632	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value>
 633	class ParamValue : public NAME_VALUE_LOOKUP
 634	{
 635	public:
 636		typedef const T&							value_assignment_t;
 637		typedef T									value_t;
 638		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t;
 639
 640		ParamValue(): mValue() {}
 641		ParamValue(value_assignment_t other) : mValue(other) {}
 642
 643		void setValue(value_assignment_t val)
 644		{
 645			mValue = val;
 646		}
 647
 648		value_assignment_t getValue() const
 649		{
 650			return mValue;
 651		}
 652
 653		T& getValue()
 654		{
 655			return mValue;
 656		}
 657
 658		operator value_assignment_t() const
 659		{
 660			return mValue;
 661		}
 662
 663		value_assignment_t operator()() const
 664		{
 665			return mValue;
 666		}
 667
 668		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
 669		{
 670			*this = name;
 671		}
 672
 673		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
 674		{
 675			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue))
 676			{
 677				setValueName(name);
 678			}
 679
 680			return *this;
 681		}
 682
 683	protected:
 684		T mValue;
 685	};
 686
 687	template<typename T, typename NAME_VALUE_LOOKUP>
 688	class ParamValue<T, NAME_VALUE_LOOKUP, true> 
 689	:	public T,
 690		public NAME_VALUE_LOOKUP
 691	{
 692	public:
 693		typedef const T&							value_assignment_t;
 694		typedef T									value_t;
 695		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t;
 696
 697		ParamValue() 
 698		:	T(),
 699			mValidated(false)
 700		{}
 701
 702		ParamValue(value_assignment_t other)
 703		:	T(other),
 704			mValidated(false)
 705		{}
 706
 707		void setValue(value_assignment_t val)
 708		{
 709			*this = val;
 710		}
 711
 712		value_assignment_t getValue() const
 713		{
 714			return *this;
 715		}
 716
 717		T& getValue()
 718		{
 719			return *this;
 720		}
 721
 722		operator value_assignment_t() const
 723		{
 724			return *this;
 725		}
 726		
 727		value_assignment_t operator()() const
 728		{
 729			return *this;
 730		}
 731
 732		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
 733		{
 734			*this = name;
 735		}
 736
 737		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
 738		{
 739			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this))
 740			{
 741				setValueName(name);
 742			}
 743
 744			return *this;
 745		}
 746
 747	protected:
 748		mutable bool 	mValidated; // lazy validation flag
 749	};
 750
 751	template<typename NAME_VALUE_LOOKUP>
 752	class ParamValue<std::string, NAME_VALUE_LOOKUP, false>
 753	: public NAME_VALUE_LOOKUP
 754	{
 755	public:
 756		typedef const std::string&	value_assignment_t;
 757		typedef std::string			value_t;
 758		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t;
 759
 760		ParamValue(): mValue() {}
 761		ParamValue(value_assignment_t other) : mValue(other) {}
 762
 763		void setValue(value_assignment_t val)
 764		{
 765			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue))
 766			{
 767				NAME_VALUE_LOOKUP::setValueName(val);
 768			}
 769			else
 770			{
 771				mValue = val;
 772			}
 773		}
 774
 775		value_assignment_t getValue() const
 776		{
 777			return mValue;
 778		}
 779
 780		std::string& getValue()
 781		{
 782			return mValue;
 783		}
 784
 785		operator value_assignment_t() const
 786		{
 787			return mValue;
 788		}
 789
 790		value_assignment_t operator()() const
 791		{
 792			return mValue;
 793		}
 794
 795	protected:
 796		std::string mValue;
 797	};
 798
 799
 800	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
 801	struct ParamIterator
 802	{
 803		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator;
 804		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator;
 805	};
 806
 807	// specialize for custom parsing/decomposition of specific classes
 808	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc...
 809	template<typename	T,
 810			typename	NAME_VALUE_LOOKUP = TypeValues<T>,
 811			bool		HAS_MULTIPLE_VALUES = false,
 812			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>
 813	class TypedParam 
 814	:	public Param, 
 815		public ParamValue<T, NAME_VALUE_LOOKUP>
 816	{
 817	public:
 818		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t;
 819		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t;
 820		typedef typename param_value_t::value_assignment_t				value_assignment_t;
 821		typedef NAME_VALUE_LOOKUP															name_value_lookup_t;
 822
 823		using param_value_t::operator();
 824
 825		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
 826		:	Param(block_descriptor.mCurrentBlockPtr)
 827		{
 828			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
 829			{
 830 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
 831												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
 832												&mergeWith,
 833												&deserializeParam,
 834												&serializeParam,
 835												validate_func,
 836												&inspectParam,
 837												min_count, max_count));
 838				BaseBlock::addParam(block_descriptor, param_descriptor, name);
 839			}
 840
 841			setValue(value);
 842		} 
 843
 844		bool isProvided() const { return Param::anyProvided(); }
 845
 846		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 847		{ 
 848			self_t& typed_param = static_cast<self_t&>(param);
 849			// no further names in stack, attempt to parse value now
 850			if (name_stack_range.first == name_stack_range.second)
 851			{
 852				if (parser.readValue(typed_param.getValue()))
 853				{
 854					typed_param.clearValueName();
 855					typed_param.setProvided();
 856					return true;
 857				}
 858				
 859				// try to parse a known named value
 860				if(name_value_lookup_t::valueNamesExist())
 861				{
 862					// try to parse a known named value
 863					std::string name;
 864					if (parser.readValue(name))
 865					{
 866						// try to parse a per type named value
 867						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
 868						{
 869							typed_param.setValueName(name);
 870							typed_param.setProvided();
 871							return true;
 872						}
 873
 874					}
 875				}
 876			}
 877			return false;
 878		}
 879
 880		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 881		{
 882			const self_t& typed_param = static_cast<const self_t&>(param);
 883			if (!typed_param.isProvided()) return;
 884
 885			if (!name_stack.empty())
 886			{
 887				name_stack.back().second = true;
 888			}
 889
 890			std::string key = typed_param.getValueName();
 891
 892			// first try to write out name of name/value pair
 893
 894			if (!key.empty())
 895			{
 896				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
 897				{
 898					parser.writeValue(key, name_stack);
 899				}
 900			}
 901			// then try to serialize value directly
 902			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
 903			{
 904				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
 905				{
 906					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
 907					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
 908					{
 909						parser.writeValue(calculated_key, name_stack);
 910					}
 911				}
 912			}
 913		}
 914
 915		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
 916		{
 917			// tell parser about our actual type
 918			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
 919			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
 920			if (name_value_lookup_t::getPossibleValues())
 921			{
 922				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
 923			}
 924		}
 925
 926		void set(value_assignment_t val, bool flag_as_provided = true)
 927		{
 928			param_value_t::clearValueName();
 929			setValue(val);
 930			setProvided(flag_as_provided);
 931		}
 932
 933		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
 934		{
 935			return static_cast<self_t&>(param_value_t::operator =(name));
 936		}
 937
 938	protected:
 939
 940		self_t& operator =(const self_t& other)
 941		{
 942			param_value_t::operator =(other);
 943			Param::operator =(other);
 944			return *this;
 945		}
 946
 947		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
 948		{
 949			const self_t& src_typed_param = static_cast<const self_t&>(src);
 950			self_t& dst_typed_param = static_cast<self_t&>(dst);
 951
 952			if (src_typed_param.isProvided()
 953				&& (overwrite || !dst_typed_param.isProvided()))
 954			{
 955				dst_typed_param.set(src_typed_param.getValue());
 956				return true;
 957			}
 958			return false;
 959		}
 960	};
 961
 962	// parameter that is a block
 963	template <typename T, typename NAME_VALUE_LOOKUP>
 964	class TypedParam<T, NAME_VALUE_LOOKUP, false, true> 
 965	:	public Param,
 966		public ParamValue<T, NAME_VALUE_LOOKUP>
 967	{
 968	public:
 969		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t;
 970		typedef typename param_value_t::value_assignment_t		value_assignment_t;
 971		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t;
 972		typedef NAME_VALUE_LOOKUP								name_value_lookup_t;
 973
 974		using param_value_t::operator();
 975
 976		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
 977		:	Param(block_descriptor.mCurrentBlockPtr),
 978			param_value_t(value)
 979		{
 980			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
 981			{
 982				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
 983												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
 984												&mergeWith,
 985												&deserializeParam,
 986												&serializeParam,
 987												validate_func, 
 988												&inspectParam,
 989												min_count, max_count));
 990				BaseBlock::addParam(block_descriptor, param_descriptor, name);
 991			}
 992		}
 993
 994		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 995		{ 
 996			self_t& typed_param = static_cast<self_t&>(param);
 997			// attempt to parse block...
 998			if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
 999			{
1000				typed_param.clearValueName();
1001				typed_param.setProvided();
1002				return true;
1003			}
1004
1005			if(name_value_lookup_t::valueNamesExist())
1006			{
1007				// try to parse a known named value
1008				std::string name;
1009				if (parser.readValue(name))
1010				{
1011					// try to parse a per type named value
1012					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
1013					{
1014						typed_param.setValueName(name);
1015						typed_param.setProvided();
1016						return true;
1017					}
1018
1019				}
1020			}
1021			return false;
1022		}
1023
1024		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
1025		{
1026			const self_t& typed_param = static_cast<const self_t&>(param);
1027			if (!typed_param.isProvided()) return;
1028
1029			if (!name_stack.empty())
1030			{
1031				name_stack.back().second = true;
1032			}
1033
1034			std::string key = typed_param.getValueName();
1035			if (!key.empty())
1036			{
1037				if (!parser.writeValue(key, name_stack))
1038				{
1039					return;
1040				}
1041			}
1042			else
1043			{
1044				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
1045			}
1046		}
1047
1048		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
1049		{
1050			// I am a param that is also a block, so just recurse into my contents
1051			const self_t& typed_param = static_cast<const self_t&>(param);
1052			typed_param.inspectBlock(parser, name_stack, min_count, max_count);
1053		}
1054
1055		// a param-that-is-a-block is provided when the user has set one of its child params
1056		// *and* the block as a whole validates
1057		bool isProvided() const 
1058		{ 
1059			// only validate block when it hasn't already passed validation with current data
1060			if (Param::anyProvided() && !param_value_t::mValidated)
1061			{
1062				// a sub-block is "provided" when it has been filled in enough to be valid
1063				param_value_t::mValidated = param_value_t::validateBlock(false);
1064			}
1065			return Param::anyProvided() && param_value_t::mValidated;
1066		}
1067
1068		// assign block contents to this param-that-is-a-block
1069		void set(value_assignment_t val, bool flag_as_provided = true)
1070		{
1071			setValue(val);
1072			param_value_t::clearValueName();
1073			// force revalidation of block
1074			// next call to isProvided() will update provision status based on validity
1075			param_value_t::mValidated = false;
1076			setProvided(flag_as_provided);
1077		}
1078
1079		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
1080		{
1081			return static_cast<self_t&>(param_value_t::operator =(name));
1082		}
1083
1084		// propagate changed status up to enclosing block
1085		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
1086		{ 
1087			param_value_t::paramChanged(changed_param, user_provided);
1088			if (user_provided)
1089			{
1090				// a child param has been explicitly changed
1091				// so *some* aspect of this block is now provided
1092				param_value_t::mValidated = false;
1093				setProvided();
1094				param_value_t::clearValueName();
1095			}
1096			else
1097			{
1098				Param::enclosingBlock().paramChanged(*this, user_provided);
1099			}
1100		}
1101
1102	protected:
1103
1104		self_t& operator =(const self_t& other)
1105		{
1106			param_value_t::operator =(other);
1107			Param::operator =(other);
1108			return *this;
1109		}
1110
1111		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
1112		{
1113			const self_t& src_typed_param = static_cast<const self_t&>(src);
1114			self_t& dst_typed_param = static_cast<self_t&>(dst);
1115
1116			if (src_typed_param.anyProvided())
1117			{
1118				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite))
1119				{
1120					dst_typed_param.clearValueName();
1121					dst_typed_param.setProvided(true);
1122					return true;
1123				}
1124			}
1125			return false;
1126		}
1127	};
1128
1129	// container of non-block parameters
1130	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
1131	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> 
1132	:	public Param
1133	{
1134	public:
1135		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t;
1136		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t;
1137		typedef typename std::vector<param_value_t>							container_t;
1138		typedef const container_t&											value_assignment_t;
1139
1140		typedef typename param_value_t::value_t								value_t;
1141		typedef NAME_VALUE_LOOKUP											name_value_lookup_t;
1142		
1143		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
1144		:	Param(block_descriptor.mCurrentBlockPtr)
1145		{
1146			std::copy(value.begin(), value.end(), std::back_inserter(mValues));
1147
1148			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
1149			{
1150				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
1151												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
1152												&mergeWith,
1153												&deserializeParam,
1154												&serializeParam,
1155												validate_func,
1156												&inspectParam,
1157												min_count, max_count));
1158				BaseBlock::addParam(block_descriptor, param_descriptor, name);
1159			}
1160		} 
1161
1162		bool isProvided() const { return Param::anyProvided(); }
1163
1164		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
1165		{ 
1166			self_t& typed_param = static_cast<self_t&>(param);
1167			value_t value;
1168			// no further names in stack, attempt to parse value now
1169			if (name_stack_range.first == name_stack_range.second)
1170			{
1171				// attempt to read value directly
1172				if (parser.readValue(value))
1173				{
1174					typed_param.add(value);
1175					return true;
1176				}
1177				
1178				// try to parse a known named value
1179				if(name_value_lookup_t::valueNamesExist())
1180				{
1181					// try to parse a known named value
1182					std::string name;
1183					if (parser.readValue(name))
1184					{
1185						// try to parse a per type named value
1186						if (name_value_lookup_t::getValueFromName(name, value))
1187						{
1188							typed_param.add(value);
1189							typed_param.mValues.back().setValueName(name);
1190							return true;
1191						}
1192
1193					}
1194				}
1195			}
1196			return false;
1197		}
1198
1199		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
1200		{
1201			const self_t& typed_param = static_cast<const self_t&>(param);
1202			if (!typed_param.isProvided() || name_stack.empty()) return;
1203
1204			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
1205				it != end_it;
1206				++it)
1207			{
1208				std::string key = it->getValueName();
1209				name_stack.back().second = true;
1210
1211				if(key.empty())
1212				// not parsed via name values, write out value directly
1213				{
1214					bool value_written = parser.writeValue(*it, name_stack);
1215					if (!value_written)
1216					{
1217						std::string calculated_key = it->calcValueName(it->getValue());
1218						if (!parser.writeValue(calculated_key, name_stack))
1219						{
1220							break;
1221						}
1222					}
1223				}
1224				else 
1225				{
1226					if(!parser.writeValue(key, name_stack))
1227					{
1228						break;
1229					}
1230				}
1231			}
1232		}
1233
1234		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
1235		{
1236			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
1237			if (name_value_lookup_t::getPossibleValues())
1238			{
1239				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
1240			}
1241		}
1242
1243		void set(value_assignment_t val, bool flag_as_provided = true)
1244		{
1245			mValues = val;
1246			setProvided(flag_as_provided);
1247		}
1248
1249		param_value_t& add()
1250		{
1251			mValues.push_back(param_value_t(value_t()));
1252			Param::setProvided();
1253			return mValues.back();
1254		}
1255
1256		void add(const value_t& item)
1257		{
1258			param_value_t param_value;
1259			param_value.setValue(item);
1260			mValues.push_back(param_value);
1261			setProvided();
1262		}
1263
1264		void add(const typename name_value_lookup_t::name_t& name)
1265		{
1266			value_t value;
1267
1268			// try to parse a per type named value
1269			if (name_value_lookup_t::getValueFromName(name, value))
1270			{
1271				add(value);
1272				mValues.back().setValueName(name);
1273			}
1274		}
1275
1276		// implicit conversion
1277		operator value_assignment_t() const { return mValues; } 
1278		// explicit conversion		
1279		value_assignment_t operator()() const { return mValues; }
1280
1281		typedef typename container_t::iterator iterator;
1282		typedef typename container_t::const_iterator const_iterator;
1283		iterator begin() { return mValues.begin(); }
1284		iterator end() { return mValues.end(); }
1285		const_iterator begin() const { return mValues.begin(); }
1286		const_iterator end() const { return mValues.end(); }
1287		bool empty() const { return mValues.empty(); }
1288		size_t size() const { return mValues.size(); }
1289
1290		U32 numValidElements() const
1291		{
1292			return mValues.size();
1293		}
1294
1295	protected:
1296		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
1297		{
1298			const self_t& src_typed_param = static_cast<const self_t&>(src);
1299			self_t& dst_typed_param = static_cast<self_t&>(dst);
1300
1301			if (overwrite)
1302			{
1303				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
1304			}
1305			else
1306			{
1307				container_t new_values(src_typed_param.mValues);
1308				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
1309				std::swap(dst_typed_param.mValues, new_values);
1310			}
1311
1312			if (src_typed_param.begin() != src_typed_param.end())
1313			{
1314				dst_typed_param.setProvided();
1315			}
1316			return true;
1317		}
1318
1319		container_t		mValues;
1320	};
1321
1322	// container of block parameters
1323	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
1324	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> 
1325	:	public Param
1326	{
1327	public:
1328		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t;
1329		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t;
1330		typedef typename std::vector<param_value_t>						container_t;
1331		typedef const container_t&										value_assignment_t;
1332		typedef typename param_value_t::value_t							value_t;
1333		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;
1334
1335		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
1336		:	Param(block_descriptor.mCurrentBlockPtr)
1337		{
1338			std::copy(value.begin(), value.end(), back_inserter(mValues));
1339
1340			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
1341			{
1342				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
1343												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
1344												&mergeWith,
1345												&deserializeParam,
1346												&serializeParam,
1347												validate_func,
1348												&inspectParam,
1349												min_count, max_count));
1350				BaseBlock::addParam(block_descriptor, param_descriptor, name);
1351			}
1352		} 
1353
1354		bool isProvided() const { return Param::anyProvided(); }
1355
1356		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
1357		{ 
1358			self_t& typed_param = static_cast<self_t&>(param);
1359			bool new_value = false;
1360
1361			if (new_name || typed_param.mValues.empty())
1362			{
1363				new_value = true;
1364				typed_param.mValues.push_back(value_t());
1365			}
1366
1367			param_value_t& value = typed_param.mValues.back();
1368
1369			// attempt to parse block...
1370			if(value.deserializeBlock(parser, name_stack_range, new_name))
1371			{
1372				typed_param.setProvided();
1373				return true;
1374			}
1375			else if(name_value_lookup_t::valueNamesExist())
1376			{
1377				// try to parse a known named value
1378				std::string name;
1379				if (parser.readValue(name))
1380				{
1381					// try to parse a per type named value
1382					if (name_value_lookup_t::getValueFromName(name, value.getValue()))
1383					{
1384						typed_param.mValues.back().setValueName(name);
1385						typed_param.setProvided();
1386						return true;
1387					}
1388
1389				}
1390			}
1391
1392			if (new_value)
1393			{	// failed to parse new value, pop it off
1394				typed_param.mValues.pop_back();
1395			}
1396
1397			return false;
1398		}
1399
1400		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
1401		{
1402			const self_t& typed_param = static_cast<const self_t&>(param);
1403			if (!typed_param.isProvided() || name_stack.empty()) return;
1404
1405			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
1406				it != end_it;
1407				++it)
1408			{
1409				name_stack.back().second = true;
1410
1411				std::string key = it->getValueName();
1412				if (!key.empty())
1413				{
1414					parser.writeValue(key, name_stack);
1415				}
1416				// Not parsed via named values, write out value directly
1417				// NOTE: currently we don't worry about removing default values in Multiple
1418				else 
1419				{
1420					it->serializeBlock(parser, name_stack, NULL);
1421				}
1422			}
1423		}
1424
1425		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
1426		{
1427			// I am a vector of blocks, so describe my contents recursively
1428			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count);
1429		}
1430
1431		void set(value_assignment_t val, bool flag_as_provided = true)
1432		{
1433			mValues = val;
1434			setProvided(flag_as_provided);
1435		}
1436
1437		param_value_t& add()
1438		{
1439			mValues.push_back(value_t());
1440			setProvided();
1441			return mValues.back();
1442		}
1443
1444		void add(const value_t& item)
1445		{
1446			mValues.push_back(item);
1447			setProvided();
1448		}
1449
1450		void add(const typename name_value_lookup_t::name_t& name)
1451		{
1452			value_t value;
1453
1454			// try to parse a per type named value
1455			if (name_value_lookup_t::getValueFromName(name, value))
1456			{
1457				add(value);
1458				mValues.back().setValueName(name);
1459			}
1460		}
1461
1462		// implicit conversion
1463		operator value_assignment_t() const { return mValues; } 
1464		// explicit conversion
1465		value_assignment_t operator()() const { return mValues; }
1466
1467		typedef typename container_t::iterator iterator;
1468		typedef typename container_t::const_iterator const_iterator;
1469		iterator begin() { return mValues.begin(); }
1470		iterator end() { return mValues.end(); }
1471		const_iterator begin() const { return mValues.begin(); }
1472		const_iterator end() const { return mValues.end(); }
1473		bool empty() const { return mValues.empty(); }
1474		size_t size() const { return mValues.size(); }
1475
1476		U32 numValidElements() const
1477		{
1478			U32 count = 0;
1479			for (const_iterator it = mValues.begin(), end_it = mValues.end();
1480				it != end_it;
1481				++it)
1482			{
1483				if(it->validateBlock(false)) count++;
1484			}
1485			return count;
1486		}
1487
1488	protected:
1489
1490		static bool mergeWith(Param& dst, const Param& src, bool overwrite)
1491		{
1492			const self_t& src_typed_param = static_cast<const self_t&>(src);
1493			self_t& dst_typed_param = static_cast<self_t&>(dst);
1494
1495			if (overwrite)
1496			{
1497				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
1498			}
1499			else
1500			{
1501				container_t new_values(src_typed_param.mValues);
1502				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
1503				std::swap(dst_typed_param.mValues, new_values);
1504			}
1505
1506			if (src_typed_param.begin() != src_typed_param.end())
1507			{
1508				dst_typed_param.setProvided();
1509			}
1510
1511			return true;
1512		}
1513
1514		container_t			mValues;
1515	};
1516
1517	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
1518	class ChoiceBlock : public BASE_BLOCK
1519	{
1520		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	self_t;
1521		typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK>	enclosing_block_t;
1522		typedef BASE_BLOCK								base_block_t;
1523		
1524		LOG_CLASS(self_t);
1525	public:
1526		// take all provided params from other and apply to self
1527		bool overwriteFrom(const self_t& other)
1528		{
1529			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
1530		}
1531
1532		// take all provided params that are not already provided, and apply to self
1533		bool fillFrom(const self_t& other)
1534		{
1535			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
1536		}
1537
1538		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
1539		{
1540			bool source_override = source_provided && (overwrite || !dest_provided);
1541
1542			if (source_override || source.mCurChoice == mCurChoice)
1543			{
1544				return mergeBlock(block_data, source, overwrite);
1545			}
1546			return false;
1547		}
1548
1549		// merge with other block
1550		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
1551		{
1552			mCurChoice = other.mCurChoice;
1553			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite);
1554		}
1555
1556		// clear out old choice when param has changed
1557		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
1558		{ 
1559			param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
1560			// if we have a new choice...
1561			if (changed_param_handle != mCurChoice)
1562			{
1563				// clear provided flag on previous choice
1564				Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
1565				if (previous_choice) 
1566				{
1567					previous_choice->setProvided(false);
1568				}
1569				mCurChoice = changed_param_handle;
1570			}
1571			base_block_t::paramChanged(changed_param, user_provided);
1572		}
1573
1574		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
1575		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
1576
1577	protected:
1578		ChoiceBlock()
1579		:	mCurChoice(0)
1580		{
1581			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
1582		}
1583
1584		// Alternatives are mutually exclusive wrt other Alternatives in the same block.  
1585		// One alternative in a block will always have isChosen() == true.
1586		// At most one alternative in a block will have isProvided() == true.
1587		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
1588		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
1589		{
1590		public:
1591			friend class ChoiceBlock<DERIVED_BLOCK>;
1592
1593			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t;
1594			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
1595			typedef typename super_t::value_assignment_t								value_assignment_t;
1596
1597			using super_t::operator =;
1598
1599			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>())
1600			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1),
1601				mOriginalValue(val)
1602			{
1603				// assign initial choice to first declared option
1604				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr);
1605				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
1606				{
1607					if(blockp->mCurChoice == 0)
1608					{
1609						blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
1610					}
1611				}
1612			}
1613
1614			void choose()
1615			{
1616				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
1617			}
1618
1619			void chooseAs(value_assignment_t val)
1620			{
1621				super_t::set(val);
1622			}
1623
1624			void operator =(value_assignment_t val)
1625			{
1626				super_t::set(val);
1627			}
1628
1629			void operator()(typename super_t::value_assignment_t val) 
1630			{ 
1631				super_t::set(val);
1632			}
1633
1634			operator value_assignment_t() const 
1635			{
1636				return (*this)();
1637			} 
1638
1639			value_assignment_t operator()() const 
1640			{ 
1641				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
1642				{
1643					return super_t::getValue(); 
1644				}
1645				return mOriginalValue;
1646			} 
1647
1648			bool isChosen() const
1649			{
1650				return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
1651			}
1652		
1653		private:
1654			T			mOriginalValue;
1655		};
1656
1657	protected:
1658		static BlockDescriptor& selfBlockDescriptor()
1659		{
1660			static BlockDescriptor sBlockDescriptor;
1661			return sBlockDescriptor;
1662		}
1663
1664	private:
1665		param_handle_t	mCurChoice;
1666
1667		const Param* getCurrentChoice() const
1668		{
1669			return base_block_t::getParamFromHandle(mCurChoice);
1670		}
1671	};
1672
1673	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
1674	class Block 
1675	:	public BASE_BLOCK
1676	{
1677		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t;
1678		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;
1679
1680	public:
1681		typedef BASE_BLOCK base_block_t;
1682
1683		// take all provided params from other and apply to self
1684		bool overwriteFrom(const self_t& other)
1685		{
1686			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
1687		}
1688
1689		// take all provided params that are not already provided, and apply to self
1690		bool fillFrom(const self_t& other)
1691		{
1692			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
1693		}
1694
1695		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
1696		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
1697
1698	protected:
1699		Block()
1700		{
1701			//#pragma message("Parsing LLInitParam::Block")
1702			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
1703		}
1704
1705		//
1706		// Nested classes for declaring parameters
1707		//
1708		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
1709		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
1710		{
1711		public:
1712			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
1713			typedef typename super_t::value_assignment_t								value_assignment_t;
1714
1715			using super_t::operator();
1716			using super_t::operator =;
1717			
1718			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>())
1719			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1)
1720			{
1721				//#pragma message("Parsing LLInitParam::Block::Optional")
1722			}
1723
1724			Optional& operator =(value_assignment_t val)
1725			{
1726				set(val);
1727				return *this;
1728			}
1729
1730			DERIVED_BLOCK& operator()(value_assignment_t val)
1731			{
1732				super_t::set(val);
1733				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
1734			}
1735		};
1736
1737		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
1738		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
1739		{
1740		public:
1741			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;
1742			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t;
1743			typedef typename super_t::value_assignment_t								value_assignment_t;
1744
1745			using super_t::operator();
1746			using super_t::operator =;
1747
1748			// mandatory parameters require a name to be parseable
1749			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>())
1750			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1)
1751			{}
1752
1753			Mandatory& operator =(value_assignment_t val)
1754			{
1755				set(val);
1756				return *this;
1757			}
1758
1759			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
1760			{
1761				super_t::set(val);
1762				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
1763			}
1764
1765			static bool validate(const Param* p)
1766			{
1767				// valid only if provided
1768				return static_cast<const self_t*>(p)->isProvided();
1769			}
1770
1771		};
1772
1773		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> >
1774		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
1775		{
1776		public:
1777			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t;
1778			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;
1779			typedef typename super_t::container_t									container_t;
1780			typedef typename super_t::value_assignment_t							value_assignment_t;
1781			typedef typename super_t::iterator										iterator;
1782			typedef typename super_t::const_iterator								const_iterator;
1783
1784			explicit Multiple(const char* name = "")
1785			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
1786			{}
1787
1788			Multiple& operator =(value_assignment_t val)
1789			{
1790				set(val);
1791				return *this;
1792			}
1793
1794			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
1795			{
1796				super_t::set(val);
1797				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
1798			}
1799
1800			static bool validate(const Param* paramp) 
1801			{
1802				U32 num_valid = ((super_t*)paramp)->numValidElements();
1803				return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
1804			}
1805		};
1806
1807		class Deprecated : public Param
1808		{
1809		public:
1810			explicit Deprecated(const char* name)
1811			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr)
1812			{
1813				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor();
1814				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
1815				{
1816					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
1817													block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
1818													NULL,
1819													&deserializeParam,
1820													NULL,
1821													NULL,
1822													NULL, 
1823													0, S32_MAX));
1824					BaseBlock::addParam(block_descriptor, param_descriptor, name);
1825				}
1826			}
1827			
1828			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
1829			{
1830				if (name_stack_range.first == name_stack_range.second)
1831				{
1832					//std::string message = llformat("Deprecated value %s ignored", getName().c_str());
1833					//parser.parserWarning(message);
1834					return true;
1835				}
1836
1837				return false;
1838			}
1839		};
1840
1841		// different semantics for documentation purposes, but functionally identical
1842		typedef Deprecated Ignored;
1843
1844	protected:
1845		static BlockDescriptor& selfBlockDescriptor()
1846		{
1847			static BlockDescriptor sBlockDescriptor;
1848			return sBlockDescriptor;
1849		}
1850
1851		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block>
1852		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, 
1853			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value)
1854		{
1855			if (!param.isProvided())
1856			{
1857				param.set(value, false);
1858			}
1859		}
1860
1861	};
1862	
1863	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
1864	class BatchBlock
1865	:	public Block<DERIVED_BLOCK, BASE_BLOCK>
1866	{
1867	public:
1868		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
1869		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t;
1870
1871		BatchBlock()
1872		{}
1873
1874		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
1875		{
1876			if (new_name)
1877			{
1878				// reset block
1879				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
1880			}
1881			return super_t::deserializeBlock(p, name_stack_range, new_name);
1882		}
1883
1884		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
1885		{
1886			if (overwrite)
1887			{
1888				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
1889				// merge individual parameters into destination
1890				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite);
1891			}
1892			return false;
1893		}
1894	protected:
1895		static const DERIVED_BLOCK& defaultBatchValue()
1896		{
1897			static DERIVED_BLOCK default_value;
1898			return default_value;
1899		}
1900	};
1901
1902	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class
1903	// and not the derived class with the actual params
1904	template<typename DERIVED_BLOCK,
1905			typename BASE_BLOCK,
1906			typename NAME_VALUE_LOOKUP>
1907	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>,
1908					NAME_VALUE_LOOKUP,
1909					true>
1910	:	public NAME_VALUE_LOOKUP,
1911		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK>
1912	{
1913	public:
1914		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t;
1915		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t;
1916		typedef block_t value_t;
1917
1918		ParamValue()
1919		:	block_t(),
1920			mValidated(false)
1921		{}
1922
1923		ParamValue(value_assignment_t other)
1924		:	block_t(other),
1925			mValidated(false)
1926		{
1927		}
1928
1929		void setValue(value_assignment_t val)
1930		{
1931			*this = val;
1932		}
1933
1934		value_assignment_t getValue() const
1935		{
1936			return *this;
1937		}
1938
1939		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue()
1940		{
1941			return *this;
1942		}
1943
1944		operator value_assignment_t() const
1945		{
1946			return *this;
1947		}
1948
1949		value_assignment_t operator()() const
1950		{
1951			return *this;
1952		}
1953
1954	protected:
1955		mutable bool 	mValidated; // lazy validation flag
1956	};
1957
1958	template<typename T, bool IS_BLOCK>
1959	class ParamValue <BaseBlock::Lazy<T>,
1960					TypeValues<T>,
1961					IS_BLOCK>
1962	:	public IsBlock<T>::base_class_t
1963	{
1964	public:
1965		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t;
1966		typedef const T& value_assignment_t;
1967		typedef T value_t;
1968	
1969		ParamValue()
1970		:	mValue(),
1971			mValidated(false)
1972		{}
1973
1974		ParamValue(value_assignment_t other)
1975		:	mValue(other),
1976			mValidated(false)
1977		{}
1978
1979		void setValue(value_assignment_t val)
1980		{
1981			mValue.set(val);
1982		}
1983
1984		value_assignment_t getValue() const
1985		{
1986			return mValue.get();
1987		}
1988
1989		T& getValue()
1990		{
1991			return mValue.get();
1992		}
1993
1994		operator value_assignment_t() const
1995		{
1996			return mValue.get();
1997		}
1998
1999		value_assignment_t operator()() const
2000		{
2001			return mValue.get();
2002		}
2003
2004		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
2005		{
2006			return mValue.get().deserializeBlock(p, name_stack_range, new_name);
2007		}
2008
2009		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
2010		{
2011			if (mValue.empty()) return;
2012			
2013			mValue.get().serializeBlock(p, name_stack, diff_block);
2014		}
2015
2016		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
2017		{
2018			if (mValue.empty()) return false;
2019
2020			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
2021		}
2022
2023	protected:
2024		mutable bool 	mValidated; // lazy validation flag
2025
2026	private:
2027		BaseBlock::Lazy<T>	mValue;
2028	};
2029
2030	template <>
2031	class ParamValue <LLSD,
2032					TypeValues<LLSD>,
2033					false>
2034	:	public TypeValues<LLSD>,
2035		public BaseBlock
2036	{
2037	public:
2038		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t;
2039		typedef const LLSD&	value_assignment_t;
2040
2041		ParamValue()
2042		:	mValidated(false)
2043		{}
2044
2045		ParamValue(value_assignment_t other)
2046		:	mValue(other),
2047			mValidated(false)
2048		{}
2049
2050		void setValue(value_assignment_t val) { mValue = val; }
2051
2052		value_assignment_t getValue() const { return mValue; }
2053		LLSD& getValue() { return mValue; }
2054
2055		operator value_assignment_t() const { return mValue; }
2056		value_assignment_t operator()() const { return mValue; }
2057		
2058
2059		// block param interface
2060		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
2061		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
2062		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
2063		{
2064			//TODO: implement LLSD params as schema type Any
2065			return true;
2066		}
2067
2068	protected:
2069		mutable bool 	mValidated; // lazy validation flag
2070
2071	private:
2072		static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
2073
2074		LLSD mValue;
2075	};
2076
2077	template<typename T>
2078	class CustomParamValue
2079	:	public Block<ParamValue<T, TypeValues<T> > >,
2080		public TypeValues<T>
2081	{
2082	public:
2083		typedef enum e_value_age
2084		{	
2085			VALUE_NEEDS_UPDATE,		// mValue needs to be refreshed from the block parameters
2086			VALUE_AUTHORITATIVE,	// mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
2087			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative
2088		} EValueAge;
2089
2090		typedef ParamValue<T, TypeValues<T> >	derived_t;
2091		typedef CustomParamValue<T>				self_t;
2092		typedef Block<derived_t>				block_t;
2093		typedef const T&						value_assignment_t;
2094		typedef T								value_t;
2095
2096
2097		CustomParamValue(const T& value = T())
2098		:	mValue(value),
2099			mValueAge(VALUE_AUTHORITATIVE),
2100			mValidated(false)
2101		{}
2102
2103		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
2104		{
2105			derived_t& typed_param = static_cast<derived_t&>(*this);
2106			// try to parse direct value T
2107			if (name_stack_range.first == name_stack_range.second)
2108			{
2109				if(parser.readValue(typed_param.mValue))
2110				{
2111					typed_param.mValueAge = VALUE_AUTHORITATIVE;
2112					typed_param.updateBlockFromValue(false);
2113
2114					typed_param.clearValueName();
2115
2116					return true;
2117				}
2118			}
2119
2120			// fall back on parsing block components for T
2121			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
2122		}
2123
2124		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
2125		{
2126			const derived_t& typed_param = static_cast<const derived_t&>(*this);
2127			const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
2128			
2129			std::string key = typed_param.getValueName();
2130
2131			// first try to write out name of name/value pair
2132			if (!key.empty())
2133			{
2134				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
2135				{
2136					parser.writeValue(key, name_stack);
2137				}
2138			}
2139			// then try to serialize value directly
2140			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
2141            {
2142				
2143				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
2144				{
2145					//RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
2146					// since these tend to be viewed as the constructor arguments for the value T.  It seems
2147					// cleaner to treat the uniqueness of a BlockValue according to the generated value, and
2148					// not the individual components.  This way <color red="0" green="1" blue="0"/> will not
2149					// be exported as <color green="1"/>, since it was probably the intent of the user to 
2150					// be specific about the RGB color values.  This also fixes an issue where we distinguish
2151					// between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
2152
2153					if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
2154					{
2155						// if the value is authoritative but the parser doesn't accept the value type
2156						// go ahead and make a copy, and splat the value out to its component params
2157						// and serialize those params
2158						derived_t copy(typed_param);
2159						copy.updateBlockFromValue(true);
2160						copy.block_t::serializeBlock(parser, name_stack, NULL);
2161					}
2162					else
2163					{
2164						block_t::serializeBlock(parser, name_stack, NULL);
2165					}
2166				}
2167			}
2168		}
2169
2170		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
2171		{
2172			// first, inspect with actual type...
2173			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
2174			if (TypeValues<T>::getPossibleValues())
2175			{
2176				//...then inspect with possible string values...
2177				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());
2178			}
2179			// then recursively inspect contents...
2180			return block_t::inspectBlock(parser, name_stack, min_count, max_count);
2181		}
2182
2183		bool validateBlock(bool emit_errors = true) const
2184		{
2185			if (mValueAge == VALUE_NEEDS_UPDATE)
2186			{
2187				if (block_t::validateBlock(emit_errors))
2188				{
2189					// clear stale keyword associated with old value
2190					TypeValues<T>::clearValueName();
2191					mValueAge = BLOCK_AUTHORITATIVE;
2192					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
2193					return true;
2194				}
2195				else
2196				{
2197					//block value incomplete, so not considered provided
2198					// will attempt to revalidate on next call to isProvided()
2199					return false;  
2200				}
2201			}
2202			else
2203			{
2204				// we have a valid value in hand
2205				return true;
2206			}
2207		}
2208
2209 		// propagate change status up to enclosing block
2210		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
2211		{ 
2212			BaseBlock::paramChanged(changed_param, user_provided);
2213			if (user_provided)
2214			{
2215				// a parameter changed, so our value is out of date
2216				mValueAge = VALUE_NEEDS_UPDATE;
2217			}
2218		}
2219			
2220		void setValue(value_assignment_t val)
2221		{
2222			derived_t& typed_param = static_cast<derived_t&>(*this);
2223			// set param version number to be up to date, so we ignore block contents
2224			mValueAge = VALUE_AUTHORITATIVE;
2225			mValue = val;
2226			typed_param.clearValueName();
2227			static_cast<derived_t*>(this)->updateBlockFromValue(false);
2228		}
2229
2230		value_assignment_t getValue() const
2231		{
2232			validateBlock(true);
2233			return mValue;
2234		}
2235
2236		T& getValue() 
2237		{
2238			validateBlock(true);
2239			return mValue;
2240		}
2241
2242		operator value_assignment_t() const
2243		{
2244			return getValue();
2245		}
2246
2247		value_assignment_t operator()() const
2248		{
2249			return getValue();
2250		}
2251
2252	protected:
2253
2254		// use this from within updateValueFromBlock() to set the value without making it authoritative
2255		void updateValue(value_assignment_t value)
2256		{
2257			mValue = value;
2258		}
2259
2260		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
2261		{
2262			bool source_override = source_provided && (overwrite || !dst_provided);
2263
2264			const derived_t& src_typed_param = static_cast<const derived_t&>(source);
2265
2266			if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
2267			{
2268				// copy value over
2269				setValue(src_typed_param.getValue());
2270				return true;
2271			}
2272			// merge individual parameters into destination
2273			if (mValueAge == VALUE_AUTHORITATIVE)
2274			{
2275				static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
2276			}
2277			return mergeBlock(block_data, source, overwrite);
2278		}
2279
2280		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
2281		{
2282			return block_t::mergeBlock(block_data, source, overwrite);
2283		}
2284
2285		mutable bool 		mValidated; // lazy validation flag
2286
2287	private:
2288		mutable T			mValue;
2289		mutable EValueAge	mValueAge;
2290	};
2291}
2292
2293
2294#endif // LL_LLPARAM_H