19
19
// You should have received a copy of the GNU Lesser General Public
20
20
// License along with this library; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
23
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
25
#include "config.h"
27
static char rcsid[] not_used =
28
{"$Id: ConstraintEvaluator.cc 24370 2011-03-28 16:21:32Z jimg $"
29
#include "ServerFunctionsList.h"
31
30
#include "ConstraintEvaluator.h"
33
#include "ce_functions.h"
35
32
#include "ce_parser.h"
36
//#include "ce_expr.tab.hh"
38
38
struct yy_buffer_state;
39
yy_buffer_state *ce_expr_scan_string(const char *str);
40
int ce_exprparse(void *arg);
40
int ce_exprparse(libdap::ce_parser_arg *arg);
42
42
// Glue routines declared in expr.lex
43
43
void ce_expr_switch_to_buffer(void *new_buffer);
44
44
void ce_expr_delete_buffer(void * buffer);
45
45
void *ce_expr_string(const char *yy_str);
47
extern int ce_exprdebug;
49
51
ConstraintEvaluator::ConstraintEvaluator()
51
register_functions(*this);
53
// Functions are now held in BES modules. jhrg 1/30/13
55
// modules load functions to this list; this class searches the list
56
// instead of having it's own copy. This is very similar to the BES'
57
// various List classes, but this one is part of libdap and not the
58
// BES. The List class is a singleton, so each function module can
59
// register it's functions to the list object.
60
d_functions_list = ServerFunctionsList::TheList();
54
63
ConstraintEvaluator::~ConstraintEvaluator()
56
65
// delete all the constants created by the parser for CE evaluation
57
66
for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
62
72
for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
68
79
/** Returns the first clause in a parsed constraint expression. */
69
ConstraintEvaluator::Clause_iter
70
ConstraintEvaluator::clause_begin()
80
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
75
85
/** Returns a reference to the end of the list of clauses in a parsed
76
constraint expression. It does not reference the last clause */
77
ConstraintEvaluator::Clause_iter
78
ConstraintEvaluator::clause_end()
86
constraint expression. It does not reference the last clause */
87
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
83
92
/** Returns the value of the indicated clause of a constraint
86
ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
94
bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
89
throw InternalErr(__FILE__, __LINE__,
90
"There are no CE clauses for *this* DDS object.");
97
throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
92
99
return (*iter)->value(dds);
95
102
/** @brief Add a clause to a constraint expression.
97
This function adds an operator clause to the constraint
104
This function adds an operator clause to the constraint
100
@param op An integer indicating the operator in use. These
101
values are generated by \c bison.
102
@param arg1 A pointer to the argument on the left side of the
104
@param arg2 A pointer to a list of the arguments on the right
105
side of the operator.
108
ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
107
@param op An integer indicating the operator in use. These
108
values are generated by \c bison.
109
@param arg1 A pointer to the argument on the left side of the
111
@param arg2 A pointer to a list of the arguments on the right
112
side of the operator.
114
void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
110
116
Clause *clause = new Clause(op, arg1, arg2);
149
153
/** The Constraint Evaluator maintains a list of BaseType pointers for all the
150
constants that the constraint expression parser generates. These objects
151
are deleted by the Constraint Evaluator destructor. Note that there are no
152
list accessors; these constants are never accessed from the list. The list
153
is simply a convenient way to make sure the constants are disposed of
154
constants that the constraint expression parser generates. These objects
155
are deleted by the Constraint Evaluator destructor. Note that there are no
156
list accessors; these constants are never accessed from the list. The list
157
is simply a convenient way to make sure the constants are disposed of
157
ConstraintEvaluator::append_constant(BaseType *btp)
160
void ConstraintEvaluator::append_constant(BaseType *btp)
159
162
constants.push_back(btp);
165
// This code was removed when I switched from CE having it's own internal
166
// list of functions to using an external list.
165
170
const string d_name;
168
func_name_is(const string &name): d_name(name)
173
func_name_is(const string &name) :
170
177
bool operator()(const ConstraintEvaluator::function f)
172
179
return f.name == d_name;
176
183
/** The Constraint Evaluator carries with it a list of external functions it
177
can use while evaluate a constraint expression. If a constraint contains
178
any of these functions, the entries in the list allow the parser to evaluate
179
it. The functions are of three types: those that return boolean values,
180
those that return real (also called BaseType) values, and those that
181
are applied during evaluation of the projection for side effect
183
@note The add_function() methods will replace a function of the same name,
184
so it is possible to overwrite functions in specific handlers if the
185
handler need special behavior to implement one of the standard functions.
187
@see ce_functions for the standard functions
189
These methods are used to manipulate this list of known
192
@name External Function Accessors
184
can use while evaluate a constraint expression. If a constraint contains
185
any of these functions, the entries in the list allow the parser to evaluate
186
it. The functions are of three types: those that return boolean values,
187
those that return real (also called BaseType) values, and those that
188
are applied during evaluation of the projection for side effect
190
@note The add_function() methods will replace a function of the same name,
191
so it is possible to overwrite functions in specific handlers if the
192
handler need special behavior to implement one of the standard functions.
194
@see ce_functions for the standard functions
196
These methods are used to manipulate this list of known
199
@name External Function Accessors
195
202
/** @brief Add a boolean function to the list. */
197
ConstraintEvaluator::add_function(const string &name, bool_func f)
203
void ConstraintEvaluator::add_function(const string &name, bool_func f)
199
205
functions.remove_if(func_name_is(name));
200
206
function func(name, f);
270
281
/** @brief Does the current constraint expression return a BaseType
272
This method does not evaluate the clause, it provides information to the
273
evaluator regarding _how_ to evaluate the clause.
274
@return True if the clause is a function that returns a BaseType* and
277
ConstraintEvaluator::functional_expression()
283
This method does not evaluate the clause, it provides information to the
284
evaluator regarding _how_ to evaluate the clause.
285
@return True if the clause is a function that returns a BaseType* and
289
bool ConstraintEvaluator::functional_expression()
279
291
if (expr.empty())
282
Clause *cp = expr[0] ;
294
Clause *cp = expr[0];
283
295
return cp->value_clause();
286
/** @brief Evaluate a function-valued constraint expression. */
298
/** @brief Evaluate a function-valued constraint expression.
288
302
ConstraintEvaluator::eval_function(DDS &dds, const string &)
290
304
if (expr.size() != 1)
291
throw InternalErr(__FILE__, __LINE__,
292
"The length of the list of CE clauses is not 1.");
305
throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
294
Clause *cp = expr[0] ;
307
Clause *cp = expr[0];
295
308
BaseType *result;
296
309
if (cp->value(dds, &result))
302
/** @brief Does the current constraint expression return a DDS pointer?
304
This method does not evaluate the clauses, it provides information to the
305
evaluator regarding _how_ to evaluate the clause.
307
@note Added for libdap 3.11
309
@return True if the clause is a function that returns a DDS* and
315
/** @brief Does the current constraint expression contain function clauses
317
This method does not evaluate the clauses, it provides information to the
318
evaluator regarding _how_ to evaluate the clause.
320
@note Added for libdap 3.11
322
@return True if the current constraint contains function clauses,
323
otherwise returns False */
311
324
bool ConstraintEvaluator::function_clauses()
313
326
if (expr.empty())
316
329
for (unsigned int i = 0; i < expr.size(); ++i) {
317
Clause *cp = expr[i];
318
if (!cp->value_clause())
330
Clause *cp = expr[i];
331
if (!cp->value_clause())
325
338
/** @brief Evaluate a function-valued constraint expression that contains
326
several function calls.
328
This method can be called for any function-valued constraint expression.
329
Unlike eval_function(), it will package the return value in a new DDS
330
object. The server should free this object once it has been serialized
333
@note While there is another type of function that can appear in a CE (a
334
'projection function') those are evaluated by the ce parser - they are used
335
to insert new variables into the DDS as a side effect of CE evaluation.
336
That kind of function can never appear here; these are all functions that
337
return BaseType pointers.
339
@note Added for libdap 3.11 */
339
several function calls.
341
This method can be called for any function-valued constraint expression.
342
Unlike eval_function(), it will package the return value in a new DDS
343
object. The server should free this object once it has been serialized
346
@note While there is another type of function that can appear in a CE (a
347
'projection function') those are evaluated by the ce parser - they are used
348
to insert new variables into the DDS as a side effect of CE evaluation.
349
That kind of function can never appear here; these are all functions that
350
return BaseType pointers.
352
@note Added for libdap 3.11 */
341
354
ConstraintEvaluator::eval_function_clauses(DDS &dds)
343
356
if (expr.empty())
344
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
357
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
346
359
DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
347
360
for (unsigned int i = 0; i < expr.size(); ++i) {
348
Clause *cp = expr[i];
350
if (cp->value(dds, &result)) {
351
result->set_send_p(true);
352
fdds->add_var(result);
356
throw Error("A function was called but failed to return a value.");
361
Clause *cp = expr[i];
363
if (cp->value(dds, &result)) {
364
// This is correct: The function must allocate the memory for the result
365
// variable. 11/30/12 jhrg
366
fdds->add_var_nocopy(result);
370
throw Error("A function was called but failed to return a value.");
363
377
/** @brief Evaluate a function-valued constraint expression that contains
364
several function calls. Takes and returns a DataDDS.
366
@see ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
367
@note Added for libdap 3.11 */
378
several function calls. Takes and returns a DataDDS.
380
@todo Change this so that the new variables are inserted into the
381
original DDS object - this will allow constraints that mix simple
382
projections with function calls. The function is responsible for
383
setting the new variable's read_p property and this 'evaluator'
384
sets the send_p property. The original variables would have to be
385
removed from the original DDS for this to work or the names of
386
the new variables would have to not clash with the original variables'
389
@see ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
390
@note Added for libdap 3.11 */
369
392
ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
371
394
if (expr.empty())
372
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
395
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
374
DataDDS *fdds = new DataDDS(dds.get_factory(),
375
"function_result_" + dds.get_dataset_name(),
376
dds.get_version(), dds.get_protocol());
397
DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
378
400
for (unsigned int i = 0; i < expr.size(); ++i) {
379
Clause *cp = expr[i];
381
if (cp->value(dds, &result)) {
382
result->set_send_p(true);
383
fdds->add_var(result);
387
throw Error("A function was called but failed to return a value.");
401
Clause *cp = expr[i];
403
if (cp->value(dds, &result)) {
404
fdds->add_var_nocopy(result);
408
throw Error("A function was called but failed to return a value.");
394
415
/** @brief Does the current constraint expression return a boolean value? */
396
ConstraintEvaluator::boolean_expression()
416
bool ConstraintEvaluator::boolean_expression()
398
418
if (expr.empty())
410
429
/** @brief Evaluate a boolean-valued constraint expression.
411
This is main method for the evaluator ans is called by the
412
BaseType::serialize() methods.
430
This is main method for the evaluator ans is called by the
431
BaseType::serialize() methods.
414
@param dds Use these variables when evaluating the expressions.
415
@param dataset This string is passed to the read() methods.
416
@return True if the expression is true, false otherwise. */
418
ConstraintEvaluator::eval_selection(DDS &dds, const string &)
433
@param dds Use these variables when evaluating the expressions.
434
@param dataset This string is passed to the read() methods.
435
@return True if the expression is true, false otherwise. */
436
bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
420
438
if (expr.empty()) {
421
439
DBG(cerr << "No selection recorded" << endl);
443
460
/** @brief Parse the constraint expression given the current DDS.
445
Evaluate the constraint expression; return the value of the expression.
446
As a side effect, mark the DDS so that BaseType's mfuncs can be used to
447
correctly read the variable's value and send it to the client.
462
Evaluate the constraint expression; return the value of the expression.
463
As a side effect, mark the DDS so that BaseType's mfuncs can be used to
464
correctly read the variable's value and send it to the client.
449
@param constraint A string containing the constraint expression.
450
@param dds The DDS that provides the environment within which the
451
constraint is evaluated.
452
@exception Throws Error if the constraint does not parse. */
454
ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
466
@param constraint A string containing the constraint expression.
467
@param dds The DDS that provides the environment within which the
468
constraint is evaluated.
469
@exception Throws Error if the constraint does not parse. */
470
void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
456
472
void *buffer = ce_expr_string(constraint.c_str());
474
// Toggle this to debug the parser. A last resort...
475
ce_exprdebug = false;
457
477
ce_expr_switch_to_buffer(buffer);
459
479
ce_parser_arg arg(this, &dds);
461
481
// For all errors, exprparse will throw Error.
462
ce_exprparse((void *)&arg);
464
ce_expr_delete_buffer(buffer);
484
ce_expr_delete_buffer(buffer);
487
// Make sure to remove the buffer when there's an error
488
ce_expr_delete_buffer(buffer);
467
493
} // namespace libdap