diff options
Diffstat (limited to 'indra/llxuixml')
| -rw-r--r-- | indra/llxuixml/llinitparam.cpp | 82 | ||||
| -rw-r--r-- | indra/llxuixml/llinitparam.h | 1633 | ||||
| -rw-r--r-- | indra/llxuixml/llxuiparser.cpp | 285 | ||||
| -rw-r--r-- | indra/llxuixml/llxuiparser.h | 2 |
4 files changed, 1396 insertions, 606 deletions
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 482064ed7b..3c0d0aaa7e 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam { const U8* my_addr = reinterpret_cast<const U8*>(this); const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr)); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } // @@ -112,22 +114,41 @@ namespace LLInitParam std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); } + void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) + { + // create a copy of the param descriptor in mAllParams + // so other data structures can store a pointer to it + mAllParams.push_back(in_param); + ParamDescriptorPtr param(mAllParams.back()); + + std::string name(char_name); + if ((size_t)param->mParamHandle > mMaxParamOffset) + { + llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; + } + + if (name.empty()) + { + mUnnamedParams.push_back(param); + } + else + { + // don't use insert, since we want to overwrite existing entries + mNamedParams[name] = param; + } + + if (param->mValidationFunc) + { + mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); + } + } + BlockDescriptor::BlockDescriptor() : mMaxParamOffset(0), mInitializationState(UNINITIALIZED), mCurrentBlockPtr(NULL) {} - // - // BaseBlock - // - BaseBlock::BaseBlock() - : mChangeVersion(0) - {} - - BaseBlock::~BaseBlock() - {} - // called by each derived class in least to most derived order void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) { @@ -368,36 +389,6 @@ namespace LLInitParam return false; } - //static - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) - { - // create a copy of the param descriptor in mAllParams - // so other data structures can store a pointer to it - block_data.mAllParams.push_back(in_param); - ParamDescriptorPtr param(block_data.mAllParams.back()); - - std::string name(char_name); - if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) - { - llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; - } - - if (name.empty()) - { - block_data.mUnnamedParams.push_back(param); - } - else - { - // don't use insert, since we want to overwrite existing entries - block_data.mNamedParams[name] = param; - } - - if (param->mValidationFunc) - { - block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); - } - } - void BaseBlock::addSynonym(Param& param, const std::string& synonym) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -427,14 +418,6 @@ namespace LLInitParam } } - void BaseBlock::paramChanged(const Param& changed_param, bool user_provided) - { - if (user_provided) - { - mChangeVersion++; - } - } - const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const { param_handle_t handle = getHandleFromParam(paramp); @@ -478,6 +461,7 @@ namespace LLInitParam if (merge_func) { Param* paramp = getParamFromHandle((*it)->mParamHandle); + llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle); some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 183472450d..ce59401e87 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -36,6 +36,71 @@ #include "llerror.h" +namespace LLTypeTags +{ + template <typename INNER_TYPE, int _SORT_ORDER> + struct TypeTagBase + { + typedef void is_tag_t; + typedef INNER_TYPE inner_t; + static const int SORT_ORDER=_SORT_ORDER; + }; + + template <int VAL1, int VAL2> + struct GreaterThan + { + static const bool value = VAL1 > VAL2; + }; + + template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > + struct Swap + { + typedef typename ITEM::template Cons<REST>::value_t value_t; + }; + + template<typename ITEM, typename REST> + struct Swap<ITEM, REST, true> + { + typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; + }; + + template<typename T, typename SORTABLE = void> + struct IsSortable + { + static const bool value = false; + }; + + template<typename T> + struct IsSortable<T, typename T::is_tag_t> + { + static const bool value = true; + }; + + template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> + struct InsertInto + { + typedef typename ITEM::template Cons<REST>::value_t value_t; + }; + + template<typename ITEM, typename REST> + struct InsertInto <ITEM, REST, true> + { + typedef typename Swap<ITEM, REST>::value_t value_t; + }; + + template<typename T, bool SORTABLE = IsSortable<T>::value> + struct Sorted + { + typedef T value_t; + }; + + template<typename T> + struct Sorted <T, true> + { + typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t; + }; +} + namespace LLInitParam { // used to indicate no matching value to a given name when parsing @@ -43,6 +108,8 @@ namespace LLInitParam template<typename T> const T& defaultValue() { static T value; return value; } + // wraps comparison operator between any 2 values of the same type + // specialize to handle cases where equality isn't defined well, or at all template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value > struct ParamCompare { @@ -51,7 +118,7 @@ namespace LLInitParam return a == b; } }; - + // boost function types are not comparable template<typename T> struct ParamCompare<T, true> @@ -74,23 +141,126 @@ namespace LLInitParam static bool equals(const Flag& a, const Flag& b) { return false; } }; + // helper functions and classes typedef ptrdiff_t param_handle_t; + struct IS_A_BLOCK {}; + struct NOT_BLOCK {}; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template<typename T, typename BLOCK_IDENTIFIER = void> + struct IsBlock + { + typedef NOT_BLOCK value_t; + }; + + template<typename T> + struct IsBlock<T, typename T::baseblock_base_class_t> + { + typedef IS_A_BLOCK value_t; + }; + + // ParamValue class directly manages the wrapped value + // by holding on to a copy (scalar params) + // or deriving from it (blocks) + // has specializations for custom value behavior + // and "tag" values like Lazy and Atomic + template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> + class ParamValue + { + typedef ParamValue<T, VALUE_IS_BLOCK> self_t; + + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue(): mValue() {} + ParamValue(const default_value_t& other) : mValue(other) {} + + void setValue(const value_t& val) + { + mValue = val; + } + + const value_t& getValue() const + { + return mValue; + } + + T& getValue() + { + return mValue; + } + + protected: + T mValue; + }; + + template<typename T> + class ParamValue<T, IS_A_BLOCK> + : public T + { + typedef ParamValue<T, IS_A_BLOCK> self_t; + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : T(other), + mValidated(false) + {} + + void setValue(const value_t& val) + { + *this = val; + } + + const value_t& getValue() const + { + return *this; + } + + T& getValue() + { + return *this; + } + + protected: + mutable bool mValidated; // lazy validation flag + }; + // empty default implementation of key cache // leverages empty base class optimization template <typename T> class TypeValues + : public ParamValue<typename LLTypeTags::Sorted<T>::value_t> { + private: + struct Inaccessable{}; public: typedef std::map<std::string, T> value_name_map_t; + typedef Inaccessable name_t; + typedef TypeValues<T> type_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; + + TypeValues(const typename param_value_t::value_t& val) + : param_value_t(val) + {} void setValueName(const std::string& key) {} std::string getValueName() const { return ""; } - std::string calcValueName(const T& value) const { return ""; } + std::string calcValueName(const value_t& value) const { return ""; } void clearValueName() const {} - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { return false; } @@ -105,14 +275,39 @@ namespace LLInitParam return NULL; } + void assignNamedValue(const Inaccessable& name) + {} + + operator const value_t&() const + { + return param_value_t::getValue(); + } + + const value_t& operator()() const + { + return param_value_t::getValue(); + } + static value_name_map_t* getValueNames() {return NULL;} }; - template <typename T, typename DERIVED_TYPE = TypeValues<T> > + // helper class to implement name value lookups + // and caching of last used name + template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true > class TypeValuesHelper + : public ParamValue<typename LLTypeTags::Sorted<T>::value_t> { + typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t; public: typedef typename std::map<std::string, T> value_name_map_t; + typedef std::string name_t; + typedef self_t type_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; + + TypeValuesHelper(const typename param_value_t::value_t& val) + : param_value_t(val) + {} //TODO: cache key by index to save on param block size void setValueName(const std::string& value_name) @@ -125,7 +320,7 @@ namespace LLInitParam return mValueName; } - std::string calcValueName(const T& value) const + std::string calcValueName(const value_t& value) const { value_name_map_t* map = getValueNames(); for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -146,7 +341,7 @@ namespace LLInitParam mValueName.clear(); } - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { value_name_map_t* map = getValueNames(); typename value_name_map_t::iterator found_it = map->find(name); @@ -188,18 +383,90 @@ namespace LLInitParam return &sValues; } - static void declare(const std::string& name, const T& value) + static void declare(const std::string& name, const value_t& value) { (*getValueNames())[name] = value; } + void operator ()(const std::string& name) + { + *this = name; + } + + void assignNamedValue(const std::string& name) + { + if (getValueFromName(name, param_value_t::getValue())) + { + setValueName(name); + } + } + + operator const value_t&() const + { + return param_value_t::getValue(); + } + + const value_t& operator()() const + { + return param_value_t::getValue(); + } + protected: - static void getName(const std::string& name, const T& value) + static void getName(const std::string& name, const value_t& value) {} mutable std::string mValueName; }; + // string types can support custom named values, but need + // to disambiguate in code between a string that is a named value + // and a string that is a name + template <typename DERIVED_TYPE> + class TypeValuesHelper<std::string, DERIVED_TYPE, true> + : public TypeValuesHelper<std::string, DERIVED_TYPE, false> + { + public: + typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; + typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t; + typedef std::string value_t; + typedef std::string name_t; + typedef self_t type_value_t; + + TypeValuesHelper(const std::string& val) + : TypeValuesHelper(val) + {} + + void operator ()(const std::string& name) + { + *this = name; + } + + self_t& operator =(const std::string& name) + { + if (base_t::getValueFromName(name, ParamValue<std::string>::getValue())) + { + base_t::setValueName(name); + } + else + { + ParamValue<std::string>::setValue(name); + } + return *this; + } + + operator const value_t&() const + { + return ParamValue<std::string>::getValue(); + } + + const value_t& operator()() const + { + return ParamValue<std::string>::getValue(); + } + + }; + + // parser base class with mechanisms for registering readers/writers/inspectors of different types class Parser { LOG_CLASS(Parser); @@ -293,36 +560,7 @@ namespace LLInitParam parser_inspect_func_map_t* mParserInspectFuncs; }; - class BaseBlock; - - class Param - { - public: - // public to allow choice blocks to clear provided flag on stale choices - void setProvided(bool is_provided) { mIsProvided = is_provided; } - - 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; - - }; + class Param; // various callbacks and constraints associated with an individual param struct ParamDescriptor @@ -378,6 +616,7 @@ namespace LLInitParam } EInitializationState; void aggregateBlockData(BlockDescriptor& src_block_data); + void addParam(ParamDescriptorPtr param, const char* name); typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t; typedef std::vector<ParamDescriptorPtr> param_list_t; @@ -390,12 +629,149 @@ namespace LLInitParam all_params_list_t mAllParams; // all parameters, owns descriptors size_t mMaxParamOffset; EInitializationState mInitializationState; // whether or not static block data has been initialized - BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed + class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; + //TODO: implement in terms of owned_ptr + template<typename T> + class LazyValue + { + public: + LazyValue() + : mPtr(NULL) + {} + + ~LazyValue() + { + delete mPtr; + } + + LazyValue(const T& value) + { + mPtr = new T(value); + } + + LazyValue(const LazyValue& other) + : mPtr(NULL) + { + *this = other; + } + + LazyValue& operator = (const LazyValue& other) + { + if (!other.mPtr) + { + delete mPtr; + mPtr = NULL; + } + else + { + if (!mPtr) + { + mPtr = new T(*other.mPtr); + } + else + { + *mPtr = *(other.mPtr); + } + } + return *this; + } + + bool operator==(const LazyValue& other) const + { + if (empty() || other.empty()) return false; + return *mPtr == *other.mPtr; + } + + bool empty() const + { + return mPtr == NULL; + } + + void set(const T& other) + { + if (!mPtr) + { + mPtr = new T(other); + } + else + { + *mPtr = other; + } + } + + const T& get() const + { + return *ensureInstance(); + } + + T& get() + { + return *ensureInstance(); + } + + operator const T&() const + { + return get(); + } + + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == NULL) + { + mPtr = new T(); + } + return mPtr; + } + + private: + + mutable T* mPtr; + }; + + // root class of all parameter blocks + class BaseBlock { public: + // lift block tags into baseblock namespace so derived classes do not need to qualify them + typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; + typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + + template<typename T> + struct Sequential : public LLTypeTags::TypeTagBase<T, 2> + { + template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; }; + template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; }; + }; + + template<typename T> + struct Atomic : public LLTypeTags::TypeTagBase<T, 1> + { + template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; + template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; }; + }; + + template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > + struct Lazy : public LLTypeTags::TypeTagBase<T, 0> + { + template <typename S> struct Cons + { + typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; + }; + template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> > + { + typedef Lazy<S, IS_A_BLOCK> value_t; + }; + template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> > + { + typedef Lazy<S, BLOCK_T> value_t; + }; + }; + // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount { @@ -436,8 +812,7 @@ namespace LLInitParam LOG_CLASS(BaseBlock); friend class Param; - BaseBlock(); - virtual ~BaseBlock(); + virtual ~BaseBlock() {} bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); param_handle_t getHandleFromParam(const Param* param) const; @@ -460,16 +835,14 @@ namespace LLInitParam 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); - - S32 getLastChangeVersion() const { return mChangeVersion; } + 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(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } // take all provided params from other and apply to self bool overwriteFrom(const BaseBlock& other) @@ -483,181 +856,115 @@ namespace LLInitParam 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); - // can be updated in getters - mutable S32 mChangeVersion; - - static BlockDescriptor& selfBlockDescriptor() + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } - private: - const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; - }; - - // 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; - }; - - template<typename T> - struct IsBlock<T, typename T::baseblock_base_class_t> - { - static const bool value = true; - }; - - 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; - - ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} - - void setValue(value_assignment_t val) - { - mValue = val; - } - - value_assignment_t getValue() const - { - return mValue; - } + protected: + void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); - T& getValue() - { - return mValue; - } - operator value_assignment_t() const - { - return mValue; - } - - value_assignment_t operator()() const + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) { - return mValue; + return mergeBlock(block_data, source, overwrite); } - private: - T mValue; + const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; - template<typename T, typename NAME_VALUE_LOOKUP> - class ParamValue<T, NAME_VALUE_LOOKUP, true> - : public T, - public NAME_VALUE_LOOKUP + class Param { public: - typedef const T& value_assignment_t; - - ParamValue() - : T(), - mKeyVersion(0), - mValidatedVersion(-1), - mValidated(false) - {} - - ParamValue(value_assignment_t other) - : T(other), - mKeyVersion(0), - mValidatedVersion(-1), - mValidated(false) - {} - - void setValue(value_assignment_t val) + void setProvided(bool is_provided = true) { - *this = val; + mIsProvided = is_provided; + enclosingBlock().paramChanged(*this, is_provided); } - value_assignment_t getValue() const + Param& operator =(const Param& other) { + mIsProvided = other.mIsProvided; + // don't change mEnclosingblockoffset return *this; } + protected: - T& getValue() - { - return *this; - } + bool anyProvided() const { return mIsProvided; } - operator value_assignment_t() const - { - return *this; + 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)getEnclosingBlockOffset())); } - - value_assignment_t operator()() const + + U32 getEnclosingBlockOffset() const { - return *this; + return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow; } - S32 mKeyVersion; + private: + friend class BaseBlock; + + //24 bits for member offset field and 1 bit for provided flag + U16 mEnclosingBlockOffsetLow; + U8 mEnclosingBlockOffsetHigh:7; + U8 mIsProvided:1; - protected: - mutable S32 mValidatedVersion; - mutable bool mValidated; // lazy validation flag }; 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; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator const_iterator; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator iterator; }; - // specialize for custom parsing/decomposition of specific classes - // e.g. TypedParam<LLRect> has left, top, right, bottom, etc... + // wrapper for parameter with a known type + // specialized to handle 4 cases: + // simple "scalar" value + // parameter that is itself a block + // multiple scalar values, stored in a vector + // multiple blocks, stored in a vector 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> + typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t> class TypedParam : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public NAME_VALUE_LOOKUP::type_value_t { + protected: + typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::default_value_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - typedef const T& value_assignment_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef typename param_value_t::value_t value_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) + using named_value_t::operator(); + + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr), + named_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); + init(block_descriptor, validate_func, min_count, max_count, name); } - - setValue(value); } bool isProvided() const { return Param::anyProvided(); } @@ -671,24 +978,23 @@ namespace LLInitParam if (parser.readValue(typed_param.getValue())) { typed_param.clearValueName(); - typed_param.setProvided(true); - typed_param.enclosingBlock().paramChanged(param, true); + typed_param.setProvided(); return true; } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(named_value_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())) + + if (named_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); - typed_param.setProvided(true); - typed_param.enclosingBlock().paramChanged(param, true); + typed_param.setProvided(); return true; } @@ -725,7 +1031,9 @@ namespace LLInitParam 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)) + if (calculated_key.size() + && (!diff_param + || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))) { parser.writeValue(calculated_key, name_stack); } @@ -738,22 +1046,34 @@ namespace LLInitParam // 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()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const value_t& val, bool flag_as_provided = true) { + named_value_t::clearValueName(); setValue(val); - param_value_t::clearValueName(); setProvided(flag_as_provided); - Param::enclosingBlock().paramChanged(*this, flag_as_provided); + } + + self_t& operator =(const typename named_value_t::name_t& name) + { + named_value_t::assignNamedValue(name); + return *this; } 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); @@ -767,37 +1087,43 @@ namespace LLInitParam } return false; } + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // parameter that is a block template <typename T, typename NAME_VALUE_LOOKUP> - class TypedParam<T, NAME_VALUE_LOOKUP, false, true> + class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public NAME_VALUE_LOOKUP::type_value_t { + protected: + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::default_value_t default_value_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - typedef const T value_const_t; - typedef T value_t; - typedef value_const_t& value_assignment_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + using named_value_t::operator(); + typedef typename param_value_t::value_t value_t; + + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - param_value_t(value) + named_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); + init(block_descriptor, validate_func, min_count, max_count, name); } } @@ -808,24 +1134,21 @@ namespace LLInitParam if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) { typed_param.clearValueName(); - typed_param.enclosingBlock().paramChanged(param, true); - typed_param.setProvided(true); + typed_param.setProvided(); return true; } - if(name_value_lookup_t::valueNamesExist()) + if(named_value_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())) + if (named_value_t::getValueFromName(name, typed_param.getValue())) { - typed_param.enclosingBlock().paramChanged(param, true); typed_param.setValueName(name); - typed_param.setProvided(true); - typed_param.mKeyVersion = typed_param.getLastChangeVersion(); + typed_param.setProvided(); return true; } @@ -845,11 +1168,11 @@ namespace LLInitParam } std::string key = typed_param.getValueName(); - if (!key.empty() && typed_param.mKeyVersion == typed_param.getLastChangeVersion()) + if (!key.empty()) { - if (!parser.writeValue(key, name_stack)) + if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) { - return; + parser.writeValue(key, name_stack); } } else @@ -860,8 +1183,16 @@ namespace LLInitParam 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); + + // tell parser about our actual type + parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); + } + typed_param.inspectBlock(parser, name_stack, min_count, max_count); } @@ -870,42 +1201,59 @@ namespace LLInitParam bool isProvided() const { // only validate block when it hasn't already passed validation with current data - if (Param::anyProvided() && param_value_t::mValidatedVersion < param_value_t::getLastChangeVersion()) + 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); - param_value_t::mValidatedVersion = param_value_t::getLastChangeVersion(); } 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) + void set(const value_t& val, bool flag_as_provided = true) { setValue(val); - param_value_t::clearValueName(); - // force revalidation of block by clearing known provided version + named_value_t::clearValueName(); + // force revalidation of block // next call to isProvided() will update provision status based on validity - param_value_t::mValidatedVersion = -1; + param_value_t::mValidated = false; setProvided(flag_as_provided); - Param::enclosingBlock().paramChanged(*this, flag_as_provided); + } + + self_t& operator =(const typename named_value_t::name_t& name) + { + named_value_t::assignNamedValue(name); + return *this; } // 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); - Param::enclosingBlock().paramChanged(*this, user_provided); + if (user_provided) { // a child param has been explicitly changed // so *some* aspect of this block is now provided - setProvided(true); + param_value_t::mValidated = false; + setProvided(); + named_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); @@ -913,48 +1261,55 @@ namespace LLInitParam 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)) + if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite)) { dst_typed_param.clearValueName(); dst_typed_param.setProvided(true); - dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); return true; } } return false; } + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // container of non-block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> + class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> : public Param { + protected: + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; + typedef container_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + 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 VALUE_TYPE value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef typename param_value_t::value_t value_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_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); + init(block_descriptor, validate_func, min_count, max_count, name); + } } @@ -975,14 +1330,14 @@ namespace LLInitParam } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(named_value_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)) + if (named_value_t::getValueFromName(name, value)) { typed_param.add(value); typed_param.mValues.back().setValueName(name); @@ -1004,7 +1359,7 @@ namespace LLInitParam it != end_it; ++it) { - std::string key = it->getValue(); + std::string key = it->getValueName(); name_stack.back().second = true; if(key.empty()) @@ -1013,7 +1368,7 @@ namespace LLInitParam bool value_written = parser.writeValue(*it, name_stack); if (!value_written) { - std::string calculated_key = it->calcValueName(key); + std::string calculated_key = it->calcValueName(it->getValue()); if (!parser.writeValue(calculated_key, name_stack)) { break; @@ -1033,38 +1388,50 @@ namespace LLInitParam 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()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); - Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - value_t& add() + param_value_t& add() { - mValues.push_back(param_value_t(value_t())); - setProvided(true); - Param::enclosingBlock().paramChanged(*this, true); + mValues.push_back(value_t()); + Param::setProvided(); return mValues.back(); } - void add(const value_t& item) + self_t& add(const value_t& item) + { + mValues.push_back(item); + setProvided(); + return *this; + } + + self_t& add(const typename named_value_t::name_t& name) { - mValues.push_back(param_value_t(item)); - setProvided(true); - Param::enclosingBlock().paramChanged(*this, true); + value_t value; + + // try to parse a per type named value + if (named_value_t::getValueFromName(name, value)) + { + add(value); + mValues.back().setValueName(name); + } + + return *this; } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_t& operator()() const { return mValues; } typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; @@ -1099,44 +1466,52 @@ namespace LLInitParam if (src_typed_param.begin() != src_typed_param.end()) { - dst_typed_param.setProvided(true); - dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); + dst_typed_param.setProvided(); } return true; } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // container of block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> + class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> : public Param { + protected: + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + typedef container_t default_value_t; + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; 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 VALUE_TYPE 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) + typedef typename param_value_t::value_t value_t; + + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_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); + init(block_descriptor, validate_func, min_count, max_count, name); } } @@ -1158,23 +1533,20 @@ namespace LLInitParam // attempt to parse block... if(value.deserializeBlock(parser, name_stack_range, new_name)) { - typed_param.enclosingBlock().paramChanged(param, true); - typed_param.setProvided(true); + typed_param.setProvided(); return true; } - else if(name_value_lookup_t::valueNamesExist()) + else if(named_value_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())) + if (named_value_t::getValueFromName(name, value.getValue())) { typed_param.mValues.back().setValueName(name); - typed_param.mValues.back().mKeyVersion = value.getLastChangeVersion(); - typed_param.enclosingBlock().paramChanged(param, true); - typed_param.setProvided(true); + typed_param.setProvided(); return true; } @@ -1201,7 +1573,7 @@ namespace LLInitParam name_stack.back().second = true; std::string key = it->getValueName(); - if (!key.empty() && it->mKeyVersion == it->getLastChangeVersion()) + if (!key.empty()) { parser.writeValue(key, name_stack); } @@ -1216,39 +1588,57 @@ namespace LLInitParam 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); + const param_value_t& value_param = param_value_t(value_t()); + + // tell parser about our actual type + parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } - void set(value_assignment_t val, bool flag_as_provided = true) + value_param.inspectBlock(parser, name_stack, min_count, max_count); + } + + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); - Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - value_t& add() + param_value_t& add() { mValues.push_back(value_t()); - setProvided(true); - Param::enclosingBlock().paramChanged(*this, true); + setProvided(); return mValues.back(); } - void add(const value_t& item) + self_t& add(const value_t& item) { mValues.push_back(item); - setProvided(true); - Param::enclosingBlock().paramChanged(*this, true); + setProvided(); + return *this; + } + + self_t& add(const typename named_value_t::name_t& name) + { + value_t value; + + // try to parse a per type named value + if (named_value_t::getValueFromName(name, value)) + { + add(value); + mValues.back().setValueName(name); + } + return *this; } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_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(); } @@ -1288,34 +1678,48 @@ namespace LLInitParam if (src_typed_param.begin() != src_typed_param.end()) { - dst_typed_param.setProvided(true); - dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); + dst_typed_param.setProvided(); } return true; } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; - template <typename DERIVED_BLOCK> - class ChoiceBlock : public BaseBlock + template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> + class ChoiceBlock : public BASE_BLOCK { - typedef ChoiceBlock<DERIVED_BLOCK> self_t; - typedef ChoiceBlock<DERIVED_BLOCK> enclosing_block_t; + 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 mergeBlock(selfBlockDescriptor(), other, true); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return mergeBlock(selfBlockDescriptor(), other, false); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false); } bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1333,57 +1737,59 @@ namespace LLInitParam bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) { mCurChoice = other.mCurChoice; - return BaseBlock::mergeBlock(selfBlockDescriptor(), other, overwrite); + return base_block_t::mergeBlock(getBlockDescriptor(), 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 = BaseBlock::getHandleFromParam(&changed_param); + 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 = BaseBlock::getParamFromHandle(mCurChoice); + Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice); if (previous_choice) { previous_choice->setProvided(false); } mCurChoice = changed_param_handle; } - BaseBlock::paramChanged(changed_param, user_provided); + base_block_t::paramChanged(changed_param, user_provided); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: ChoiceBlock() : mCurChoice(0) { - BaseBlock::init(selfBlockDescriptor(), BaseBlock::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), 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> > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t > class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false> { + typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; + 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), + explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), 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)) + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); + if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) { if(blockp->mCurChoice == 0) { @@ -1397,27 +1803,27 @@ namespace LLInitParam static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true); } - void chooseAs(value_assignment_t val) + void chooseAs(const value_t& val) { super_t::set(val); } - void operator=(value_assignment_t val) + void operator =(const value_t& val) { super_t::set(val); } - void operator()(typename super_t::value_assignment_t val) + void operator()(const value_t& val) { super_t::set(val); } - operator value_assignment_t() const + operator const value_t&() const { return (*this)(); } - value_assignment_t operator()() const + const value_t& operator()() const { if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this) { @@ -1432,11 +1838,11 @@ namespace LLInitParam } private: - T mOriginalValue; + default_value_t mOriginalValue; }; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; @@ -1447,7 +1853,7 @@ namespace LLInitParam const Param* getCurrentChoice() const { - return BaseBlock::getParamFromHandle(mCurChoice); + return base_block_t::getParamFromHandle(mCurChoice); } }; @@ -1456,6 +1862,8 @@ namespace LLInitParam : public BASE_BLOCK { typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t; + + protected: typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t; public: @@ -1464,80 +1872,86 @@ namespace LLInitParam // 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); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), 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); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: Block() { //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // // Nested classes for declaring parameters // - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_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; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; - explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) + public: + using super_t::operator(); + using super_t::operator =; + + explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") } - Optional& operator=(value_assignment_t val) + Optional& operator =(const value_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(value_assignment_t val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); } - using super_t::operator(); }; - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_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 TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; + + public: + 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) + explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} - Mandatory& operator=(value_assignment_t val) + Mandatory& operator =(const value_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); } - using super_t::operator(); static bool validate(const Param* p) { @@ -1547,28 +1961,29 @@ namespace LLInitParam }; - template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_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 TypedParam<T, NAME_VALUE_LOOKUP, true> 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::value_t value_t; + + public: 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) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} - Multiple& operator=(value_assignment_t val) + Multiple& operator =(const container_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(const container_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1585,9 +2000,9 @@ namespace LLInitParam { public: explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1598,7 +2013,7 @@ namespace LLInitParam NULL, NULL, 0, S32_MAX)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + block_descriptor.addParam(param_descriptor, name); } } @@ -1618,16 +2033,17 @@ namespace LLInitParam // different semantics for documentation purposes, but functionally identical typedef Deprecated Ignored; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } - template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> + protected: + template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename 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) + const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value) { if (!param.isProvided()) { @@ -1637,141 +2053,414 @@ namespace LLInitParam }; - template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> - class BatchBlock - : public Block<DERIVED_BLOCK, BASE_BLOCK> + template<typename T, typename BLOCK_T> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void> + { + typedef IS_A_BLOCK value_t; + }; + + template<typename T, typename BLOCK_T> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void> + { + typedef NOT_BLOCK value_t; + }; + + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> + { + typedef typename IsBlock<T>::value_t value_t; + }; + + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER> { + typedef typename IsBlock<T>::value_t value_t; + }; + + + template<typename T> + struct InnerMostType + { + typedef T value_t; + }; + + template<typename T> + struct InnerMostType<ParamValue<T, NOT_BLOCK> > + { + typedef typename InnerMostType<T>::value_t value_t; + }; + + template<typename T> + struct InnerMostType<ParamValue<T, IS_A_BLOCK> > + { + typedef typename InnerMostType<T>::value_t value_t; + }; + + template<typename T, typename BLOCK_T> + class ParamValue <BaseBlock::Atomic<T>, BLOCK_T> + { + typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; + public: - typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t; - typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t; + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; - BatchBlock() + ParamValue() + : mValue(), + mValidated(false) {} + ParamValue(const default_value_t& value) + : mValue(value), + mValidated(false) + {} + + void setValue(const value_t& val) + { + mValue.setValue(val); + } + + const value_t& getValue() const + { + return mValue.getValue(); + } + + value_t& getValue() + { + return mValue.getValue(); + } + 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(); + resetToDefault(); + } + return mValue.deserializeBlock(p, name_stack_range, new_name); } - return super_t::deserializeBlock(p, name_stack_range, new_name); + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + { + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_block); } - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { if (overwrite) { - *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); - // merge individual parameters into destination - return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); + resetToDefault(); + return mValue.mergeBlock(block_data, source.getValue(), overwrite); } return false; } - protected: - static const DERIVED_BLOCK& defaultBatchValue() + + bool validateBlock(bool emit_errors = true) const + { + return mValue.validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + + + mutable bool mValidated; // lazy validation flag + + private: + void resetToDefault() { - static DERIVED_BLOCK default_value; - return default_value; + static T default_value; + mValue = default_value; } + + T mValue; }; - // 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> + template<typename T> + class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> { + typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t; + public: - typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t; - typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& value_assignment_t; + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; ParamValue() - : block_t(), - mKeyVersion(0), - mValidatedVersion(-1), + : mValue(), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + ParamValue(const default_value_t& value) + : mValue(value), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + void setValue(const value_t& val) + { + mValue.setValue(val); + } + + const value_t& getValue() const + { + return mValue.getValue(); + } + + value_t& getValue() + { + return mValue.getValue(); + } + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + { + if (new_name) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + if (name_stack_range.first == name_stack_range.second + && mCurParam != getBlockDescriptor().mAllParams.end()) + { + // deserialize to mCurParam + ParamDescriptor& pd = *(*mCurParam); + ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; + Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); + + if (deserialize_func + && paramp + && deserialize_func(*paramp, p, name_stack_range, new_name)) + { + ++mCurParam; + return true; + } + else + { + return false; + } + } + else + { + return mValue.deserializeBlock(p, name_stack_range, new_name); + } + } + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + { + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_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 + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return mValue.mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag + + private: + + BlockDescriptor::all_params_list_t::iterator mCurParam; + T mValue; + }; + + template<typename T> + class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> + : public T + { + typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t; + + public: + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(const default_value_t& value) + : T(value.getValue()), + mValidated(false) + {} + + mutable bool mValidated; // lazy validation flag + }; + + template<typename T, typename BLOCK_T> + class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> + { + typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; + + public: + typedef typename InnerMostType<T>::value_t value_t; + typedef LazyValue<T> default_value_t; + + ParamValue() + : mValue(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : mValue(other), mValidated(false) {} - ParamValue(value_assignment_t other) - : block_t(other), - mKeyVersion(0), - mValidatedVersion(-1), + ParamValue(const T& value) + : mValue(value), mValidated(false) + {} + + void setValue(const value_t& val) { + mValue.set(val); } - void setValue(value_assignment_t val) + const value_t& getValue() const { - *this = val; + return mValue.get().getValue(); } - value_assignment_t getValue() const + value_t& getValue() { - return *this; + return mValue.get().getValue(); } - BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue() + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) { - return *this; + return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - operator value_assignment_t() const + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { - return *this; + if (mValue.empty()) return; + + const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) + ? &(diff_block->mValue.get().getValue()) + : NULL; + mValue.get().serializeBlock(p, name_stack, base_block); } - value_assignment_t operator()() 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 { - return *this; + return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } - S32 mKeyVersion; + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.empty() || mValue.get().validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } - protected: - mutable S32 mValidatedVersion; mutable bool mValidated; // lazy validation flag + + private: + LazyValue<T> mValue; + }; + + template<typename T, typename BLOCK_T> + class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> + { + typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; + + public: + typedef typename InnerMostType<T>::value_t value_t; + typedef LazyValue<T> default_value_t; + + ParamValue() + : mValue(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : mValue(other), + mValidated(false) + {} + + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + + void setValue(const value_t& val) + { + mValue.set(val); + } + + const value_t& getValue() const + { + return mValue.get().getValue(); + } + + value_t& getValue() + { + return mValue.get().getValue(); + } + + mutable bool mValidated; // lazy validation flag + + private: + LazyValue<T> mValue; }; template <> - class ParamValue <LLSD, - TypeValues<LLSD>, - false> - : public TypeValues<LLSD>, - public BaseBlock + class ParamValue <LLSD, NOT_BLOCK> + : public BaseBlock { public: - typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t; - typedef const LLSD& value_assignment_t; + typedef LLSD value_t; + typedef LLSD default_value_t; ParamValue() - : mKeyVersion(0), - mValidatedVersion(-1), - mValidated(false) + : mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const default_value_t& other) : mValue(other), - mKeyVersion(0), - mValidatedVersion(-1), mValidated(false) {} - void setValue(value_assignment_t val) { mValue = val; } + void setValue(const value_t& val) { mValue = val; } - value_assignment_t getValue() const { return mValue; } + const value_t& getValue() const { return mValue; } LLSD& getValue() { return mValue; } - operator value_assignment_t() const { return mValue; } - value_assignment_t operator()() const { return mValue; } - - S32 mKeyVersion; - // block param interface bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; @@ -1782,7 +2471,6 @@ namespace LLInitParam } protected: - mutable S32 mValidatedVersion; mutable bool mValidated; // lazy validation flag private: @@ -1793,8 +2481,7 @@ namespace LLInitParam template<typename T> class CustomParamValue - : public Block<ParamValue<T, TypeValues<T> > >, - public TypeValues<T> + : public Block<ParamValue<T> > { public: typedef enum e_value_age @@ -1804,16 +2491,17 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue<T, TypeValues<T> > derived_t; + typedef ParamValue<T> derived_t; typedef CustomParamValue<T> self_t; - typedef Block<derived_t> block_t; - typedef const T& value_assignment_t; + typedef Block<derived_t> block_t; + typedef T default_value_t; + typedef T value_t; + typedef void baseblock_base_class_t; - CustomParamValue(const T& value = T()) + + CustomParamValue(const default_value_t& value = T()) : mValue(value), mValueAge(VALUE_AUTHORITATIVE), - mKeyVersion(0), - mValidatedVersion(-1), mValidated(false) {} @@ -1828,8 +2516,6 @@ namespace LLInitParam typed_param.mValueAge = VALUE_AUTHORITATIVE; typed_param.updateBlockFromValue(false); - typed_param.clearValueName(); - return true; } } @@ -1843,18 +2529,8 @@ namespace LLInitParam 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 (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) { if (!parser.writeValue(typed_param.getValue(), name_stack)) @@ -1884,19 +2560,6 @@ namespace LLInitParam } } - 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) @@ -1904,7 +2567,6 @@ namespace LLInitParam 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; @@ -1934,17 +2596,15 @@ namespace LLInitParam } } - void setValue(value_assignment_t val) + void setValue(const value_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 + const value_t& getValue() const { validateBlock(true); return mValue; @@ -1956,22 +2616,10 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const - { - return getValue(); - } - - value_assignment_t operator()() const - { - return getValue(); - } - - S32 mKeyVersion; - protected: // use this from within updateValueFromBlock() to set the value without making it authoritative - void updateValue(value_assignment_t value) + void updateValue(const value_t& value) { mValue = value; } @@ -2001,7 +2649,6 @@ namespace LLInitParam return block_t::mergeBlock(block_data, source, overwrite); } - mutable S32 mValidatedVersion; mutable bool mValidated; // lazy validation flag private: diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 878f992178..9cd88a1620 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -42,7 +42,7 @@ #include <boost/spirit/include/classic_core.hpp> #include "lluicolor.h" - +#include "v3math.h" using namespace BOOST_SPIRIT_CLASSIC_NS; const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; @@ -59,30 +59,25 @@ const char* NO_VALUE_MARKER = "no_value"; const S32 LINE_NUMBER_HERE = 0; -struct MaxOccur : public LLInitParam::ChoiceBlock<MaxOccur> +struct MaxOccursValues : public LLInitParam::TypeValuesHelper<U32, MaxOccursValues> { - Alternative<int> count; - Alternative<std::string> unbounded; - - MaxOccur() - : unbounded("", "unbounded") - {} + static void declareValues() + { + declare("unbounded", U32_MAX); + } }; struct Occurs : public LLInitParam::Block<Occurs> { - Optional<S32> minOccurs; - Optional<MaxOccur> maxOccurs; + Optional<U32> minOccurs; + Optional<U32, MaxOccursValues> maxOccurs; Occurs() - : minOccurs("minOccurs"), - maxOccurs("maxOccurs") - { - minOccurs = 0; - maxOccurs.unbounded.choose(); - } -}; + : minOccurs("minOccurs", 0), + maxOccurs("maxOccurs", U32_MAX) + {} +}; typedef enum { @@ -103,60 +98,184 @@ namespace LLInitParam }; } -struct Name : public LLInitParam::Block<Name> +struct Element; +struct Group; +struct Sequence; + +struct All : public LLInitParam::Block<All, Occurs> { - Mandatory<std::string> name; + Multiple< Lazy<Element, IS_A_BLOCK> > elements; - Name() - : name("name") - {} + All() + : elements("element") + { + maxOccurs = 1; + } }; struct Attribute : public LLInitParam::Block<Attribute> { - Mandatory<Name> name; - Mandatory<std::string> type; + Mandatory<std::string> name, + type; Mandatory<EUse> use; Attribute() : name("name"), type("type"), use("use") - { - } + {} +}; + +struct Any : public LLInitParam::Block<Any, Occurs> +{ + Optional<std::string> _namespace; + + Any() + : _namespace("namespace") + {} +}; + +struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> +{ + Alternative< Lazy<Element, IS_A_BLOCK> > element; + Alternative< Lazy<Group, IS_A_BLOCK> > group; + Alternative< Lazy<Choice, IS_A_BLOCK> > choice; + Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; + Alternative< Lazy<Any> > any; + + Choice() + : element("element"), + group("group"), + choice("choice"), + sequence("sequence"), + any("any") + {} + +}; + +struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs> +{ + Alternative< Lazy<Element, IS_A_BLOCK> > element; + Alternative< Lazy<Group, IS_A_BLOCK> > group; + Alternative< Lazy<Choice> > choice; + Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; + Alternative< Lazy<Any> > any; +}; + +struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> +{ + Alternative<All> all; + Alternative<Choice> choice; + Alternative<Sequence> sequence; + + GroupContents() + : all("all"), + choice("choice"), + sequence("sequence") + {} +}; + +struct Group : public LLInitParam::Block<Group, GroupContents> +{ + Optional<std::string> name, + ref; + + Group() + : name("name"), + ref("ref") + {} +}; + +struct Restriction : public LLInitParam::Block<Restriction> +{ +}; + +struct Extension : public LLInitParam::Block<Extension> +{ }; -struct ComplexType : public LLInitParam::Block<ComplexType> +struct SimpleContent : public LLInitParam::ChoiceBlock<SimpleContent> { - Multiple<Attribute> attribute; - //Multiple<struct Element> elements; - Optional<bool> mixed; + Alternative<Restriction> restriction; + Alternative<Extension> extension; + + SimpleContent() + : restriction("restriction"), + extension("extension") + {} +}; + +struct SimpleType : public LLInitParam::Block<SimpleType> +{ + // TODO +}; + +struct ComplexContent : public LLInitParam::Block<ComplexContent, SimpleContent> +{ + Optional<bool> mixed; + + ComplexContent() + : mixed("mixed", true) + {} +}; + +struct ComplexTypeContents : public LLInitParam::ChoiceBlock<ComplexTypeContents> +{ + Alternative<SimpleContent> simple_content; + Alternative<ComplexContent> complex_content; + Alternative<Group> group; + Alternative<All> all; + Alternative<Choice> choice; + Alternative<Sequence> sequence; + + ComplexTypeContents() + : simple_content("simpleContent"), + complex_content("complexContent"), + group("group"), + all("all"), + choice("choice"), + sequence("sequence") + {} +}; + +struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents> +{ + Optional<std::string> name; + Optional<bool> mixed; + + Multiple<Attribute> attribute; + Multiple< Lazy<Element, IS_A_BLOCK > > elements; ComplexType() - : attribute("xs:attribute"), - //elements("xs:element"), + : name("name"), + attribute("xs:attribute"), + elements("xs:element"), mixed("mixed") { - mixed = true; } }; -struct Element : public LLInitParam::Block<Element, Occurs> +struct ElementContents : public LLInitParam::ChoiceBlock<ElementContents, Occurs> { - Mandatory<ComplexType> complexType; - Mandatory<Name> name; + Alternative<SimpleType> simpleType; + Alternative<ComplexType> complexType; - Element() - : complexType("xs:complexType") + ElementContents() + : simpleType("simpleType"), + complexType("complexType") {} }; -struct Elements : public LLInitParam::Block<Elements, Occurs> +struct Element : public LLInitParam::Block<Element, ElementContents> { - Multiple<Element> elements; + Optional<std::string> name, + ref, + type; - Elements() - : elements("xs:element") + Element() + : name("xs:name"), + ref("xs:ref"), + type("xs:type") {} }; @@ -164,30 +283,33 @@ struct Schema : public LLInitParam::Block<Schema> { private: Mandatory<std::string> targetNamespace, - xmlns; + xmlns, + xs; public: Optional<std::string> attributeFormDefault, - elementFormDefault, - xs; + elementFormDefault; - Optional<Elements> elements; + Mandatory<Element> root_element; void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;} - Schema() + Schema(const std::string& ns = LLStringUtil::null) : attributeFormDefault("attributeFormDefault"), elementFormDefault("elementFormDefault"), xs("xmlns:xs"), targetNamespace("targetNamespace"), xmlns("xmlns"), - elements("xs:choice") + root_element("xs:element") { attributeFormDefault = "unqualified"; elementFormDefault = "qualified"; xs = "http://www.w3.org/2001/XMLSchema"; + if (!ns.empty()) + { + setNameSpace(ns); + }; } - }; // @@ -214,22 +336,30 @@ LLXSDWriter::LLXSDWriter() void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) { + Schema schema(xml_namespace); + + schema.root_element.name = type_name; + Choice& choice = schema.root_element.complexType.choice; + + choice.minOccurs = 0; + choice.maxOccurs = "unbounded"; + mSchemaNode = node; - node->setName("xs:schema"); - node->createChild("attributeFormDefault", true)->setStringValue("unqualified"); - node->createChild("elementFormDefault", true)->setStringValue("qualified"); - node->createChild("targetNamespace", true)->setStringValue(xml_namespace); - node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema"); - node->createChild("xmlns", true)->setStringValue(xml_namespace); - - node = node->createChild("xs:complexType", false); - node->createChild("name", true)->setStringValue(type_name); - node->createChild("mixed", true)->setStringValue("true"); - - mAttributeNode = node; - mElementNode = node->createChild("xs:choice", false); - mElementNode->createChild("minOccurs", true)->setStringValue("0"); - mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded"); + //node->setName("xs:schema"); + //node->createChild("attributeFormDefault", true)->setStringValue("unqualified"); + //node->createChild("elementFormDefault", true)->setStringValue("qualified"); + //node->createChild("targetNamespace", true)->setStringValue(xml_namespace); + //node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema"); + //node->createChild("xmlns", true)->setStringValue(xml_namespace); + + //node = node->createChild("xs:complexType", false); + //node->createChild("name", true)->setStringValue(type_name); + //node->createChild("mixed", true)->setStringValue("true"); + + //mAttributeNode = node; + //mElementNode = node->createChild("xs:choice", false); + //mElementNode->createChild("minOccurs", true)->setStringValue("0"); + //mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded"); block.inspectBlock(*this); // duplicate element choices @@ -536,6 +666,7 @@ LLXUIParser::LLXUIParser() registerParserFuncs<S32>(readS32Value, writeS32Value); registerParserFuncs<F32>(readF32Value, writeF32Value); registerParserFuncs<F64>(readF64Value, writeF64Value); + registerParserFuncs<LLVector3>(readVector3Value, writeVector3Value); registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value); registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue); registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue); @@ -1010,6 +1141,31 @@ bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_ return false; } +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast<LLXUIParser&>(parser); + LLVector3* vecp = (LLVector3*)val_ptr; + if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast<LLXUIParser&>(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLVector3 vector = *((LLVector3*)val_ptr); + node->setFloatValue(3, vector.mV); + return true; + } + return false; +} + bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) { LLXUIParser& self = static_cast<LLXUIParser&>(parser); @@ -1247,6 +1403,7 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl if( !file.isOpen() ) { LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; + XML_ParserFree( mParser ); return false; } diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index d7cd256967..e48663e5cc 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -127,6 +127,7 @@ private: static bool readS32Value(Parser& parser, void* val_ptr); static bool readF32Value(Parser& parser, void* val_ptr); static bool readF64Value(Parser& parser, void* val_ptr); + static bool readVector3Value(Parser& parser, void* val_ptr); static bool readColor4Value(Parser& parser, void* val_ptr); static bool readUIColorValue(Parser& parser, void* val_ptr); static bool readUUIDValue(Parser& parser, void* val_ptr); @@ -144,6 +145,7 @@ private: static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); |
