/** * @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 class Rule; int predicateFlagsFromValue(int value); template struct Value { friend Rule; public: Value(ENUM e) : mPredicateCombinationFlags(0x1) { add(e); } Value() : mPredicateCombinationFlags(0x1) {} void add(ENUM predicate) { llassert(predicate < 5); if (!has(predicate)) { int predicate_shift = 0x1 << (int)predicate; mPredicateCombinationFlags <<= predicate_shift; } } void remove(ENUM predicate) { llassert(predicate < 5); int predicate_shift = 0x1 << (int)predicate; int flag_mask = predicateFlagsFromValue(predicate); int flags_to_modify = mPredicateCombinationFlags & flag_mask; // clear flags containing predicate to be removed mPredicateCombinationFlags &= ~flag_mask; // shift flags, in effect removing predicate flags_to_modify >>= predicate_shift; // put modified flags back mPredicateCombinationFlags |= flags_to_modify; } void unknown(ENUM predicate) { add(predicate); int flags_with_predicate = mPredicateCombinationFlags; remove(predicate); // unknown is result of adding and removing predicate at the same time! mPredicateCombinationFlags |= flags_with_predicate; } bool has(ENUM predicate) { int flag_mask = predicateFlagsFromValue(predicate); return (mPredicateCombinationFlags & flag_mask) != 0; } private: int mPredicateCombinationFlags; }; struct EmptyRule {}; template class Rule { public: Rule(ENUM value) : mPredicateRequirements(predicateFlagsFromValue(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& value) const { return ((value.mPredicateCombinationFlags | 0x1) & mPredicateRequirements) != 0; } bool isTriviallyTrue() const { return mPredicateRequirements & 0x1; } bool isTriviallyFalse() const { return mPredicateRequirements == 0; } private: int mPredicateRequirements; }; template Rule make_rule(ENUM e) { return Rule(e);} // return generic empty rule class to avoid requiring template argument to create an empty rule EmptyRule make_rule(); } #endif // LL_LLPREDICATE_H