PageRenderTime 140ms CodeModel.GetById 19ms app.highlight 106ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

   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									c

Large files files are truncated, but you can click here to view the full file