diff options
Diffstat (limited to 'indra/llcommon/llinitparam.cpp')
-rw-r--r-- | indra/llcommon/llinitparam.cpp | 870 |
1 files changed, 435 insertions, 435 deletions
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index d15bd2f619..7bba1a540d 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -1,26 +1,26 @@ -/** +/** * @file llinitparam.cpp - * @brief parameter block abstraction for creating complex objects and + * @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$ */ @@ -34,434 +34,434 @@ namespace LLInitParam { - predicate_rule_t default_parse_rules() - { - return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY); - } - - // - // Param - // - Param::Param(BaseBlock* enclosing_block) - : mIsProvided(false) - { - const U8* my_addr = reinterpret_cast<const U8*>(this); - const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); - mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; - mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; - } - - // - // ParamDescriptor - // - ParamDescriptor::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) - : mParamHandle(p), - mMergeFunc(merge_func), - mDeserializeFunc(deserialize_func), - mSerializeFunc(serialize_func), - mValidationFunc(validation_func), - mInspectFunc(inspect_func), - mMinCount(min_count), - mMaxCount(max_count), - mUserData(NULL) - {} - - ParamDescriptor::ParamDescriptor() - : mParamHandle(0), - mMergeFunc(NULL), - mDeserializeFunc(NULL), - mSerializeFunc(NULL), - mValidationFunc(NULL), - mInspectFunc(NULL), - mMinCount(0), - mMaxCount(0), - mUserData(NULL) - {} - - ParamDescriptor::~ParamDescriptor() - { - delete mUserData; - } - - // - // Parser - // - Parser::~Parser() - {} - - void Parser::parserWarning(const std::string& message) - { - if (mParseSilently) return; - LL_WARNS() << message << LL_ENDL; - } - - void Parser::parserError(const std::string& message) - { - if (mParseSilently) return; - LL_ERRS() << message << LL_ENDL; - } - - - // - // BlockDescriptor - // - void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) - { - mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end()); - std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams)); - std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList)); - 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) - { - LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL; - } - - 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) - {} - - // called by each derived class in least to most derived order - void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) - { - descriptor.mCurrentBlockPtr = this; - descriptor.mMaxParamOffset = block_size; - - switch(descriptor.mInitializationState) - { - case BlockDescriptor::UNINITIALIZED: - // copy params from base class here - descriptor.aggregateBlockData(base_descriptor); - - descriptor.mInitializationState = BlockDescriptor::INITIALIZING; - break; - case BlockDescriptor::INITIALIZING: - descriptor.mInitializationState = BlockDescriptor::INITIALIZED; - break; - case BlockDescriptor::INITIALIZED: - // nothing to do - break; - } - } - - param_handle_t BaseBlock::getHandleFromParam(const Param* param) const - { - const U8* param_address = reinterpret_cast<const U8*>(param); - const U8* baseblock_address = reinterpret_cast<const U8*>(this); - return (param_address - baseblock_address); - } - - bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) - { - Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); - if (!deserializeBlock(p, range, true)) - { - if (!silent) - { - p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); - } - return false; - } - return true; - } - - - bool BaseBlock::validateBlock(bool emit_errors) const - { - // only validate block when it hasn't already passed validation with current data - if (!mValidated) - { - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - for (const BlockDescriptor::param_validation_list_t::value_type& pair : block_data.mValidationList) - { - const Param* param = getParamFromHandle(pair.first); - if (!pair.second(param)) - { - if (emit_errors) - { - LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL; - } - return false; - } - } - mValidated = true; - } - return mValidated; - } - - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const - { - bool serialized = false; - if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided()))) - { - return false; - } - // named param is one like LLView::Params::follows - // unnamed param is like LLView::Params::rect - implicit - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - - for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) - { - param_handle_t param_handle = ptr->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::serialize_func_t serialize_func = ptr->mSerializeFunc; - if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) - { - const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); - } - } - - for (const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams) - { - param_handle_t param_handle = pair.second->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::serialize_func_t serialize_func = pair.second->mSerializeFunc; - if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) - { - // Ensure this param has not already been serialized - // Prevents <rect> from being serialized as its own tag. - bool duplicate = false; - for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) - { - if (param_handle == ptr->mParamHandle) - { - duplicate = true; - break; - } - } - - //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers - // don't know how to detect them - if (duplicate) - { - continue; - } - - name_stack.push_back(std::make_pair(pair.first, !duplicate)); - const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); - name_stack.pop_back(); - } - } - - if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) - { - serialized |= parser.writeValue(Flag(), name_stack); - } - // was anything serialized in this block? - return serialized; - } - - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const - { - // named param is one like LLView::Params::follows - // unnamed param is like LLView::Params::rect - implicit - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - - for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) - { - param_handle_t param_handle = ptr->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::inspect_func_t inspect_func = ptr->mInspectFunc; - if (inspect_func) - { - name_stack.push_back(std::make_pair("", true)); - inspect_func(*param, parser, name_stack, ptr->mMinCount, ptr->mMaxCount); - name_stack.pop_back(); - } - } - - for(const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams) - { - param_handle_t param_handle = pair.second->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::inspect_func_t inspect_func = pair.second->mInspectFunc; - if (inspect_func) - { - // Ensure this param has not already been inspected - bool duplicate = false; + predicate_rule_t default_parse_rules() + { + return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY); + } + + // + // Param + // + Param::Param(BaseBlock* enclosing_block) + : mIsProvided(false) + { + const U8* my_addr = reinterpret_cast<const U8*>(this); + const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; + } + + // + // ParamDescriptor + // + ParamDescriptor::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) + : mParamHandle(p), + mMergeFunc(merge_func), + mDeserializeFunc(deserialize_func), + mSerializeFunc(serialize_func), + mValidationFunc(validation_func), + mInspectFunc(inspect_func), + mMinCount(min_count), + mMaxCount(max_count), + mUserData(NULL) + {} + + ParamDescriptor::ParamDescriptor() + : mParamHandle(0), + mMergeFunc(NULL), + mDeserializeFunc(NULL), + mSerializeFunc(NULL), + mValidationFunc(NULL), + mInspectFunc(NULL), + mMinCount(0), + mMaxCount(0), + mUserData(NULL) + {} + + ParamDescriptor::~ParamDescriptor() + { + delete mUserData; + } + + // + // Parser + // + Parser::~Parser() + {} + + void Parser::parserWarning(const std::string& message) + { + if (mParseSilently) return; + LL_WARNS() << message << LL_ENDL; + } + + void Parser::parserError(const std::string& message) + { + if (mParseSilently) return; + LL_ERRS() << message << LL_ENDL; + } + + + // + // BlockDescriptor + // + void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) + { + mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end()); + std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams)); + std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList)); + 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) + { + LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL; + } + + 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) + {} + + // called by each derived class in least to most derived order + void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) + { + descriptor.mCurrentBlockPtr = this; + descriptor.mMaxParamOffset = block_size; + + switch(descriptor.mInitializationState) + { + case BlockDescriptor::UNINITIALIZED: + // copy params from base class here + descriptor.aggregateBlockData(base_descriptor); + + descriptor.mInitializationState = BlockDescriptor::INITIALIZING; + break; + case BlockDescriptor::INITIALIZING: + descriptor.mInitializationState = BlockDescriptor::INITIALIZED; + break; + case BlockDescriptor::INITIALIZED: + // nothing to do + break; + } + } + + param_handle_t BaseBlock::getHandleFromParam(const Param* param) const + { + const U8* param_address = reinterpret_cast<const U8*>(param); + const U8* baseblock_address = reinterpret_cast<const U8*>(this); + return (param_address - baseblock_address); + } + + bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) + { + Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); + if (!deserializeBlock(p, range, true)) + { + if (!silent) + { + p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); + } + return false; + } + return true; + } + + + bool BaseBlock::validateBlock(bool emit_errors) const + { + // only validate block when it hasn't already passed validation with current data + if (!mValidated) + { + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + for (const BlockDescriptor::param_validation_list_t::value_type& pair : block_data.mValidationList) + { + const Param* param = getParamFromHandle(pair.first); + if (!pair.second(param)) + { + if (emit_errors) + { + LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL; + } + return false; + } + } + mValidated = true; + } + return mValidated; + } + + bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const + { + bool serialized = false; + if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided()))) + { + return false; + } + // named param is one like LLView::Params::follows + // unnamed param is like LLView::Params::rect - implicit + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + + for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) + { + param_handle_t param_handle = ptr->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::serialize_func_t serialize_func = ptr->mSerializeFunc; + if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) + { + const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; + serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); + } + } + + for (const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams) + { + param_handle_t param_handle = pair.second->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::serialize_func_t serialize_func = pair.second->mSerializeFunc; + if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) + { + // Ensure this param has not already been serialized + // Prevents <rect> from being serialized as its own tag. + bool duplicate = false; + for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) + { + if (param_handle == ptr->mParamHandle) + { + duplicate = true; + break; + } + } + + //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers + // don't know how to detect them + if (duplicate) + { + continue; + } + + name_stack.push_back(std::make_pair(pair.first, !duplicate)); + const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; + serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); + name_stack.pop_back(); + } + } + + if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) + { + serialized |= parser.writeValue(Flag(), name_stack); + } + // was anything serialized in this block? + return serialized; + } + + bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const + { + // named param is one like LLView::Params::follows + // unnamed param is like LLView::Params::rect - implicit + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + + for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams) + { + param_handle_t param_handle = ptr->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::inspect_func_t inspect_func = ptr->mInspectFunc; + if (inspect_func) + { + name_stack.push_back(std::make_pair("", true)); + inspect_func(*param, parser, name_stack, ptr->mMinCount, ptr->mMaxCount); + name_stack.pop_back(); + } + } + + for(const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams) + { + param_handle_t param_handle = pair.second->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::inspect_func_t inspect_func = pair.second->mInspectFunc; + if (inspect_func) + { + // Ensure this param has not already been inspected + bool duplicate = false; for (const ParamDescriptorPtr &ptr : block_data.mUnnamedParams) - { - if (param_handle == ptr->mParamHandle) - { - duplicate = true; - break; - } - } - - name_stack.push_back(std::make_pair(pair.first, !duplicate)); - inspect_func(*param, parser, name_stack, pair.second->mMinCount, pair.second->mMaxCount); - name_stack.pop_back(); - } - } - - return true; - } - - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored) - { - BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - bool names_left = name_stack_range.first != name_stack_range.second; - - bool new_name = names_left - ? name_stack_range.first->second - : true; - - if (names_left) - { - const std::string& top_name = name_stack_range.first->first; - - BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); - if (found_it != block_data.mNamedParams.end()) - { - // find pointer to member parameter from offset table - Param* paramp = getParamFromHandle(found_it->second->mParamHandle); - ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc; - - Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); - ++new_name_stack.first; - if (deserialize_func(*paramp, p, new_name_stack, new_name)) - { - // value is no longer new, we know about it now - name_stack_range.first->second = false; - return true; - } - else - { - return false; - } - } - } - - // try to parse unnamed parameters, in declaration order - for (ParamDescriptorPtr& ptr : block_data.mUnnamedParams) - { - Param* paramp = getParamFromHandle(ptr->mParamHandle); - ParamDescriptor::deserialize_func_t deserialize_func = ptr->mDeserializeFunc; - - if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name)) - { - return true; - } - } - - // if no match, and no names left on stack, this is just an existence assertion of this block - // verify by calling readValue with NoParamValue type, an inherently unparseable type - if (!names_left) - { - Flag no_value; - return p.readValue(no_value); - } - - return false; - } - - void BaseBlock::addSynonym(Param& param, const std::string& synonym) - { - BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - if (block_data.mInitializationState == BlockDescriptor::INITIALIZING) - { - param_handle_t handle = getHandleFromParam(¶m); - - // check for invalid derivation from a paramblock (i.e. without using - // Block<T, Base_Class> - if ((size_t)handle > block_data.mMaxParamOffset) - { - LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL; - } - - ParamDescriptorPtr param_descriptor = findParamDescriptor(param); - if (param_descriptor) - { - if (synonym.empty()) - { - block_data.mUnnamedParams.push_back(param_descriptor); - } - else - { - block_data.mNamedParams[synonym] = param_descriptor; - } - } - } - } - - const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const - { - param_handle_t handle = getHandleFromParam(paramp); - for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) - { - if (it->second->mParamHandle == handle) - { - return it->first; - } - } - - return LLStringUtil::null; - } - - ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param) - { - param_handle_t handle = getHandleFromParam(¶m); - BlockDescriptor& descriptor = mostDerivedBlockDescriptor(); - for (ParamDescriptorPtr& ptr : descriptor.mAllParams) - { - if (ptr->mParamHandle == handle) return ptr; - } - return ParamDescriptorPtr(); - } - - // take all provided params from other and apply to self - // NOTE: this requires that "other" is of the same derived type as this - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) - { - bool some_param_changed = false; - for (const ParamDescriptorPtr& ptr : block_data.mAllParams) - { - const Param* other_paramp = other.getParamFromHandle(ptr->mParamHandle); - ParamDescriptor::merge_func_t merge_func = ptr->mMergeFunc; - if (merge_func) - { - Param* paramp = getParamFromHandle(ptr->mParamHandle); - llassert(paramp->getEnclosingBlockOffset() == ptr->mParamHandle); - some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); - } - } - return some_param_changed; - } + { + if (param_handle == ptr->mParamHandle) + { + duplicate = true; + break; + } + } + + name_stack.push_back(std::make_pair(pair.first, !duplicate)); + inspect_func(*param, parser, name_stack, pair.second->mMinCount, pair.second->mMaxCount); + name_stack.pop_back(); + } + } + + return true; + } + + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored) + { + BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + bool names_left = name_stack_range.first != name_stack_range.second; + + bool new_name = names_left + ? name_stack_range.first->second + : true; + + if (names_left) + { + const std::string& top_name = name_stack_range.first->first; + + BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); + if (found_it != block_data.mNamedParams.end()) + { + // find pointer to member parameter from offset table + Param* paramp = getParamFromHandle(found_it->second->mParamHandle); + ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc; + + Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); + ++new_name_stack.first; + if (deserialize_func(*paramp, p, new_name_stack, new_name)) + { + // value is no longer new, we know about it now + name_stack_range.first->second = false; + return true; + } + else + { + return false; + } + } + } + + // try to parse unnamed parameters, in declaration order + for (ParamDescriptorPtr& ptr : block_data.mUnnamedParams) + { + Param* paramp = getParamFromHandle(ptr->mParamHandle); + ParamDescriptor::deserialize_func_t deserialize_func = ptr->mDeserializeFunc; + + if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name)) + { + return true; + } + } + + // if no match, and no names left on stack, this is just an existence assertion of this block + // verify by calling readValue with NoParamValue type, an inherently unparseable type + if (!names_left) + { + Flag no_value; + return p.readValue(no_value); + } + + return false; + } + + void BaseBlock::addSynonym(Param& param, const std::string& synonym) + { + BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + if (block_data.mInitializationState == BlockDescriptor::INITIALIZING) + { + param_handle_t handle = getHandleFromParam(¶m); + + // check for invalid derivation from a paramblock (i.e. without using + // Block<T, Base_Class> + if ((size_t)handle > block_data.mMaxParamOffset) + { + LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL; + } + + ParamDescriptorPtr param_descriptor = findParamDescriptor(param); + if (param_descriptor) + { + if (synonym.empty()) + { + block_data.mUnnamedParams.push_back(param_descriptor); + } + else + { + block_data.mNamedParams[synonym] = param_descriptor; + } + } + } + } + + const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const + { + param_handle_t handle = getHandleFromParam(paramp); + for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) + { + if (it->second->mParamHandle == handle) + { + return it->first; + } + } + + return LLStringUtil::null; + } + + ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param) + { + param_handle_t handle = getHandleFromParam(¶m); + BlockDescriptor& descriptor = mostDerivedBlockDescriptor(); + for (ParamDescriptorPtr& ptr : descriptor.mAllParams) + { + if (ptr->mParamHandle == handle) return ptr; + } + return ParamDescriptorPtr(); + } + + // take all provided params from other and apply to self + // NOTE: this requires that "other" is of the same derived type as this + bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + { + bool some_param_changed = false; + for (const ParamDescriptorPtr& ptr : block_data.mAllParams) + { + const Param* other_paramp = other.getParamFromHandle(ptr->mParamHandle); + ParamDescriptor::merge_func_t merge_func = ptr->mMergeFunc; + if (merge_func) + { + Param* paramp = getParamFromHandle(ptr->mParamHandle); + llassert(paramp->getEnclosingBlockOffset() == ptr->mParamHandle); + some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); + } + } + return some_param_changed; + } } |