summaryrefslogtreecommitdiff
path: root/indra/llxuixml/llinitparam.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llxuixml/llinitparam.h')
-rw-r--r--indra/llxuixml/llinitparam.h2299
1 files changed, 0 insertions, 2299 deletions
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
deleted file mode 100644
index 4ab1d891a3..0000000000
--- a/indra/llxuixml/llinitparam.h
+++ /dev/null
@@ -1,2299 +0,0 @@
-/**
- * @file llinitparam.h
- * @brief parameter block abstraction for creating complex objects and
- * parsing construction parameters from xml and LLSD
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPARAM_H
-#define LL_LLPARAM_H
-
-#include <vector>
-#include <boost/function.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/unordered_map.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include "llerror.h"
-
-namespace LLInitParam
-{
- // used to indicate no matching value to a given name when parsing
- struct Flag{};
-
- template<typename T> const T& defaultValue() { static T value; return value; }
-
- template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
- struct ParamCompare
- {
- static bool equals(const T &a, const T &b)
- {
- return a == b;
- }
- };
-
- // boost function types are not comparable
- template<typename T>
- struct ParamCompare<T, true>
- {
- static bool equals(const T&a, const T &b)
- {
- return false;
- }
- };
-
- template<>
- struct ParamCompare<LLSD, false>
- {
- static bool equals(const LLSD &a, const LLSD &b) { return false; }
- };
-
- template<>
- struct ParamCompare<Flag, false>
- {
- static bool equals(const Flag& a, const Flag& b) { return false; }
- };
-
-
- // helper functions and classes
- typedef ptrdiff_t param_handle_t;
-
- // empty default implementation of key cache
- // leverages empty base class optimization
- template <typename T>
- class TypeValues
- {
- private:
- struct Inaccessable{};
- public:
- typedef std::map<std::string, T> value_name_map_t;
- typedef Inaccessable name_t;
-
- void setValueName(const std::string& key) {}
- std::string getValueName() const { return ""; }
- std::string calcValueName(const T& value) const { return ""; }
- void clearValueName() const {}
-
- static bool getValueFromName(const std::string& name, T& value)
- {
- return false;
- }
-
- static bool valueNamesExist()
- {
- return false;
- }
-
- static std::vector<std::string>* getPossibleValues()
- {
- return NULL;
- }
-
- static value_name_map_t* getValueNames() {return NULL;}
- };
-
- template <typename T, typename DERIVED_TYPE = TypeValues<T> >
- class TypeValuesHelper
- {
- public:
- typedef typename std::map<std::string, T> value_name_map_t;
- typedef std::string name_t;
-
- //TODO: cache key by index to save on param block size
- void setValueName(const std::string& value_name)
- {
- mValueName = value_name;
- }
-
- std::string getValueName() const
- {
- return mValueName;
- }
-
- std::string calcValueName(const T& value) const
- {
- value_name_map_t* map = getValueNames();
- for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
- it != end_it;
- ++it)
- {
- if (ParamCompare<T>::equals(it->second, value))
- {
- return it->first;
- }
- }
-
- return "";
- }
-
- void clearValueName() const
- {
- mValueName.clear();
- }
-
- static bool getValueFromName(const std::string& name, T& value)
- {
- value_name_map_t* map = getValueNames();
- typename value_name_map_t::iterator found_it = map->find(name);
- if (found_it == map->end()) return false;
-
- value = found_it->second;
- return true;
- }
-
- static bool valueNamesExist()
- {
- return !getValueNames()->empty();
- }
-
- static value_name_map_t* getValueNames()
- {
- static value_name_map_t sMap;
- static bool sInitialized = false;
-
- if (!sInitialized)
- {
- sInitialized = true;
- DERIVED_TYPE::declareValues();
- }
- return &sMap;
- }
-
- static std::vector<std::string>* getPossibleValues()
- {
- static std::vector<std::string> sValues;
-
- value_name_map_t* map = getValueNames();
- for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end();
- it != end_it;
- ++it)
- {
- sValues.push_back(it->first);
- }
- return &sValues;
- }
-
- static void declare(const std::string& name, const T& value)
- {
- (*getValueNames())[name] = value;
- }
-
- protected:
- static void getName(const std::string& name, const T& value)
- {}
-
- mutable std::string mValueName;
- };
-
- class Parser
- {
- LOG_CLASS(Parser);
-
- public:
-
- struct CompareTypeID
- {
- bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
- {
- return lhs->before(*rhs);
- }
- };
-
- typedef std::vector<std::pair<std::string, bool> > name_stack_t;
- typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t;
- typedef std::vector<std::string> possible_values_t;
-
- typedef bool (*parser_read_func_t)(Parser& parser, void* output);
- typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
- typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
-
- typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID> parser_read_func_map_t;
- typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID> parser_write_func_map_t;
- typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID> parser_inspect_func_map_t;
-
- Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
- : mParseSilently(false),
- mParserReadFuncs(&read_map),
- mParserWriteFuncs(&write_map),
- mParserInspectFuncs(&inspect_map)
- {}
- virtual ~Parser();
-
- template <typename T> bool readValue(T& param)
- {
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
- if (found_it != mParserReadFuncs->end())
- {
- return found_it->second(*this, (void*)&param);
- }
- return false;
- }
-
- template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
- {
- parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
- if (found_it != mParserWriteFuncs->end())
- {
- return found_it->second(*this, (const void*)&param, name_stack);
- }
- return false;
- }
-
- // dispatch inspection to registered inspection functions, for each parameter in a param block
- template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
- {
- parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
- if (found_it != mParserInspectFuncs->end())
- {
- found_it->second(name_stack, min_count, max_count, possible_values);
- return true;
- }
- return false;
- }
-
- virtual std::string getCurrentElementName() = 0;
- virtual void parserWarning(const std::string& message);
- virtual void parserError(const std::string& message);
- void setParseSilently(bool silent) { mParseSilently = silent; }
-
- protected:
- template <typename T>
- void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
- {
- mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
- mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
- }
-
- template <typename T>
- void registerInspectFunc(parser_inspect_func_t inspect_func)
- {
- mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
- }
-
- bool mParseSilently;
-
- private:
- parser_read_func_map_t* mParserReadFuncs;
- parser_write_func_map_t* mParserWriteFuncs;
- parser_inspect_func_map_t* mParserInspectFuncs;
- };
-
- class Param;
-
- // various callbacks and constraints associated with an individual param
- struct ParamDescriptor
- {
- struct UserData
- {
- virtual ~UserData() {}
- };
-
- typedef bool(*merge_func_t)(Param&, const Param&, bool);
- typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
- typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
- typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
- typedef bool(*validation_func_t)(const Param*);
-
- ParamDescriptor(param_handle_t p,
- merge_func_t merge_func,
- deserialize_func_t deserialize_func,
- serialize_func_t serialize_func,
- validation_func_t validation_func,
- inspect_func_t inspect_func,
- S32 min_count,
- S32 max_count);
-
- ParamDescriptor();
- ~ParamDescriptor();
-
- param_handle_t mParamHandle;
- merge_func_t mMergeFunc;
- deserialize_func_t mDeserializeFunc;
- serialize_func_t mSerializeFunc;
- inspect_func_t mInspectFunc;
- validation_func_t mValidationFunc;
- S32 mMinCount;
- S32 mMaxCount;
- S32 mNumRefs;
- UserData* mUserData;
- };
-
- typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
-
- // each derived Block class keeps a static data structure maintaining offsets to various params
- class BlockDescriptor
- {
- public:
- BlockDescriptor();
-
- typedef enum e_initialization_state
- {
- UNINITIALIZED,
- INITIALIZING,
- INITIALIZED
- } EInitializationState;
-
- void aggregateBlockData(BlockDescriptor& src_block_data);
-
- typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t;
- typedef std::vector<ParamDescriptorPtr> param_list_t;
- typedef std::list<ParamDescriptorPtr> all_params_list_t;
- typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t;
-
- param_map_t mNamedParams; // parameters with associated names
- param_list_t mUnnamedParams; // parameters with_out_ associated names
- param_validation_list_t mValidationList; // parameters that must be validated
- all_params_list_t mAllParams; // all parameters, owns descriptors
- size_t mMaxParamOffset;
- EInitializationState mInitializationState; // whether or not static block data has been initialized
- class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
- };
-
- class BaseBlock
- {
- public:
- //TODO: implement in terms of owned_ptr
- template<typename T>
- class Lazy
- {
- public:
- Lazy()
- : mPtr(NULL)
- {}
-
- ~Lazy()
- {
- delete mPtr;
- }
-
- Lazy(const Lazy& other)
- {
- if (other.mPtr)
- {
- mPtr = new T(*other.mPtr);
- }
- else
- {
- mPtr = NULL;
- }
- }
-
- Lazy<T>& operator = (const Lazy<T>& other)
- {
- if (other.mPtr)
- {
- mPtr = new T(*other.mPtr);
- }
- else
- {
- mPtr = NULL;
- }
- return *this;
- }
-
- bool empty() const
- {
- return mPtr == NULL;
- }
-
- void set(const T& other)
- {
- delete mPtr;
- mPtr = new T(other);
- }
-
- const T& get() const
- {
- return ensureInstance();
- }
-
- T& get()
- {
- return ensureInstance();
- }
-
- private:
- // lazily allocate an instance of T
- T* ensureInstance() const
- {
- if (mPtr == NULL)
- {
- mPtr = new T();
- }
- return mPtr;
- }
-
- private:
- // if you get a compilation error with this, that means you are using a forward declared struct for T
- // unfortunately, the type traits we rely on don't work with forward declared typed
- //static const int dummy = sizeof(T);
-
- mutable T* mPtr;
- };
-
- // "Multiple" constraint types, put here in root class to avoid ambiguity during use
- struct AnyAmount
- {
- enum { minCount = 0 };
- enum { maxCount = U32_MAX };
- };
-
- template<U32 MIN_AMOUNT>
- struct AtLeast
- {
- enum { minCount = MIN_AMOUNT };
- enum { maxCount = U32_MAX };
- };
-
- template<U32 MAX_AMOUNT>
- struct AtMost
- {
- enum { minCount = 0 };
- enum { maxCount = MAX_AMOUNT };
- };
-
- template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
- struct Between
- {
- enum { minCount = MIN_AMOUNT };
- enum { maxCount = MAX_AMOUNT };
- };
-
- template<U32 EXACT_COUNT>
- struct Exactly
- {
- enum { minCount = EXACT_COUNT };
- enum { maxCount = EXACT_COUNT };
- };
-
- // this typedef identifies derived classes as being blocks
- typedef void baseblock_base_class_t;
- LOG_CLASS(BaseBlock);
- friend class Param;
-
- virtual ~BaseBlock() {}
- bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
-
- param_handle_t getHandleFromParam(const Param* param) const;
- bool validateBlock(bool emit_errors = true) const;
-
- Param* getParamFromHandle(const param_handle_t param_handle)
- {
- if (param_handle == 0) return NULL;
-
- U8* baseblock_address = reinterpret_cast<U8*>(this);
- return reinterpret_cast<Param*>(baseblock_address + param_handle);
- }
-
- const Param* getParamFromHandle(const param_handle_t param_handle) const
- {
- const U8* baseblock_address = reinterpret_cast<const U8*>(this);
- return reinterpret_cast<const Param*>(baseblock_address + param_handle);
- }
-
- void addSynonym(Param& param, const std::string& synonym);
-
- // Blocks can override this to do custom tracking of changes
- virtual void paramChanged(const Param& changed_param, bool user_provided) {}
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
- // take all provided params from other and apply to self
- bool overwriteFrom(const BaseBlock& other)
- {
- return false;
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const BaseBlock& other)
- {
- return false;
- }
-
- static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name);
-
- ParamDescriptorPtr findParamDescriptor(const Param& param);
-
- protected:
- void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
-
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- return mergeBlock(block_data, source, overwrite);
- }
- // take all provided params from other and apply to self
- bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
-
- static BlockDescriptor& selfBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- private:
- const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
- };
-
- template<typename T>
- struct ParamCompare<BaseBlock::Lazy<T>, false >
- {
- static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); }
- };
-
- class Param
- {
- public:
- void setProvided(bool is_provided = true)
- {
- mIsProvided = is_provided;
- enclosingBlock().paramChanged(*this, is_provided);
- }
-
- Param& operator =(const Param& other)
- {
- mIsProvided = other.mIsProvided;
- // don't change mEnclosingblockoffset
- return *this;
- }
- protected:
-
- bool anyProvided() const { return mIsProvided; }
-
- Param(BaseBlock* enclosing_block);
-
- // store pointer to enclosing block as offset to reduce space and allow for quick copying
- BaseBlock& enclosingBlock() const
- {
- const U8* my_addr = reinterpret_cast<const U8*>(this);
- // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
- return *const_cast<BaseBlock*>
- (reinterpret_cast<const BaseBlock*>
- (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
- }
-
- private:
- friend class BaseBlock;
-
- U32 mEnclosingBlockOffset:31;
- U32 mIsProvided:1;
-
- };
-
- // these templates allow us to distinguish between template parameters
- // that derive from BaseBlock and those that don't
- template<typename T, typename Void = void>
- struct IsBlock
- {
- static const bool value = false;
- struct EmptyBase {};
- typedef EmptyBase base_class_t;
- };
-
- template<typename T>
- struct IsBlock<T, typename T::baseblock_base_class_t>
- {
- static const bool value = true;
- typedef BaseBlock base_class_t;
- };
-
- template<typename T>
- struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t >
- {
- static const bool value = true;
- typedef BaseBlock base_class_t;
- };
-
- template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value>
- class ParamValue : public NAME_VALUE_LOOKUP
- {
- public:
- typedef const T& value_assignment_t;
- typedef T value_t;
- typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK> self_t;
-
- ParamValue(): mValue() {}
- ParamValue(value_assignment_t other) : mValue(other) {}
-
- void setValue(value_assignment_t val)
- {
- mValue = val;
- }
-
- value_assignment_t getValue() const
- {
- return mValue;
- }
-
- T& getValue()
- {
- return mValue;
- }
-
- operator value_assignment_t() const
- {
- return mValue;
- }
-
- value_assignment_t operator()() const
- {
- return mValue;
- }
-
- void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- *this = name;
- }
-
- self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue))
- {
- setValueName(name);
- }
-
- return *this;
- }
-
- protected:
- T mValue;
- };
-
- template<typename T, typename NAME_VALUE_LOOKUP>
- class ParamValue<T, NAME_VALUE_LOOKUP, true>
- : public T,
- public NAME_VALUE_LOOKUP
- {
- public:
- typedef const T& value_assignment_t;
- typedef T value_t;
- typedef ParamValue<T, NAME_VALUE_LOOKUP, true> self_t;
-
- ParamValue()
- : T(),
- mValidated(false)
- {}
-
- ParamValue(value_assignment_t other)
- : T(other),
- mValidated(false)
- {}
-
- void setValue(value_assignment_t val)
- {
- *this = val;
- }
-
- value_assignment_t getValue() const
- {
- return *this;
- }
-
- T& getValue()
- {
- return *this;
- }
-
- operator value_assignment_t() const
- {
- return *this;
- }
-
- value_assignment_t operator()() const
- {
- return *this;
- }
-
- void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- *this = name;
- }
-
- self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- if (NAME_VALUE_LOOKUP::getValueFromName(name, *this))
- {
- setValueName(name);
- }
-
- return *this;
- }
-
- protected:
- mutable bool mValidated; // lazy validation flag
- };
-
- template<typename NAME_VALUE_LOOKUP>
- class ParamValue<std::string, NAME_VALUE_LOOKUP, false>
- : public NAME_VALUE_LOOKUP
- {
- public:
- typedef const std::string& value_assignment_t;
- typedef std::string value_t;
- typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false> self_t;
-
- ParamValue(): mValue() {}
- ParamValue(value_assignment_t other) : mValue(other) {}
-
- void setValue(value_assignment_t val)
- {
- if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue))
- {
- NAME_VALUE_LOOKUP::setValueName(val);
- }
- else
- {
- mValue = val;
- }
- }
-
- value_assignment_t getValue() const
- {
- return mValue;
- }
-
- std::string& getValue()
- {
- return mValue;
- }
-
- operator value_assignment_t() const
- {
- return mValue;
- }
-
- value_assignment_t operator()() const
- {
- return mValue;
- }
-
- protected:
- std::string mValue;
- };
-
-
- template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- struct ParamIterator
- {
- typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator const_iterator;
- typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator iterator;
- };
-
- // specialize for custom parsing/decomposition of specific classes
- // e.g. TypedParam<LLRect> has left, top, right, bottom, etc...
- template<typename T,
- typename NAME_VALUE_LOOKUP = TypeValues<T>,
- bool HAS_MULTIPLE_VALUES = false,
- bool VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>
- class TypedParam
- : public Param,
- public ParamValue<T, NAME_VALUE_LOOKUP>
- {
- public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t;
- typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t;
- typedef typename param_value_t::value_assignment_t value_assignment_t;
- typedef NAME_VALUE_LOOKUP name_value_lookup_t;
-
- using param_value_t::operator();
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr)
- {
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- BaseBlock::addParam(block_descriptor, param_descriptor, name);
- }
-
- setValue(value);
- }
-
- bool isProvided() const { return Param::anyProvided(); }
-
- static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
- // no further names in stack, attempt to parse value now
- if (name_stack_range.first == name_stack_range.second)
- {
- if (parser.readValue(typed_param.getValue()))
- {
- typed_param.clearValueName();
- typed_param.setProvided();
- return true;
- }
-
- // try to parse a known named value
- if(name_value_lookup_t::valueNamesExist())
- {
- // try to parse a known named value
- std::string name;
- if (parser.readValue(name))
- {
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
- {
- typed_param.setValueName(name);
- typed_param.setProvided();
- return true;
- }
-
- }
- }
- }
- return false;
- }
-
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
-
- if (!name_stack.empty())
- {
- name_stack.back().second = true;
- }
-
- std::string key = typed_param.getValueName();
-
- // first try to write out name of name/value pair
-
- if (!key.empty())
- {
- if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
- {
- parser.writeValue(key, name_stack);
- }
- }
- // then try to serialize value directly
- else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
- {
- if (!parser.writeValue(typed_param.getValue(), name_stack))
- {
- std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
- if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
- {
- parser.writeValue(calculated_key, name_stack);
- }
- }
- }
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- // tell parser about our actual type
- parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
- // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
- if (name_value_lookup_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
- }
- }
-
- void set(value_assignment_t val, bool flag_as_provided = true)
- {
- param_value_t::clearValueName();
- setValue(val);
- setProvided(flag_as_provided);
- }
-
- self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- return static_cast<self_t&>(param_value_t::operator =(name));
- }
-
- protected:
-
- self_t& operator =(const self_t& other)
- {
- param_value_t::operator =(other);
- Param::operator =(other);
- return *this;
- }
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (src_typed_param.isProvided()
- && (overwrite || !dst_typed_param.isProvided()))
- {
- dst_typed_param.set(src_typed_param.getValue());
- return true;
- }
- return false;
- }
- };
-
- // parameter that is a block
- template <typename T, typename NAME_VALUE_LOOKUP>
- class TypedParam<T, NAME_VALUE_LOOKUP, false, true>
- : public Param,
- public ParamValue<T, NAME_VALUE_LOOKUP>
- {
- public:
- typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t;
- typedef typename param_value_t::value_assignment_t value_assignment_t;
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t;
- typedef NAME_VALUE_LOOKUP name_value_lookup_t;
-
- using param_value_t::operator();
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr),
- param_value_t(value)
- {
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- BaseBlock::addParam(block_descriptor, param_descriptor, name);
- }
- }
-
- static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
- // attempt to parse block...
- if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
- {
- typed_param.clearValueName();
- typed_param.setProvided();
- return true;
- }
-
- if(name_value_lookup_t::valueNamesExist())
- {
- // try to parse a known named value
- std::string name;
- if (parser.readValue(name))
- {
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))
- {
- typed_param.setValueName(name);
- typed_param.setProvided();
- return true;
- }
-
- }
- }
- return false;
- }
-
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
-
- if (!name_stack.empty())
- {
- name_stack.back().second = true;
- }
-
- std::string key = typed_param.getValueName();
- if (!key.empty())
- {
- if (!parser.writeValue(key, name_stack))
- {
- return;
- }
- }
- else
- {
- typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
- }
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- // I am a param that is also a block, so just recurse into my contents
- const self_t& typed_param = static_cast<const self_t&>(param);
- typed_param.inspectBlock(parser, name_stack, min_count, max_count);
- }
-
- // a param-that-is-a-block is provided when the user has set one of its child params
- // *and* the block as a whole validates
- bool isProvided() const
- {
- // only validate block when it hasn't already passed validation with current data
- if (Param::anyProvided() && !param_value_t::mValidated)
- {
- // a sub-block is "provided" when it has been filled in enough to be valid
- param_value_t::mValidated = param_value_t::validateBlock(false);
- }
- return Param::anyProvided() && param_value_t::mValidated;
- }
-
- // assign block contents to this param-that-is-a-block
- void set(value_assignment_t val, bool flag_as_provided = true)
- {
- setValue(val);
- param_value_t::clearValueName();
- // force revalidation of block
- // next call to isProvided() will update provision status based on validity
- param_value_t::mValidated = false;
- setProvided(flag_as_provided);
- }
-
- self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name)
- {
- return static_cast<self_t&>(param_value_t::operator =(name));
- }
-
- // propagate changed status up to enclosing block
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- param_value_t::paramChanged(changed_param, user_provided);
- if (user_provided)
- {
- // a child param has been explicitly changed
- // so *some* aspect of this block is now provided
- param_value_t::mValidated = false;
- setProvided();
- param_value_t::clearValueName();
- }
- else
- {
- Param::enclosingBlock().paramChanged(*this, user_provided);
- }
- }
-
- protected:
-
- self_t& operator =(const self_t& other)
- {
- param_value_t::operator =(other);
- Param::operator =(other);
- return *this;
- }
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (src_typed_param.anyProvided())
- {
- if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite))
- {
- dst_typed_param.clearValueName();
- dst_typed_param.setProvided(true);
- return true;
- }
- }
- return false;
- }
- };
-
- // container of non-block parameters
- template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>
- : public Param
- {
- public:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> self_t;
- typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t;
- typedef typename std::vector<param_value_t> container_t;
- typedef const container_t& value_assignment_t;
-
- typedef typename param_value_t::value_t value_t;
- typedef NAME_VALUE_LOOKUP name_value_lookup_t;
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr)
- {
- std::copy(value.begin(), value.end(), std::back_inserter(mValues));
-
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- BaseBlock::addParam(block_descriptor, param_descriptor, name);
- }
- }
-
- bool isProvided() const { return Param::anyProvided(); }
-
- static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
- value_t value;
- // no further names in stack, attempt to parse value now
- if (name_stack_range.first == name_stack_range.second)
- {
- // attempt to read value directly
- if (parser.readValue(value))
- {
- typed_param.add(value);
- return true;
- }
-
- // try to parse a known named value
- if(name_value_lookup_t::valueNamesExist())
- {
- // try to parse a known named value
- std::string name;
- if (parser.readValue(name))
- {
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, value))
- {
- typed_param.add(value);
- typed_param.mValues.back().setValueName(name);
- return true;
- }
-
- }
- }
- }
- return false;
- }
-
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided() || name_stack.empty()) return;
-
- for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
- it != end_it;
- ++it)
- {
- std::string key = it->getValueName();
- name_stack.back().second = true;
-
- if(key.empty())
- // not parsed via name values, write out value directly
- {
- bool value_written = parser.writeValue(*it, name_stack);
- if (!value_written)
- {
- std::string calculated_key = it->calcValueName(it->getValue());
- if (!parser.writeValue(calculated_key, name_stack))
- {
- break;
- }
- }
- }
- else
- {
- if(!parser.writeValue(key, name_stack))
- {
- break;
- }
- }
- }
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
- if (name_value_lookup_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
- }
- }
-
- void set(value_assignment_t val, bool flag_as_provided = true)
- {
- mValues = val;
- setProvided(flag_as_provided);
- }
-
- param_value_t& add()
- {
- mValues.push_back(param_value_t(value_t()));
- Param::setProvided();
- return mValues.back();
- }
-
- self_t& add(const value_t& item)
- {
- param_value_t param_value;
- param_value.setValue(item);
- mValues.push_back(param_value);
- setProvided();
- return *this;
- }
-
- self_t& add(const typename name_value_lookup_t::name_t& name)
- {
- value_t value;
-
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, value))
- {
- add(value);
- mValues.back().setValueName(name);
- }
-
- return *this;
- }
-
- // implicit conversion
- operator value_assignment_t() const { return mValues; }
- // explicit conversion
- value_assignment_t operator()() const { return mValues; }
-
- typedef typename container_t::iterator iterator;
- typedef typename container_t::const_iterator const_iterator;
- iterator begin() { return mValues.begin(); }
- iterator end() { return mValues.end(); }
- const_iterator begin() const { return mValues.begin(); }
- const_iterator end() const { return mValues.end(); }
- bool empty() const { return mValues.empty(); }
- size_t size() const { return mValues.size(); }
-
- U32 numValidElements() const
- {
- return mValues.size();
- }
-
- protected:
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (overwrite)
- {
- std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
- }
- else
- {
- container_t new_values(src_typed_param.mValues);
- std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
- std::swap(dst_typed_param.mValues, new_values);
- }
-
- if (src_typed_param.begin() != src_typed_param.end())
- {
- dst_typed_param.setProvided();
- }
- return true;
- }
-
- container_t mValues;
- };
-
- // container of block parameters
- template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>
- : public Param
- {
- public:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> self_t;
- typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t;
- typedef typename std::vector<param_value_t> container_t;
- typedef const container_t& value_assignment_t;
- typedef typename param_value_t::value_t value_t;
- typedef NAME_VALUE_LOOKUP name_value_lookup_t;
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr)
- {
- std::copy(value.begin(), value.end(), back_inserter(mValues));
-
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- BaseBlock::addParam(block_descriptor, param_descriptor, name);
- }
- }
-
- bool isProvided() const { return Param::anyProvided(); }
-
- static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
- bool new_value = false;
-
- if (new_name || typed_param.mValues.empty())
- {
- new_value = true;
- typed_param.mValues.push_back(value_t());
- }
-
- param_value_t& value = typed_param.mValues.back();
-
- // attempt to parse block...
- if(value.deserializeBlock(parser, name_stack_range, new_name))
- {
- typed_param.setProvided();
- return true;
- }
- else if(name_value_lookup_t::valueNamesExist())
- {
- // try to parse a known named value
- std::string name;
- if (parser.readValue(name))
- {
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, value.getValue()))
- {
- typed_param.mValues.back().setValueName(name);
- typed_param.setProvided();
- return true;
- }
-
- }
- }
-
- if (new_value)
- { // failed to parse new value, pop it off
- typed_param.mValues.pop_back();
- }
-
- return false;
- }
-
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided() || name_stack.empty()) return;
-
- for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
- it != end_it;
- ++it)
- {
- name_stack.back().second = true;
-
- std::string key = it->getValueName();
- if (!key.empty())
- {
- parser.writeValue(key, name_stack);
- }
- // Not parsed via named values, write out value directly
- // NOTE: currently we don't worry about removing default values in Multiple
- else
- {
- it->serializeBlock(parser, name_stack, NULL);
- }
- }
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- // I am a vector of blocks, so describe my contents recursively
- param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count);
- }
-
- void set(value_assignment_t val, bool flag_as_provided = true)
- {
- mValues = val;
- setProvided(flag_as_provided);
- }
-
- param_value_t& add()
- {
- mValues.push_back(value_t());
- setProvided();
- return mValues.back();
- }
-
- self_t& add(const value_t& item)
- {
- mValues.push_back(item);
- setProvided();
- return *this;
- }
-
- self_t& add(const typename name_value_lookup_t::name_t& name)
- {
- value_t value;
-
- // try to parse a per type named value
- if (name_value_lookup_t::getValueFromName(name, value))
- {
- add(value);
- mValues.back().setValueName(name);
- }
- return *this;
- }
-
- // implicit conversion
- operator value_assignment_t() const { return mValues; }
- // explicit conversion
- value_assignment_t operator()() const { return mValues; }
-
- typedef typename container_t::iterator iterator;
- typedef typename container_t::const_iterator const_iterator;
- iterator begin() { return mValues.begin(); }
- iterator end() { return mValues.end(); }
- const_iterator begin() const { return mValues.begin(); }
- const_iterator end() const { return mValues.end(); }
- bool empty() const { return mValues.empty(); }
- size_t size() const { return mValues.size(); }
-
- U32 numValidElements() const
- {
- U32 count = 0;
- for (const_iterator it = mValues.begin(), end_it = mValues.end();
- it != end_it;
- ++it)
- {
- if(it->validateBlock(false)) count++;
- }
- return count;
- }
-
- protected:
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (overwrite)
- {
- std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
- }
- else
- {
- container_t new_values(src_typed_param.mValues);
- std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
- std::swap(dst_typed_param.mValues, new_values);
- }
-
- if (src_typed_param.begin() != src_typed_param.end())
- {
- dst_typed_param.setProvided();
- }
-
- return true;
- }
-
- container_t mValues;
- };
-
- template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
- class ChoiceBlock : public BASE_BLOCK
- {
- typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
- typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> enclosing_block_t;
- typedef BASE_BLOCK base_block_t;
-
- LOG_CLASS(self_t);
- public:
- // take all provided params from other and apply to self
- bool overwriteFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
- }
-
- bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
- {
- bool source_override = source_provided && (overwrite || !dest_provided);
-
- if (source_override || source.mCurChoice == mCurChoice)
- {
- return mergeBlock(block_data, source, overwrite);
- }
- return false;
- }
-
- // merge with other block
- bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
- {
- mCurChoice = other.mCurChoice;
- return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite);
- }
-
- // clear out old choice when param has changed
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
- // if we have a new choice...
- if (changed_param_handle != mCurChoice)
- {
- // clear provided flag on previous choice
- Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
- if (previous_choice)
- {
- previous_choice->setProvided(false);
- }
- mCurChoice = changed_param_handle;
- }
- base_block_t::paramChanged(changed_param, user_provided);
- }
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
- protected:
- ChoiceBlock()
- : mCurChoice(0)
- {
- BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
- }
-
- // Alternatives are mutually exclusive wrt other Alternatives in the same block.
- // One alternative in a block will always have isChosen() == true.
- // At most one alternative in a block will have isProvided() == true.
- template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- public:
- friend class ChoiceBlock<DERIVED_BLOCK>;
-
- typedef Alternative<T, NAME_VALUE_LOOKUP> self_t;
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
-
- using super_t::operator =;
-
- explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>())
- : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1),
- mOriginalValue(val)
- {
- // assign initial choice to first declared option
- DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr);
- if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
- {
- if(blockp->mCurChoice == 0)
- {
- blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
- }
- }
- }
-
- void choose()
- {
- static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
- }
-
- void chooseAs(value_assignment_t val)
- {
- super_t::set(val);
- }
-
- void operator =(value_assignment_t val)
- {
- super_t::set(val);
- }
-
- void operator()(typename super_t::value_assignment_t val)
- {
- super_t::set(val);
- }
-
- operator value_assignment_t() const
- {
- return (*this)();
- }
-
- value_assignment_t operator()() const
- {
- if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
- {
- return super_t::getValue();
- }
- return mOriginalValue;
- }
-
- bool isChosen() const
- {
- return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
- }
-
- private:
- T mOriginalValue;
- };
-
- protected:
- static BlockDescriptor& selfBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- private:
- param_handle_t mCurChoice;
-
- const Param* getCurrentChoice() const
- {
- return base_block_t::getParamFromHandle(mCurChoice);
- }
- };
-
- template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
- class Block
- : public BASE_BLOCK
- {
- typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t;
- typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t;
-
- public:
- typedef BASE_BLOCK base_block_t;
-
- // take all provided params from other and apply to self
- bool overwriteFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true);
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false);
- }
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
-
- protected:
- Block()
- {
- //#pragma message("Parsing LLInitParam::Block")
- BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK));
- }
-
- //
- // Nested classes for declaring parameters
- //
- template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
-
- using super_t::operator();
- using super_t::operator =;
-
- explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>())
- : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1)
- {
- //#pragma message("Parsing LLInitParam::Block::Optional")
- }
-
- Optional& operator =(value_assignment_t val)
- {
- set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(value_assignment_t val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
- };
-
- template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t;
- typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
-
- using super_t::operator();
- using super_t::operator =;
-
- // mandatory parameters require a name to be parseable
- explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>())
- : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1)
- {}
-
- Mandatory& operator =(value_assignment_t val)
- {
- set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
-
- static bool validate(const Param* p)
- {
- // valid only if provided
- return static_cast<const self_t*>(p)->isProvided();
- }
-
- };
-
- template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
- {
- public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t;
- typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t;
- typedef typename super_t::container_t container_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
- typedef typename super_t::iterator iterator;
- typedef typename super_t::const_iterator const_iterator;
-
- explicit Multiple(const char* name = "")
- : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
- {}
-
- Multiple& operator =(value_assignment_t val)
- {
- set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
-
- static bool validate(const Param* paramp)
- {
- U32 num_valid = ((super_t*)paramp)->numValidElements();
- return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
- }
- };
-
- class Deprecated : public Param
- {
- public:
- explicit Deprecated(const char* name)
- : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr)
- {
- BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor();
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- NULL,
- &deserializeParam,
- NULL,
- NULL,
- NULL,
- 0, S32_MAX));
- BaseBlock::addParam(block_descriptor, param_descriptor, name);
- }
- }
-
- static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- if (name_stack_range.first == name_stack_range.second)
- {
- //std::string message = llformat("Deprecated value %s ignored", getName().c_str());
- //parser.parserWarning(message);
- return true;
- }
-
- return false;
- }
- };
-
- // different semantics for documentation purposes, but functionally identical
- typedef Deprecated Ignored;
-
- protected:
- static BlockDescriptor& selfBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block>
- void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,
- typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value)
- {
- if (!param.isProvided())
- {
- param.set(value, false);
- }
- }
-
- };
-
- template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
- class BatchBlock
- : public Block<DERIVED_BLOCK, BASE_BLOCK>
- {
- public:
- typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
- typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t;
-
- BatchBlock()
- {}
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
- {
- if (new_name)
- {
- // reset block
- *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
- }
- return super_t::deserializeBlock(p, name_stack_range, new_name);
- }
-
- bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
- {
- if (overwrite)
- {
- *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue();
- // merge individual parameters into destination
- return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite);
- }
- return false;
- }
- protected:
- static const DERIVED_BLOCK& defaultBatchValue()
- {
- static DERIVED_BLOCK default_value;
- return default_value;
- }
- };
-
- // FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class
- // and not the derived class with the actual params
- template<typename DERIVED_BLOCK,
- typename BASE_BLOCK,
- typename NAME_VALUE_LOOKUP>
- class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>,
- NAME_VALUE_LOOKUP,
- true>
- : public NAME_VALUE_LOOKUP,
- protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK>
- {
- public:
- typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t;
- typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& value_assignment_t;
- typedef block_t value_t;
-
- ParamValue()
- : block_t(),
- mValidated(false)
- {}
-
- ParamValue(value_assignment_t other)
- : block_t(other),
- mValidated(false)
- {
- }
-
- void setValue(value_assignment_t val)
- {
- *this = val;
- }
-
- value_assignment_t getValue() const
- {
- return *this;
- }
-
- BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue()
- {
- return *this;
- }
-
- operator value_assignment_t() const
- {
- return *this;
- }
-
- value_assignment_t operator()() const
- {
- return *this;
- }
-
- protected:
- mutable bool mValidated; // lazy validation flag
- };
-
- template<typename T, bool IS_BLOCK>
- class ParamValue <BaseBlock::Lazy<T>,
- TypeValues<T>,
- IS_BLOCK>
- : public IsBlock<T>::base_class_t
- {
- public:
- typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t;
- typedef const T& value_assignment_t;
- typedef T value_t;
-
- ParamValue()
- : mValue(),
- mValidated(false)
- {}
-
- ParamValue(value_assignment_t other)
- : mValue(other),
- mValidated(false)
- {}
-
- void setValue(value_assignment_t val)
- {
- mValue.set(val);
- }
-
- value_assignment_t getValue() const
- {
- return mValue.get();
- }
-
- T& getValue()
- {
- return mValue.get();
- }
-
- operator value_assignment_t() const
- {
- return mValue.get();
- }
-
- value_assignment_t operator()() const
- {
- return mValue.get();
- }
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)
- {
- return mValue.get().deserializeBlock(p, name_stack_range, new_name);
- }
-
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
- {
- if (mValue.empty()) return;
-
- mValue.get().serializeBlock(p, name_stack, diff_block);
- }
-
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- if (mValue.empty()) return false;
-
- return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
- }
-
- protected:
- mutable bool mValidated; // lazy validation flag
-
- private:
- BaseBlock::Lazy<T> mValue;
- };
-
- template <>
- class ParamValue <LLSD,
- TypeValues<LLSD>,
- false>
- : public TypeValues<LLSD>,
- public BaseBlock
- {
- public:
- typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t;
- typedef const LLSD& value_assignment_t;
-
- ParamValue()
- : mValidated(false)
- {}
-
- ParamValue(value_assignment_t other)
- : mValue(other),
- mValidated(false)
- {}
-
- void setValue(value_assignment_t val) { mValue = val; }
-
- value_assignment_t getValue() const { return mValue; }
- LLSD& getValue() { return mValue; }
-
- operator value_assignment_t() const { return mValue; }
- value_assignment_t operator()() const { return mValue; }
-
-
- // block param interface
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- //TODO: implement LLSD params as schema type Any
- return true;
- }
-
- protected:
- mutable bool mValidated; // lazy validation flag
-
- private:
- static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
-
- LLSD mValue;
- };
-
- template<typename T>
- class CustomParamValue
- : public Block<ParamValue<T, TypeValues<T> > >,
- public TypeValues<T>
- {
- public:
- typedef enum e_value_age
- {
- VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters
- VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
- BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative
- } EValueAge;
-
- typedef ParamValue<T, TypeValues<T> > derived_t;
- typedef CustomParamValue<T> self_t;
- typedef Block<derived_t> block_t;
- typedef const T& value_assignment_t;
- typedef T value_t;
-
-
- CustomParamValue(const T& value = T())
- : mValue(value),
- mValueAge(VALUE_AUTHORITATIVE),
- mValidated(false)
- {}
-
- bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
- {
- derived_t& typed_param = static_cast<derived_t&>(*this);
- // try to parse direct value T
- if (name_stack_range.first == name_stack_range.second)
- {
- if(parser.readValue(typed_param.mValue))
- {
- typed_param.mValueAge = VALUE_AUTHORITATIVE;
- typed_param.updateBlockFromValue(false);
-
- typed_param.clearValueName();
-
- return true;
- }
- }
-
- // fall back on parsing block components for T
- return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
- }
-
- void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
- {
- const derived_t& typed_param = static_cast<const derived_t&>(*this);
- const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
-
- std::string key = typed_param.getValueName();
-
- // first try to write out name of name/value pair
- if (!key.empty())
- {
- if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
- {
- parser.writeValue(key, name_stack);
- }
- }
- // then try to serialize value directly
- else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
- {
-
- if (!parser.writeValue(typed_param.getValue(), name_stack))
- {
- //RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
- // since these tend to be viewed as the constructor arguments for the value T. It seems
- // cleaner to treat the uniqueness of a BlockValue according to the generated value, and
- // not the individual components. This way <color red="0" green="1" blue="0"/> will not
- // be exported as <color green="1"/>, since it was probably the intent of the user to
- // be specific about the RGB color values. This also fixes an issue where we distinguish
- // between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
-
- if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
- {
- // if the value is authoritative but the parser doesn't accept the value type
- // go ahead and make a copy, and splat the value out to its component params
- // and serialize those params
- derived_t copy(typed_param);
- copy.updateBlockFromValue(true);
- copy.block_t::serializeBlock(parser, name_stack, NULL);
- }
- else
- {
- block_t::serializeBlock(parser, name_stack, NULL);
- }
- }
- }
- }
-
- bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- // first, inspect with actual type...
- parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
- if (TypeValues<T>::getPossibleValues())
- {
- //...then inspect with possible string values...
- parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());
- }
- // then recursively inspect contents...
- return block_t::inspectBlock(parser, name_stack, min_count, max_count);
- }
-
- bool validateBlock(bool emit_errors = true) const
- {
- if (mValueAge == VALUE_NEEDS_UPDATE)
- {
- if (block_t::validateBlock(emit_errors))
- {
- // clear stale keyword associated with old value
- TypeValues<T>::clearValueName();
- mValueAge = BLOCK_AUTHORITATIVE;
- static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
- return true;
- }
- else
- {
- //block value incomplete, so not considered provided
- // will attempt to revalidate on next call to isProvided()
- return false;
- }
- }
- else
- {
- // we have a valid value in hand
- return true;
- }
- }
-
- // propagate change status up to enclosing block
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- BaseBlock::paramChanged(changed_param, user_provided);
- if (user_provided)
- {
- // a parameter changed, so our value is out of date
- mValueAge = VALUE_NEEDS_UPDATE;
- }
- }
-
- void setValue(value_assignment_t val)
- {
- derived_t& typed_param = static_cast<derived_t&>(*this);
- // set param version number to be up to date, so we ignore block contents
- mValueAge = VALUE_AUTHORITATIVE;
- mValue = val;
- typed_param.clearValueName();
- static_cast<derived_t*>(this)->updateBlockFromValue(false);
- }
-
- value_assignment_t getValue() const
- {
- validateBlock(true);
- return mValue;
- }
-
- T& getValue()
- {
- validateBlock(true);
- return mValue;
- }
-
- operator value_assignment_t() const
- {
- return getValue();
- }
-
- value_assignment_t operator()() const
- {
- return getValue();
- }
-
- protected:
-
- // use this from within updateValueFromBlock() to set the value without making it authoritative
- void updateValue(value_assignment_t value)
- {
- mValue = value;
- }
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- bool source_override = source_provided && (overwrite || !dst_provided);
-
- const derived_t& src_typed_param = static_cast<const derived_t&>(source);
-
- if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
- {
- // copy value over
- setValue(src_typed_param.getValue());
- return true;
- }
- // merge individual parameters into destination
- if (mValueAge == VALUE_AUTHORITATIVE)
- {
- static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
- }
- return mergeBlock(block_data, source, overwrite);
- }
-
- bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- return block_t::mergeBlock(block_data, source, overwrite);
- }
-
- mutable bool mValidated; // lazy validation flag
-
- private:
- mutable T mValue;
- mutable EValueAge mValueAge;
- };
-}
-
-
-#endif // LL_LLPARAM_H