From 213b45cd7d8b0367f85ee68b79941f6d548c1e9c Mon Sep 17 00:00:00 2001 From: Nick Bofferding Date: Tue, 16 Aug 2011 12:40:36 -0500 Subject: Add target iterator and predicate support Change-Id: I728bb312277591d81c0575e74878fba9f816b962 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/260 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III Reviewed-by: MIKE J. JONES --- src/include/usr/targeting/attributeenums.H | 1 + src/include/usr/targeting/iterators/rangefilter.H | 323 +++++++++++++++++++++ .../usr/targeting/iterators/targetiterator.H | 257 ++++++++++++++++ .../usr/targeting/predicates/predicatebase.H | 111 +++++++ .../usr/targeting/predicates/predicatectm.H | 118 ++++++++ .../targeting/predicates/predicatepostfixexpr.H | 204 +++++++++++++ src/include/usr/targeting/targetservice.H | 95 +++++- 7 files changed, 1093 insertions(+), 16 deletions(-) create mode 100644 src/include/usr/targeting/iterators/rangefilter.H create mode 100644 src/include/usr/targeting/iterators/targetiterator.H create mode 100644 src/include/usr/targeting/predicates/predicatebase.H create mode 100644 src/include/usr/targeting/predicates/predicatectm.H create mode 100644 src/include/usr/targeting/predicates/predicatepostfixexpr.H (limited to 'src/include/usr/targeting') diff --git a/src/include/usr/targeting/attributeenums.H b/src/include/usr/targeting/attributeenums.H index c4cd5c28a..6d7eed93d 100644 --- a/src/include/usr/targeting/attributeenums.H +++ b/src/include/usr/targeting/attributeenums.H @@ -34,6 +34,7 @@ namespace TARGETING */ enum ATTRIBUTE_ID { + ATTR_NA = 0x00, ATTR_CLASS = 0x01, ATTR_TYPE = 0x02, ATTR_MODEL = 0x03, diff --git a/src/include/usr/targeting/iterators/rangefilter.H b/src/include/usr/targeting/iterators/rangefilter.H new file mode 100644 index 000000000..b582cb0b6 --- /dev/null +++ b/src/include/usr/targeting/iterators/rangefilter.H @@ -0,0 +1,323 @@ + +#ifndef TARG_RANGEFILTER_H +#define TARG_RANGEFILTER_H + +/** + * @file rangefilter.H + * + * @brief Interface describing an object which takes an iterator range and + * allows caller to iterate through the elements which match a supplied + * predicate (filter) + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD + +// Other Host Boot Components + +// Targeting Component +#include +#include +#include + +//****************************************************************************** +// Macros +//****************************************************************************** + +#undef TARG_NAMESPACE +#undef TARG_CLASS +#undef TARG_FUNC + +//****************************************************************************** +// Interface +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" + +#define TARG_CLASS "RangeFilter::" + +/** + * @brief Templated class which which takes an iterator range of arbitrary type + * and allows caller to iterate through the elements which match a supplied + * predicate (filter) + */ +template +class RangeFilter +{ + public: + + /** + * @var Forward the type of iterated elements to help build the + * class generically + */ + typedef typename IteratorType::value_type value_type; + + /** + * @var fake_bool is a pointer to a member function of RangeFilter + * which takes no arguments and returns void. + * Used to implement ability to check if range iterator is valid + */ + typedef void (RangeFilter::*fake_bool)() const; + + /** + * @brief Create a range object and locate first item in the range that + * matches the predicate (or the first if no predicate) + * + * @param[in] i_begin Iterator pointing to first item in range + * @param[in] i_end Iterator pointing to last item in range + * @param[in] i_pPredicate Predicate evaluated against each pointed to + * item + * + * @note Begin iterator must point to element prior to end iterator, + * otherwise result is undefined + */ + RangeFilter( + const IteratorType& i_begin, + const IteratorType& i_end, + const PredicateBase* i_pPredicate = NULL); + + /** + * @brief Destroy a range object (nothing to do) + */ + ~RangeFilter() + { + } + + /** + * @brief Dummy function used to implement ability to check if range + * iterator is valid + */ + operator fake_bool() const + { + return (iv_current != iv_end) + ? &RangeFilter::notComparable : NULL; + } + + /** + * @brief Pre-increment operator which advances the range's iterator + * to point to the next valid element + * + * @return Reference to this range filter + */ + RangeFilter& operator++(); + + /** + * @brief Dereference the range filter, returning the element pointed + * + * @return The element pointed to by the range filter + */ + value_type operator*() const + { + return *iv_current; + } + + /** + * @brief Dereference the range filter, returning the element pointed + * for use by the dereference and call member operator + * + * @return The element pointed to by the range filter + */ + value_type operator->() const + { + return *iv_current; + } + + /** + * @brief Reset the range's internal iterator to point to the first + * item in the range that matches the predicate (or the first if no + * predicate) + */ + void reset(); + + /** + * @brief Set the range's predicate filter + * + * @param[in] i_pPredicate Predicate to evaluate against elements + * pointed to by the range + */ + void setPredicate( + const PredicateBase* i_pPredicate); + + /** + * @brief Assignment operator; assign one range filter to another + * + * @param[in] i_rhs Range filter to assign + */ + RangeFilter& operator=( + const RangeFilter& i_rhs); + + /** + * @brief Copy constructor; create range filter using another range + * filter as a prototype for it + * + * @param[in] i_rhs Range filter to assign on create + */ + RangeFilter( + const RangeFilter& i_rhs); + + private: + + /** + * @brief Update internal cursor to point to the next element of the + * underlying range + * + * @note If the internal cursor is at the end of the range, then do + * nothing + */ + void advance(); + + /** + * @brief Update internal cursor to point to the next element of the + * underlying range only if not past the end of the range and the + * predicate doesn't match the current item + * + * @note If the internal cursor is at the end of the range, then do + * nothing + */ + void advanceIfNoMatch(); + + /** + * @brief Dummy function used to implement ability to check if range + * iterator is valid + */ + void notComparable() const + { + } + + IteratorType iv_current; ///< Iterator pointing to the + ///< current element + IteratorType iv_begin; ///< Iterator pointing to first + ///< element in range + IteratorType iv_end; ///< Iterator to past the end + ///< element in range + const PredicateBase* iv_pPredicate; ///< Range filter +}; + +typedef RangeFilter TargetRangeFilter; +typedef RangeFilter ConstTargetRangeFilter; + +//****************************************************************************** +// RangeFilter::RangeFilter +//****************************************************************************** + +template +RangeFilter::RangeFilter( + const IteratorType& i_begin, + const IteratorType& i_end, + const PredicateBase* const i_pPredicate) +: iv_current(i_begin), + iv_begin(i_begin), + iv_end(i_end), + iv_pPredicate(i_pPredicate) +{ + advanceIfNoMatch(); +} + +//****************************************************************************** +// RangeFilter::operator= +//****************************************************************************** + +template +RangeFilter& RangeFilter::operator=( + const RangeFilter& i_rhs) +{ + iv_current = i_rhs.iv_current; + iv_begin = i_rhs.iv_begin; + iv_end = i_rhs.iv_end; + iv_pPredicate = i_rhs.iv_pPredicate; +} + +//****************************************************************************** +// RangeFilter::RangeFilter (copy constructor) +//****************************************************************************** + +template +RangeFilter::RangeFilter( + const RangeFilter& i_rhs) +: iv_current(i_rhs.iv_current), + iv_begin(i_rhs.iv_begin), + iv_end(i_rhs.iv_end), + iv_pPredicate(i_rhs.iv_pPredicate) +{ +} + +//****************************************************************************** +// RangeFilter::setPredicate +//****************************************************************************** + +template +void RangeFilter::setPredicate( + const PredicateBase* const i_pPredicate) +{ + iv_pPredicate = i_pPredicate; + advanceIfNoMatch(); +} + +//****************************************************************************** +// RangeFilter::reset +//****************************************************************************** + +template +void RangeFilter::reset() +{ + iv_current = iv_begin; + advanceIfNoMatch(); +} + +//****************************************************************************** +// RangeFilter::operator++ +//****************************************************************************** + +template +RangeFilter& RangeFilter::operator++() +{ + advance(); + return *this; +} + +/** + * @brief Disable meaningless "bool" comparisons that can occur when + * evaluating a range as a bool by forcing a compilation failure. + * Function interfaces not documented since they are not used. + */ +template +bool operator!=(const TargetRangeFilter& i_lhs, const T& i_rhs) +{ + i_lhs.notComparable(); + return false; +} + +template +bool operator==(const TargetRangeFilter& i_lhs, const T& i_rhs) +{ + i_lhs.notComparable(); + return false; +} + +template +bool operator!=(const ConstTargetRangeFilter& i_lhs, const T& i_rhs) +{ + i_lhs.notComparable(); + return false; +} + +template +bool operator==(const ConstTargetRangeFilter& i_lhs, const T& i_rhs) +{ + i_lhs.notComparable(); + return false; +} + +#undef TARG_CLASS +#undef TARG_NAMESPACE + +} // End namespace TARGETING + +#endif + diff --git a/src/include/usr/targeting/iterators/targetiterator.H b/src/include/usr/targeting/iterators/targetiterator.H new file mode 100644 index 000000000..6f250cbb5 --- /dev/null +++ b/src/include/usr/targeting/iterators/targetiterator.H @@ -0,0 +1,257 @@ + +#ifndef TARG_TARGETITERATOR_H +#define TARG_TARGETITERATOR_H + +/** + * @file targetiterator.H + * + * @brief Interface describing iterator/const iterator used to iterate through + * target service targets + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD +#include + +// Other Host Boot Components +#include + +// Targeting Component + +//****************************************************************************** +// Macros +//****************************************************************************** + +#undef TARG_NAMESPACE +#undef TARG_CLASS +#undef TARG_FUNC + +//****************************************************************************** +// Interface +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" + +#define TARG_CLASS "_TargetIterator::" + +class Target; + +/** + * @brief Class which iterates through targets managed by the target service. + * Provides "Target*" and "const Target*" versions via templates + */ +template +class _TargetIterator +{ + public: + + /** + * @brief Maps type of iterated element to common alias (Target* or + * const Target*) + */ + typedef T iterator; + typedef T value_type; + + /** + * @brief Create an iterator to a (const/non-const) target handle. + * Defaults to end() + */ + ALWAYS_INLINE + _TargetIterator() + : iv_pCurrent(NULL) + { + } + + /** + * @brief Create an iterator to a (const/non-const) target handle + * + * @param[in] i_pTarget Target handle (pointer or const pointer + * depending on flavor) the iterator should reference + */ + ALWAYS_INLINE + explicit _TargetIterator(T i_pTarget) + : iv_pCurrent(i_pTarget) + { + } + + /** + * @brief Destroy an iterator to a (const/non-const) target handle + * + * @note Iterator does not own any resources to destroy + */ + ALWAYS_INLINE + ~_TargetIterator() + { + } + + /** + * @brief Dereference the iterator (return what it points to) + * + * @return Target handle in form of Target* or const Target* + * + * @note Returns NULL if it points to end(), should not be + * dereferenced in this case. + */ + ALWAYS_INLINE + T operator* () const + { + // Only return copy of the target pointer (instead of a reference) + // because a reference will go out of scope when the iterator + // advances + return iv_pCurrent; + } + + /** + * @brief Dereference the iterator (return what it points to) + * and (outside this function) call a function/member of + * the referenced target + * + * @return Target handle in form of Target* or const Target* + * + * @note Returns NULL if it points to end(), causing an + * assert when automatically dereferenced. + */ + ALWAYS_INLINE + T operator->() const + { + // Only return copy of the target pointer (instead of a reference) + // because a reference will go out of scope when the iterator + // advances + return iv_pCurrent; + } + + /** + * @brief Pre-increment the iterator + * + * @return The reference to the same iterator after advancing it + */ + ALWAYS_INLINE + _TargetIterator& operator++(); + + /** + * @brief Post-increment the iterator + * + * @param[in] UNNAMED Dummy parameter used to distinguish + * this interface from pre-increment + * + * @return Copy of the original iterator before it advanced + */ + ALWAYS_INLINE + _TargetIterator operator++(int); + + /** + * @brief Determine if two iterators of same type are logically equal + * + * @param[in] i_rhs The other iterator to compare + * + * @return bool indicating whether the iterators point to the same + * entity + * + * @retval true Iterators point to same entity + * @retval false Iterators do not point to same entity + */ + ALWAYS_INLINE + bool operator==(const _TargetIterator& i_rhs) const + { + return (iv_pCurrent == i_rhs.iv_pCurrent); + } + + /** + * @brief Determine if two iterators of same type are logically not + * equal + * + * @param[in] i_rhs The other iterator to compare + * + * @return bool indicating whether the iterators point to a different + * logical entity + * + * @retval true Iterators point to different entity + * @retval false Iterators point to same entity + */ + ALWAYS_INLINE + bool operator!=(const _TargetIterator& i_rhs) const + { + return (iv_pCurrent != i_rhs.iv_pCurrent); + } + + /** + * @brief Assignment operator; assign iterator to another (such that + * they logically point to same entity) + * + * @param[in] i_rhs The iterator to assign + * + * @return Reference to the iterator, now updated to point to the same + * entity as the input iterator points to + */ + ALWAYS_INLINE + _TargetIterator& operator=(const _TargetIterator& i_rhs) + { + iv_pCurrent = i_rhs.iv_pCurrent; + return *this; + } + + /** + * @brief Copy constructor; assign iterator to a new iterator (such + * that they logically point to same entity) + * + * @param[in] i_rhs The iterator to assign + */ + ALWAYS_INLINE + _TargetIterator(const _TargetIterator& i_rhs) + : iv_pCurrent(i_rhs.iv_pCurrent) + { + } + + private: + + /** + * @brief Advance the iterator to point to the next item maintained by + * the target service (or end() if end of list) + */ + void advance(); + + T iv_pCurrent; // Pointer to current target +}; + +/** + * @brief Type aliases to simplify user code + */ +typedef _TargetIterator TargetIterator; +typedef _TargetIterator ConstTargetIterator; + +//****************************************************************************** +// _TargetIterator::operator++ (postincrement) +//****************************************************************************** + +template +_TargetIterator _TargetIterator::operator++(int) +{ + _TargetIterator l_originalIterator(*this); + advance(); + return l_originalIterator; +} + +//****************************************************************************** +// _TargetIterator::operator++ (preincrement) +//****************************************************************************** + +template +_TargetIterator& _TargetIterator::operator++() +{ + advance(); + return *this; +} + +#undef TARG_CLASS +#undef TARG_NAMESPACE + +} // End namespace TARGETING + +#endif // TARG_TARGETITERATOR_H + diff --git a/src/include/usr/targeting/predicates/predicatebase.H b/src/include/usr/targeting/predicates/predicatebase.H new file mode 100644 index 000000000..e555092b9 --- /dev/null +++ b/src/include/usr/targeting/predicates/predicatebase.H @@ -0,0 +1,111 @@ + +#ifndef TARG_PREDICATEBASE_H +#define TARG_PREDICATEBASE_H + +/** + * @file predicatebase.H + * + * @brief Interface for an abstract targeting predicate which filters a set of + * targets based on the programmed criteria. Concrete predicates must + * provide the interface specified here. + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD + +// Other Host Boot Components + +// Targeting Component + +//****************************************************************************** +// Macros +//****************************************************************************** + +/** + * @brief Disable copy constructor / assignment operators + */ +#undef TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS +#define TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(Type) \ + Type(const Type& i_other); \ + Type& operator=(const Type& i_other) + +/** + * @brief Ensure trace macros are undefined + */ +#undef TARG_NAMESPACE +#undef TARG_CLASS +#undef TARG_FN + +//****************************************************************************** +// Interface +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" +#define TARG_CLASS "PredicateBase::" + +class Target; + +/** + * @brief Abstract predicate class which specifies an interface for all + * concrete predicates. A predicate acts as a filter on a set of targets. + */ +class PredicateBase +{ + public: + + /** + * @brief Destroys the predicate base class (nothing to do) + */ + virtual ~PredicateBase(); + + /** + * @brief Predicate function call interface + * + * @par Detailed Description: + * This abstract interface must be declared/implemented by all + * derived predicates. A concrete version of this function accepts + * a target, applies the associated predicate logic, and returns + * whether the target met the predicate criteria or not. Caller + * must always supply a valid Target*, or routine will assert. + * + * @param[in] i_pTarget Pointer to target to apply predicate to + * + * @return Boolean indicating whether target matches criteria specified + * by the concrete predicate + * + * @retval true Target matches the predicate criteria + * @retval false Target does not match the predicate criteria + */ + virtual bool operator()( + const Target* i_pTarget) const = 0; + + protected: + + /** + * @brief Create the predicate base class (nothing to do) + * + * @note Constructor protected to allow access from the derived class + */ + PredicateBase() + { + #define TARG_FN "PredicateBase()" + #undef TARG_FN + } + + private: + + TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicateBase); +}; + +#undef TARG_CLASS +#undef TARG_NAMESPACE + +} // End namespace TARGETING + +#endif // TARG_PREDICATEBASE_H diff --git a/src/include/usr/targeting/predicates/predicatectm.H b/src/include/usr/targeting/predicates/predicatectm.H new file mode 100644 index 000000000..760f0d02d --- /dev/null +++ b/src/include/usr/targeting/predicates/predicatectm.H @@ -0,0 +1,118 @@ + +#ifndef TARG_PREDICATECTM_H +#define TARG_PREDICATECTM_H + +/** + * @file predicatectm.H + * + * @brief Interface for a predicate which fiters a target based on its class, + * type, and model. + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD + +// Other Host Boot Components + +// Targeting Component +#include +#include +#include + +//****************************************************************************** +// Macros +//****************************************************************************** + +#undef TARG_NAMESPACE +#undef TARG_CLASS +#undef TARG_FN + +//****************************************************************************** +// Interface +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" +#define TARG_CLASS "PredicateCTM::" + +class Target; + +/** + * @brief Predicate class which filters a target based on its class, type, + * and model + */ +class PredicateCTM : public PredicateBase +{ + public: + + /** + * @brief Create a target class, type, model predicate + * + * @param[in] i_class Class of matching target, default NA (any) + * @param[in] i_type Type of matching target, default NA (any) + * @param[in] i_model Model of matching target, default NA (any) + */ + PredicateCTM( + CLASS i_class = CLASS_NA, + TYPE i_type = TYPE_NA, + MODEL i_model = MODEL_NA); + + /** + * @brief Destroy a class, type, model predicate + */ + virtual ~PredicateCTM() + { + #define TARG_FUNC "~PredicateCTM()" + #undef TARG_FUNC + } + + /** + * @brief Returns whether target matches the specified class, type, + * model + * + * @par Detailed Description: + * Returns whether target matches the specified class, type, model. + * Note that all three fields are always compared, so wildcards + * (CLASS_NA, TYPE_NA, MODEL_NA) must be used for any fields that + * do not matter. See PredicateBase class for parameter/return + * description. + */ + virtual bool operator()( + const Target* i_pTarget) const; + + private: + + CLASS iv_class; ///< Class to compare with that of target + TYPE iv_type; ///< Type to compare with that of target + MODEL iv_model; ///< Model to compare with that of target + + TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicateCTM); +}; + +//****************************************************************************** +// PredicateCTM::PredicateCTM +//****************************************************************************** + +inline PredicateCTM::PredicateCTM( + const CLASS i_class, + const TYPE i_type, + const MODEL i_model) +: iv_class(i_class), + iv_type(i_type), + iv_model(i_model) +{ + #define TARG_FUNC "PredicateCTM(...)" + #undef TARG_FUNC +} + +#undef TARG_CLASS +#undef TARG_NAMESPACE + +} // End namespace TARGETING + +#endif // TARG_PREDICATECTM_H diff --git a/src/include/usr/targeting/predicates/predicatepostfixexpr.H b/src/include/usr/targeting/predicates/predicatepostfixexpr.H new file mode 100644 index 000000000..12388fc46 --- /dev/null +++ b/src/include/usr/targeting/predicates/predicatepostfixexpr.H @@ -0,0 +1,204 @@ + +#ifndef TARG_PREDICATEPOSTFIXEXPR_H +#define TARG_PREDICATEPOSTFIXEXPR_H + +/** + * @file predicatepostfixexpr.H + * + * @brief Interface for predicate which allows callers to chain multiple other + * predicates together in complex logical expressions, and then evaluate + * them against a target + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD +#include + +// Other Host Boot Components + +// Targeting Component +#include + +//****************************************************************************** +// Macros +//****************************************************************************** + +#undef TARG_NAMESPACE +#undef TARG_CLASS +#undef TARG_FN + +//****************************************************************************** +// Interface +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" +#define TARG_CLASS "PredicatePostfixExpr::" + +class Target; + +/** + * @brief Predicate which can compute aribtrarily complex logical expressions + * of other predicates using postfix notation + */ +class PredicatePostfixExpr : public PredicateBase +{ + public: + + /** + * @brief Create empty postfix predicate expression which will always + * evaluate true if not otherwise modified. Any updates to the + * expression completely replace the initial "always true" + * behavior. + */ + PredicatePostfixExpr(); + + /** + * @brief Destroy a postfix predicate expression + * + * @note: Nothing extra to do here since object does not own the + * predicates + */ + virtual ~PredicatePostfixExpr(); + + /** + * @brief Updates the postfix predicate expression by pushing the given + * predicate onto the expression stack + * + * @param[in] i_pPredicate Pointer to existing concrete predicate. + * Passing a NULL predicate is not allowed (results in assert) + * + * @verbatim + * Example: + * + * Stack before calling push(&P2): P1 + * Stack after calling push(&P2): P1 P2 + * @endverbatim + * + * @return Reference to the same predicate expression, for chaining + */ + PredicatePostfixExpr& push( + const PredicateBase* i_pPredicate); + + /** + * @brief Updates the postfix predicate expression by pushing the + * logical "AND" operation onto the expression stack. + * + * @verbatim + * Example: + * + * Stack before calling And(): P1 P2 + * Stack after calling And(): P1 P2 AND + * Stack after evaluation: (P1 && P2) + * @endverbatim + * + * @return Reference to the same predicate expression, for chaining + */ + PredicatePostfixExpr& And(); + + /** + * @brief Updates the postfix predicate expression by pushing the + * logical "NOT" operation onto the expression stack. + * + * @verbatim + * Example: + * + * Stack before calling Not(): P1 + * Stack after calling Not(): P1 NOT + * Stack after evaluation: (!P1) + * @endverbatim + * + * @return Reference to the same predicate expression, for chaining + */ + PredicatePostfixExpr& Not(); + + /** + * @brief Updates the postfix predicate expression by pushing the + * logical "OR" operation onto the expression stack. + * + * @verbatim + * Example: + * + * Stack before calling Or(): P1 P2 + * Stack after calling Or(): P1 P2 OR + * Stack after evaluation: (P1 || P2) + * @endverbatim + * + * @return Reference to the same predicate expression for chaining + */ + PredicatePostfixExpr& Or(); + + /** + * @brief Returns whether the given target matches the criteria + * specified by the postfix predicate expression + * + * @par Detailed Description: + * Returns whether the given target matches the criteria + * specified by the postfix predicate expression. The routine + * sequentially evaluates a predicate against the supplied target + * or applies a logical operation to one or more prior predicate + * evaluations using a postfix algorithm. Routine will assert + * if postfix expression is not formatted properly, final result + * stack does not have exactly one result, target is NULL, or + * invalid logical operator was requested. See PredicateBase class + * for parameter/return description. + * + * @verbatim + * Example: + * + * PredicatePostfixExpr l_expr; + * l_expr.push(&P1).push(&P2).Or().push(&P3).And().Not(); + * + * Equivalent infix expression: !((P1 || P2) && P3) + * Assume predicate results of: P1 = 0, P2 = 1, P3 = 0 + * Expression stack prior to evaluation: P1 P2 OR P3 AND NOT + * Evaluation step 1: 1 P3 AND NOT (evaluated P1 P2 OR) + * Evaluation step 2: 0 NOT (evaluated 1 P3 AND) + * Evaluation step 3: 1 (evaluated 0 NOT; final result) + * @endverbatim + */ + virtual bool operator()( + const Target* i_pTarget) const; + + private: + + /** + * @brief Enumeration describing the type of logical operator to + * apply to one or more previous predicate evaluations + */ + enum LogicalOperator + { + EVAL, ///< Special logical operator - evaluate a predicate + AND, ///< Logically AND the result of the preceding two evaluations + OR, ///< Logically OR the result of the preceding two evaluations + NOT, ///< Logically negate the result of the preceding evaluation + }; + + /** + * @brief Structure describing one unit of the postfix predicate + * expression under evaluation + */ + struct Operation + { + LogicalOperator logicalOp; ///< Logical operator to + ///< apply to result stack + const PredicateBase* const pPredicate; ///< Predicate to evaluate, + ///< if logicalOp == EVAL + }; + + std::vector iv_ops; ///< Expression operations to perform + + TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicatePostfixExpr); +}; + +#undef TARG_CLASS +#undef TARG_NAMESPACE + +} // End namespace TARGETING + +#endif // TARG_PREDICATEPOSTFIXEXPR_H diff --git a/src/include/usr/targeting/targetservice.H b/src/include/usr/targeting/targetservice.H index 2797890c5..77e4b23f4 100644 --- a/src/include/usr/targeting/targetservice.H +++ b/src/include/usr/targeting/targetservice.H @@ -28,6 +28,8 @@ #include #include #include +#include +#include //****************************************************************************** // Interface Definitions @@ -139,6 +141,52 @@ class TargetService */ void init(); + /** + * @brief Map iterator types to common aliases + */ + typedef TargetIterator iterator; + typedef ConstTargetIterator const_iterator; + + /** + * @brief Return iterator which points to first target service target + * (or end() if none) + * + * @return Iterator pointing to first target service target + */ + iterator begin(); + + /** + * @brief Return iterator to const which points to first target service + * target (or end() if none) + * + * @return Iterator to const pointing to first target service target + */ + const_iterator begin() const; + + /** + * @brief Return iterator which points to the "past the end of the + * list" target maintained by the target service + * + * @return Iterator pointing to the "past the end of the list" target + * maintained by the target service + */ + iterator end(); + + /** + * @brief Return iterator to const which points to the "past the end of + * the list" target maintained by the target service + * + * @return Iterator to const pointing to the "past the end of the list" + * target maintained by the target service + */ + const_iterator end() const; + + /** + * @brief Allow iterator access to the target service's target store + */ + friend class _TargetIterator; + friend class _TargetIterator; + /** * @brief Returns the top level physical target * @@ -272,25 +320,31 @@ class TargetService * for said source target, the routine will return all targets * contained within the processor chip. * + * @param[out] o_list List of target handles that match the specified + * criteria * @param[in] i_pTarget Target from which to search for other targets * @param[in] i_type Type of association linking the specified target * to candidate result targets * @param[in] i_recursionLevel Whether to return candidate targets * immediately associated to the specified target or recursively * associated to it. - * @param[out] o_list List of target handles that match the specified - * criteria + * @param[in] i_pPredicate Pointer to a predicate to be evaluated + * against each candidate target (as determined by the source + * target, type, and recursion level parameters). If the predicate + * returns true, the target will be added to the result list. A + * value of NULL acts as a predicate that always returns true. * * @pre N/A * * @post Caller's list cleared; list of target handles matching the * specified criteria returned */ - void getAssociated( - const Target* i_pTarget, - ASSOCIATION_TYPE i_type, - RECURSION_LEVEL i_recursionLevel, - TargetHandleList& o_list) const; + void getAssociated( + TargetHandleList& o_list, + const Target* const i_pTarget, + const ASSOCIATION_TYPE i_type = CHILD, + const RECURSION_LEVEL i_recursionLevel = IMMEDIATE, + const PredicateBase* i_pPredicate = NULL) const; /** * @brief Dump the target service for debug only @@ -387,6 +441,10 @@ class TargetService * @param[in] i_recursionLevel Whether to provide immediate or * recursive results * @param[in] i_entityPath Entity path to start search from + * @param[in] i_pPredicate Pointer to a predicate to be evaluated + * against each candidate target. If the predicate returns true, + * the target will be added to the result list. A value of NULL + * acts as a predicate that always returns true. * @param[out] o_list List of returned target handles * * @pre Target service must be initialized @@ -396,10 +454,11 @@ class TargetService * path returned */ void _getInwards( - ATTRIBUTE_ID i_attr, - RECURSION_LEVEL i_recursionLevel, - EntityPath i_entityPath, - TargetHandleList& o_list) const; + ATTRIBUTE_ID i_attr, + RECURSION_LEVEL i_recursionLevel, + EntityPath i_entityPath, + const PredicateBase* i_pPredicate, + TargetHandleList& o_list) const; /** * @brief Returns handles to the targets associated to the @@ -418,6 +477,10 @@ class TargetService * @param[in] i_recursionLevel Whether to provide immediate or * recursive results * @param[in] i_entityPath Entity path to look from + * @param[in] i_pPredicate Pointer to a predicate to be evaluated + * against each candidate target. If the predicate returns true, + * the target will be added to the result list. A value of NULL + * acts as a predicate that always returns true. * @param[out] o_list List of returned target handles * * @pre Target service must be initialized @@ -427,13 +490,13 @@ class TargetService * entity path returned. */ void _getOutwards( - ATTRIBUTE_ID i_attr, - RECURSION_LEVEL i_recursionLevel, - EntityPath i_entityPath, - TargetHandleList& o_list ) const; + ATTRIBUTE_ID i_attr, + RECURSION_LEVEL i_recursionLevel, + EntityPath i_entityPath, + const PredicateBase* i_pPredicate, + TargetHandleList& o_list ) const; // Instance variables - bool iv_initialized; ///< Is service initialized or not Target (*iv_targets)[]; ///< Pointer to array of target objects uint32_t iv_maxTargets; ///< Maximum # target objects in the array -- cgit v1.2.1