summaryrefslogtreecommitdiffstats
path: root/src/include/usr/targeting/predicates/predicatepostfixexpr.H
blob: 12388fc46ceb78f49c246a9bb369c4f15566ebfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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 <vector>

// Other Host Boot Components

// Targeting Component
#include <targeting/predicates/predicatebase.H>

//******************************************************************************
// 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<Operation> 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
OpenPOWER on IntegriCloud