diff options
author | Richard Linden <none@none> | 2012-10-22 19:54:10 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2012-10-22 19:54:10 -0700 |
commit | d6634fcd2433e18eea1a9bf31da6d7e531817d77 (patch) | |
tree | 0d37227fd7424ef329f3dc3d642805a04b5c22b7 /indra/llcommon | |
parent | 534e0ee0514b482a8b32a72d5afed9a4652c0133 (diff) |
SH-3405 WIP convert existing stats to lltrace system
sanitized param block code to accept isValid and isProvided at any point
added predicates to control serialization
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llcommon/llinitparam.cpp | 35 | ||||
-rw-r--r-- | indra/llcommon/llinitparam.h | 221 | ||||
-rw-r--r-- | indra/llcommon/llpredicate.cpp | 33 | ||||
-rw-r--r-- | indra/llcommon/llpredicate.h | 173 | ||||
-rw-r--r-- | indra/llcommon/llsdparam.cpp | 2 |
6 files changed, 376 insertions, 90 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index c0e9266aa9..d876842cf1 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -77,6 +77,7 @@ set(llcommon_SOURCE_FILES llmutex.cpp lloptioninterface.cpp llptrto.cpp + llpredicate.cpp llprocess.cpp llprocessor.cpp llqueuedthread.cpp @@ -205,6 +206,7 @@ set(llcommon_HEADER_FILES llnametable.h lloptioninterface.h llpointer.h + llpredicate.h llpreprocessor.h llpriqueuemap.h llprocess.h diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index 54e98e66f3..a63e792925 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -164,24 +164,37 @@ namespace LLInitParam bool BaseBlock::validateBlock(bool emit_errors) const { - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it) + // only validate block when it hasn't already passed validation with current data + if (!mValidated) { - const Param* param = getParamFromHandle(it->first); - if (!it->second(param)) + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it) { - if (emit_errors) + const Param* param = getParamFromHandle(it->first); + if (!it->second(param)) { - llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl; + if (emit_errors) + { + llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl; + } + return false; } - return false; } + mValidated = true; } - return true; + return mValidated; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const + void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const { + if (!isProvided()) + { + if ((~predicate_rule_t(PROVIDED) && predicate_rule).isTriviallyFalse()) + { + return; + } + } + // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -196,7 +209,7 @@ namespace LLInitParam if (serialize_func) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialize_func(*param, parser, name_stack, diff_param); + serialize_func(*param, parser, name_stack, predicate_rule, diff_param); } } @@ -232,7 +245,7 @@ namespace LLInitParam name_stack.push_back(std::make_pair(it->first, !duplicate)); const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialize_func(*param, parser, name_stack, diff_param); + serialize_func(*param, parser, name_stack, predicate_rule, diff_param); name_stack.pop_back(); } } diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index b7607e91b9..18c9669fba 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -32,10 +32,11 @@ #include <boost/function.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/unordered_map.hpp> -#include <boost/shared_ptr.hpp> +//#include <boost/shared_ptr.hpp> #include "llerror.h" #include "llstl.h" +#include "llpredicate.h" namespace LLInitParam { @@ -211,7 +212,6 @@ namespace LLInitParam LOG_CLASS(Parser); public: - typedef std::vector<std::pair<std::string, bool> > name_stack_t; typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t; typedef std::vector<std::string> possible_values_t; @@ -293,6 +293,17 @@ namespace LLInitParam class Param; + enum ESerializePredicates + { + PROVIDED, + REQUIRED, + VALID, + NON_DEFAULT + }; + + typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t; + + // various callbacks and constraints associated with an individual param struct LL_COMMON_API ParamDescriptor { @@ -303,8 +314,8 @@ namespace LLInitParam typedef bool(*merge_func_t)(Param&, const Param&, bool); typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); - typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); - typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); + typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t, const Param*); + typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32, S32); typedef bool(*validation_func_t)(const Param*); ParamDescriptor(param_handle_t p, @@ -331,7 +342,7 @@ namespace LLInitParam UserData* mUserData; }; - typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; + typedef ParamDescriptor* ParamDescriptorPtr; // each derived Block class keeps a static data structure maintaining offsets to various params class LL_COMMON_API BlockDescriptor @@ -484,12 +495,28 @@ namespace LLInitParam LOG_CLASS(BaseBlock); friend class Param; + BaseBlock() + : mValidated(false), + mParamProvided(false) + {} + virtual ~BaseBlock() {} bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); param_handle_t getHandleFromParam(const Param* param) const; bool validateBlock(bool emit_errors = true) const; + bool isProvided() const + { + return mParamProvided; + } + + bool isValid() const + { + return validateBlock(false); + } + + Param* getParamFromHandle(const param_handle_t param_handle) { if (param_handle == 0) return NULL; @@ -507,10 +534,19 @@ 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) {} + virtual void paramChanged(const Param& changed_param, bool user_provided) + { + if (user_provided) + { + // a child param has been explicitly changed + // so *some* aspect of this block is now provided + mValidated = false; + mParamProvided = true; + } + } 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; + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule = predicate_rule_t(), 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(); } @@ -549,6 +585,9 @@ namespace LLInitParam return sBlockDescriptor; } + mutable bool mValidated; // lazy validation flag + bool mParamProvided; + private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; @@ -688,13 +727,11 @@ namespace LLInitParam typedef ParamValue<T, NAME_VALUE_LOOKUP, true> self_t; ParamValue() - : T(), - mValidated(false) + : T() {} ParamValue(value_assignment_t other) - : T(other), - mValidated(false) + : T(other) {} void setValue(value_assignment_t val) @@ -736,9 +773,6 @@ namespace LLInitParam return *this; } - - protected: - mutable bool mValidated; // lazy validation flag }; template<typename NAME_VALUE_LOOKUP> @@ -836,6 +870,8 @@ namespace LLInitParam bool isProvided() const { return Param::anyProvided(); } + bool isValid() const { return true; } + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast<self_t&>(param); @@ -870,10 +906,26 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + const self_t* diff_typed_param = static_cast<const self_t*>(diff_param); + + LLPredicate::Value<ESerializePredicates> predicate; + if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue())) + { + predicate.set(NON_DEFAULT); + } + if (typed_param.isValid()) + { + predicate.set(VALID); + if (typed_param.anyProvided()) + { + predicate.set(PROVIDED); + } + } + + if (!predicate_rule.check(predicate)) return; if (!name_stack.empty()) { @@ -886,18 +938,18 @@ namespace LLInitParam if (!key.empty()) { - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) + if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key)) { parser.writeValue(key, name_stack); } } // then try to serialize value directly - else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue())) + else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue())) { if (!parser.writeValue(typed_param.getValue(), name_stack)) { std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)) + if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), calculated_key)) { parser.writeValue(calculated_key, name_stack); } @@ -1014,10 +1066,26 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + const self_t* diff_typed_param = static_cast<const self_t*>(diff_param); + + LLPredicate::Value<ESerializePredicates> predicate; + if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue())) + { + predicate.set(NON_DEFAULT); + } + if (typed_param.isValid()) + { + predicate.set(VALID); + if (typed_param.anyProvided()) + { + predicate.set(PROVIDED); + } + } + + if (!predicate_rule.check(predicate)) return; if (!name_stack.empty()) { @@ -1034,7 +1102,7 @@ namespace LLInitParam } else { - typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param)); + typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param)); } } @@ -1049,23 +1117,16 @@ namespace LLInitParam // *and* the block as a whole validates bool isProvided() const { - // only validate block when it hasn't already passed validation with current data - if (Param::anyProvided() && !param_value_t::mValidated) - { - // a sub-block is "provided" when it has been filled in enough to be valid - param_value_t::mValidated = param_value_t::validateBlock(false); - } - return Param::anyProvided() && param_value_t::mValidated; + return Param::anyProvided() && isValid(); } + using param_value_t::isValid; + // assign block contents to this param-that-is-a-block void set(value_assignment_t val, bool flag_as_provided = true) { setValue(val); param_value_t::clearValueName(); - // force revalidation of block - // next call to isProvided() will update provision status based on validity - param_value_t::mValidated = false; setProvided(flag_as_provided); } @@ -1080,9 +1141,6 @@ namespace LLInitParam param_value_t::paramChanged(changed_param, user_provided); if (user_provided) { - // a child param has been explicitly changed - // so *some* aspect of this block is now provided - param_value_t::mValidated = false; setProvided(); param_value_t::clearValueName(); } @@ -1134,7 +1192,9 @@ namespace LLInitParam typedef NAME_VALUE_LOOKUP name_value_lookup_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + : Param(block_descriptor.mCurrentBlockPtr), + mMinCount(min_count), + mMaxCount(max_count) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); @@ -1152,7 +1212,13 @@ namespace LLInitParam } } - bool isProvided() const { return Param::anyProvided(); } + bool isProvided() const { return Param::anyProvided() && isValid(); } + + bool isValid() const + { + size_t num_elements = numValidElements(); + return mMinCount < num_elements && num_elements < mMaxCount; + } static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { @@ -1197,7 +1263,7 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); if (!typed_param.isProvided()) return; @@ -1293,7 +1359,7 @@ namespace LLInitParam bool empty() const { return mValues.empty(); } size_t size() const { return mValues.size(); } - U32 numValidElements() const + size_t numValidElements() const { return mValues.size(); } @@ -1323,6 +1389,8 @@ namespace LLInitParam } container_t mValues; + size_t mMinCount, + mMaxCount; }; // container of block parameters @@ -1339,7 +1407,9 @@ namespace LLInitParam typedef NAME_VALUE_LOOKUP name_value_lookup_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + : Param(block_descriptor.mCurrentBlockPtr), + mMinCount(min_count), + mMaxCount(max_count) { std::copy(value.begin(), value.end(), back_inserter(mValues)); @@ -1357,7 +1427,14 @@ namespace LLInitParam } } - bool isProvided() const { return Param::anyProvided(); } + bool isProvided() const { return Param::anyProvided() && isValid(); } + + bool isValid() const + { + size_t num_elements = numValidElements(); + return mMinCount < num_elements && num_elements < mMaxCount; + } + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { @@ -1420,9 +1497,13 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); + + LLPredicate::Value<ESerializePredicates> predicate_value; + if (typed_param.isProvided()) predicate_value.set(PROVIDED); + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); @@ -1437,10 +1518,10 @@ namespace LLInitParam parser.writeValue(key, name_stack); } // Not parsed via named values, write out value directly - // NOTE: currently we don't worry about removing default values in Multiple + // NOTE: currently we don't do diffing of Multiples else { - it->serializeBlock(parser, name_stack, NULL); + it->serializeBlock(parser, name_stack, predicate_rule, NULL); } name_stack.pop_back(); @@ -1500,14 +1581,14 @@ namespace LLInitParam bool empty() const { return mValues.empty(); } size_t size() const { return mValues.size(); } - U32 numValidElements() const + size_t numValidElements() const { - U32 count = 0; + size_t count = 0; for (const_iterator it = mValues.begin(), end_it = mValues.end(); it != end_it; ++it) { - if(it->validateBlock(false)) count++; + if(it->isValid()) count++; } return count; } @@ -1539,6 +1620,8 @@ namespace LLInitParam } container_t mValues; + size_t mMinCount, + mMaxCount; }; template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> @@ -1826,7 +1909,7 @@ namespace LLInitParam static bool validate(const Param* paramp) { - U32 num_valid = ((super_t*)paramp)->numValidElements(); + size_t num_valid = ((super_t*)paramp)->numValidElements(); return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount; } }; @@ -1943,13 +2026,11 @@ namespace LLInitParam typedef block_t value_t; ParamValue() - : block_t(), - mValidated(false) + : block_t() {} ParamValue(value_assignment_t other) - : block_t(other), - mValidated(false) + : block_t(other) { } @@ -1977,9 +2058,6 @@ namespace LLInitParam { return *this; } - - protected: - mutable bool mValidated; // lazy validation flag }; template<typename T, bool IS_BLOCK> @@ -1994,13 +2072,11 @@ namespace LLInitParam typedef T value_t; ParamValue() - : mValue(), - mValidated(false) + : mValue() {} ParamValue(value_assignment_t other) - : mValue(other), - mValidated(false) + : mValue(other) {} void setValue(value_assignment_t val) @@ -2033,11 +2109,11 @@ namespace LLInitParam return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const { if (mValue.empty()) return; - mValue.get().serializeBlock(p, name_stack, diff_block); + mValue.get().serializeBlock(p, name_stack, predicate_rule, diff_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const @@ -2047,9 +2123,6 @@ namespace LLInitParam return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } - protected: - mutable bool mValidated; // lazy validation flag - private: BaseBlock::Lazy<T> mValue; }; @@ -2066,12 +2139,10 @@ namespace LLInitParam typedef const LLSD& value_assignment_t; ParamValue() - : mValidated(false) {} ParamValue(value_assignment_t other) - : mValue(other), - mValidated(false) + : mValue(other) {} void setValue(value_assignment_t val) { mValue = val; } @@ -2085,16 +2156,13 @@ namespace LLInitParam // block param interface LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); - LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { //TODO: implement LLSD params as schema type Any return true; } - protected: - mutable bool mValidated; // lazy validation flag - private: static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack); @@ -2123,8 +2191,7 @@ namespace LLInitParam CustomParamValue(const T& value = T()) : mValue(value), - mValueAge(VALUE_AUTHORITATIVE), - mValidated(false) + mValueAge(VALUE_AUTHORITATIVE) {} bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) @@ -2148,7 +2215,7 @@ namespace LLInitParam return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name); } - void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const { const derived_t& typed_param = static_cast<const derived_t&>(*this); const derived_t* diff_param = static_cast<const derived_t*>(diff_block); @@ -2184,11 +2251,11 @@ namespace LLInitParam // and serialize those params derived_t copy(typed_param); copy.updateBlockFromValue(true); - copy.block_t::serializeBlock(parser, name_stack, NULL); + copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL); } else { - block_t::serializeBlock(parser, name_stack, NULL); + block_t::serializeBlock(parser, name_stack, predicate_rule, NULL); } } } @@ -2309,8 +2376,6 @@ namespace LLInitParam return block_t::mergeBlock(block_data, source, overwrite); } - mutable bool mValidated; // lazy validation flag - private: mutable T mValue; mutable EValueAge mValueAge; diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp new file mode 100644 index 0000000000..8dcd9247b7 --- /dev/null +++ b/indra/llcommon/llpredicate.cpp @@ -0,0 +1,33 @@ +/** + * @file llpredicate.cpp + * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions + * + * $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$ + */ +#include "linden_common.h" + +#include "llpredicate.h" + +namespace LLPredicate +{ + EmptyRule make_rule() { return EmptyRule(); } +} diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h new file mode 100644 index 0000000000..ad5ab363fa --- /dev/null +++ b/indra/llcommon/llpredicate.h @@ -0,0 +1,173 @@ +/** + * @file llpredicate.h + * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPREDICATE_H +#define LL_LLPREDICATE_H + +#include "llerror.h" + +namespace LLPredicate +{ + template<typename ENUM> class Rule; + + template<typename ENUM> + struct Value + { + friend Rule<ENUM>; + public: + Value(ENUM e) + : mPredicateFlags(0x1), + mPredicateCombinationFlags(0x1) + { + set(e); + } + + Value() + : mPredicateFlags(0x1), + mPredicateCombinationFlags(0x1) + {} + + void set(ENUM predicate) + { + llassert(predicate <= 5); + int predicate_flag = 0x1 << (0x1 << (int)predicate); + if (!(mPredicateFlags & predicate_flag)) + { + mPredicateCombinationFlags *= predicate_flag; + mPredicateFlags |= predicate_flag; + } + } + + bool get(ENUM predicate) + { + int predicate_flag = 0x1 << (0x1 << (int)predicate); + return (mPredicateFlags & predicate_flag) != 0; + } + + void clear(ENUM predicate) + { + llassert(predicate <= 5); + int predicate_flag = 0x1 << (0x1 << (int)predicate); + if (mPredicateFlags & predicate_flag) + { + mPredicateCombinationFlags /= predicate_flag; + mPredicateFlags &= ~predicate_flag; + } + } + + private: + int mPredicateCombinationFlags; + int mPredicateFlags; + }; + + struct EmptyRule {}; + + template<typename ENUM> + class Rule + { + public: + Rule(EmptyRule e) + : mPredicateRequirements(0x1) + {} + + Rule(ENUM value) + : mPredicateRequirements(predicateFromValue(value)) + {} + + Rule() + : mPredicateRequirements(0x1) + {} + + Rule operator~() + { + Rule new_rule; + new_rule.mPredicateRequirements = ~mPredicateRequirements; + return new_rule; + } + + Rule operator &&(const Rule& other) + { + Rule new_rule; + new_rule.mPredicateRequirements = mPredicateRequirements & other.mPredicateRequirements; + return new_rule; + } + + Rule operator ||(const Rule& other) + { + Rule new_rule; + new_rule.mPredicateRequirements = mPredicateRequirements | other.mPredicateRequirements; + return new_rule; + } + + bool check(const Value<ENUM>& value) const + { + return ((value.mPredicateCombinationFlags | 0x1) & mPredicateRequirements) != 0; + } + + static int predicateFromValue(ENUM value) + { + int countdown = value; + bool bit_val = false; + + int predicate = 0x0; + + for (int bit_index = 0; bit_index < 32; bit_index++) + { + if (bit_val) + { + predicate |= 0x1 << bit_index; + } + + if (countdown-- == 0) + { + countdown = value; + bit_val = !bit_val; + } + } + return predicate; + } + + bool isTriviallyTrue() const + { + return mPredicateRequirements & 0x1; + } + + bool isTriviallyFalse() const + { + return mPredicateRequirements == 0; + } + + private: + int mPredicateRequirements; + }; + + template<typename ENUM> + Rule<ENUM> make_rule(ENUM e) { return Rule<ENUM>(e);} + + EmptyRule make_rule(); + +} +#endif // LL_LLPREDICATE_H diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 4b8a8dba5c..713f5ac605 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -329,7 +329,7 @@ namespace LLInitParam p.writeValue<LLSD::String>(sd.asString(), name_stack); } - void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const { // attempt to write LLSD out directly if (!p.writeValue<LLSD>(mValue, name_stack)) |