|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "ServerFunctionsList.h"
|
|
Packit |
a4aae4 |
#include "ConstraintEvaluator.h"
|
|
Packit |
a4aae4 |
#include "Clause.h"
|
|
Packit |
a4aae4 |
#include "DataDDS.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "ce_parser.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "parser.h"
|
|
Packit |
a4aae4 |
#include "expr.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
struct yy_buffer_state;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int ce_exprparse(libdap::ce_parser_arg *arg);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Glue routines declared in expr.lex
|
|
Packit |
a4aae4 |
void ce_expr_switch_to_buffer(void *new_buffer);
|
|
Packit |
a4aae4 |
void ce_expr_delete_buffer(void * buffer);
|
|
Packit |
a4aae4 |
void *ce_expr_string(const char *yy_str);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
extern int ce_exprdebug;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ConstraintEvaluator::ConstraintEvaluator()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Functions are now held in BES modules. jhrg 1/30/13
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// modules load functions to this list; this class searches the list
|
|
Packit |
a4aae4 |
// instead of having it's own copy. This is very similar to the BES'
|
|
Packit |
a4aae4 |
// various List classes, but this one is part of libdap and not the
|
|
Packit |
a4aae4 |
// BES. The List class is a singleton, so each function module can
|
|
Packit |
a4aae4 |
// register it's functions to the list object.
|
|
Packit |
a4aae4 |
d_functions_list = ServerFunctionsList::TheList();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ConstraintEvaluator::~ConstraintEvaluator()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// delete all the constants created by the parser for CE evaluation
|
|
Packit |
a4aae4 |
for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
|
|
Packit |
a4aae4 |
BaseType *btp = *j;
|
|
Packit |
a4aae4 |
delete btp;
|
|
Packit |
a4aae4 |
btp = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
|
|
Packit |
a4aae4 |
Clause *cp = *k;
|
|
Packit |
a4aae4 |
delete cp;
|
|
Packit |
a4aae4 |
cp = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the first clause in a parsed constraint expression. */
|
|
Packit |
a4aae4 |
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return expr.begin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns a reference to the end of the list of clauses in a parsed
|
|
Packit |
a4aae4 |
constraint expression. It does not reference the last clause */
|
|
Packit |
a4aae4 |
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return expr.end();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the value of the indicated clause of a constraint
|
|
Packit |
a4aae4 |
expression. */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return (*iter)->value(dds);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Add a clause to a constraint expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This function adds an operator clause to the constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param op An integer indicating the operator in use. These
|
|
Packit |
a4aae4 |
values are generated by \c bison.
|
|
Packit |
a4aae4 |
@param arg1 A pointer to the argument on the left side of the
|
|
Packit |
a4aae4 |
operator.
|
|
Packit |
a4aae4 |
@param arg2 A pointer to a list of the arguments on the right
|
|
Packit |
a4aae4 |
side of the operator.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Clause *clause = new Clause(op, arg1, arg2);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
expr.push_back(clause);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Add a clause to a constraint expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This function adds a boolean function clause to the constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param func A pointer to a boolean function from the list of
|
|
Packit |
a4aae4 |
supported functions.
|
|
Packit |
a4aae4 |
@param args A list of arguments to that function.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Clause *clause = new Clause(func, args);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
expr.push_back(clause);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Add a clause to a constraint expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This function adds a real-valued (BaseType) function clause to
|
|
Packit |
a4aae4 |
the constraint expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param func A pointer to a BaseType function from the list of
|
|
Packit |
a4aae4 |
supported functions.
|
|
Packit |
a4aae4 |
@param args A list of arguments to that function.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Clause *clause = new Clause(func, args);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
expr.push_back(clause);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The Constraint Evaluator maintains a list of BaseType pointers for all the
|
|
Packit |
a4aae4 |
constants that the constraint expression parser generates. These objects
|
|
Packit |
a4aae4 |
are deleted by the Constraint Evaluator destructor. Note that there are no
|
|
Packit |
a4aae4 |
list accessors; these constants are never accessed from the list. The list
|
|
Packit |
a4aae4 |
is simply a convenient way to make sure the constants are disposed of
|
|
Packit |
a4aae4 |
properly.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void ConstraintEvaluator::append_constant(BaseType *btp)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
constants.push_back(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Find a Boolean function with a given name in the function list. */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_functions_list->find_function(name, f);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Find a BaseType function with a given name in the function list. */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_functions_list->find_function(name, f);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Find a projection function with a given name in the function list. */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_functions_list->find_function(name, f);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Does the current constraint expression return a BaseType
|
|
Packit |
a4aae4 |
pointer?
|
|
Packit |
a4aae4 |
This method does not evaluate the clause, it provides information to the
|
|
Packit |
a4aae4 |
evaluator regarding _how_ to evaluate the clause.
|
|
Packit |
a4aae4 |
@return True if the clause is a function that returns a BaseType* and
|
|
Packit |
a4aae4 |
false otherwise
|
|
Packit |
a4aae4 |
@deprecated
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::functional_expression()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Clause *cp = expr[0];
|
|
Packit |
a4aae4 |
return cp->value_clause();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Evaluate a function-valued constraint expression.
|
|
Packit |
a4aae4 |
* @deprecated
|
|
Packit |
a4aae4 |
* */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
ConstraintEvaluator::eval_function(DDS &dds, const string &)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.size() != 1)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Clause *cp = expr[0];
|
|
Packit |
a4aae4 |
BaseType *result;
|
|
Packit |
a4aae4 |
if (cp->value(dds, &result))
|
|
Packit |
a4aae4 |
return result;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return NULL;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Does the current constraint expression contain function clauses
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This method does not evaluate the clauses, it provides information to the
|
|
Packit |
a4aae4 |
evaluator regarding _how_ to evaluate the clause.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Added for libdap 3.11
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return True if the current constraint contains function clauses,
|
|
Packit |
a4aae4 |
otherwise returns False */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::function_clauses()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (unsigned int i = 0; i < expr.size(); ++i) {
|
|
Packit |
a4aae4 |
Clause *cp = expr[i];
|
|
Packit |
a4aae4 |
if (!cp->value_clause())
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Evaluate a function-valued constraint expression that contains
|
|
Packit |
a4aae4 |
several function calls.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This method can be called for any function-valued constraint expression.
|
|
Packit |
a4aae4 |
Unlike eval_function(), it will package the return value in a new DDS
|
|
Packit |
a4aae4 |
object. The server should free this object once it has been serialized
|
|
Packit |
a4aae4 |
and sent.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note While there is another type of function that can appear in a CE (a
|
|
Packit |
a4aae4 |
'projection function') those are evaluated by the ce parser - they are used
|
|
Packit |
a4aae4 |
to insert new variables into the DDS as a side effect of CE evaluation.
|
|
Packit |
a4aae4 |
That kind of function can never appear here; these are all functions that
|
|
Packit |
a4aae4 |
return BaseType pointers.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Added for libdap 3.11 */
|
|
Packit |
a4aae4 |
DDS *
|
|
Packit |
a4aae4 |
ConstraintEvaluator::eval_function_clauses(DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
|
|
Packit |
a4aae4 |
for (unsigned int i = 0; i < expr.size(); ++i) {
|
|
Packit |
a4aae4 |
Clause *cp = expr[i];
|
|
Packit |
a4aae4 |
BaseType *result;
|
|
Packit |
a4aae4 |
if (cp->value(dds, &result)) {
|
|
Packit |
a4aae4 |
// This is correct: The function must allocate the memory for the result
|
|
Packit |
a4aae4 |
// variable. 11/30/12 jhrg
|
|
Packit |
a4aae4 |
fdds->add_var_nocopy(result);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
delete fdds;
|
|
Packit |
a4aae4 |
throw Error(internal_error, "A function was called but failed to return a value.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return fdds;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Evaluate a function-valued constraint expression that contains
|
|
Packit |
a4aae4 |
several function calls. Takes and returns a DataDDS.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
|
|
Packit |
a4aae4 |
@note Added for libdap 3.11 */
|
|
Packit |
a4aae4 |
DataDDS *
|
|
Packit |
a4aae4 |
ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
|
|
Packit |
a4aae4 |
dds.get_protocol());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (unsigned int i = 0; i < expr.size(); ++i) {
|
|
Packit |
a4aae4 |
Clause *cp = expr[i];
|
|
Packit |
a4aae4 |
BaseType *result;
|
|
Packit |
a4aae4 |
if (cp->value(dds, &result)) {
|
|
Packit |
a4aae4 |
fdds->add_var_nocopy(result);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
delete fdds;
|
|
Packit |
a4aae4 |
throw Error(internal_error, "A function was called but failed to return a value.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return fdds;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Does the current constraint expression return a boolean value? */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::boolean_expression()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty())
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool boolean = true;
|
|
Packit |
a4aae4 |
for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
|
|
Packit |
a4aae4 |
boolean = boolean && (*i)->boolean_clause();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return boolean;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Evaluate a boolean-valued constraint expression.
|
|
Packit |
a4aae4 |
This is main method for the evaluator and is called by the
|
|
Packit |
a4aae4 |
BaseType::serialize() methods.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param dds Use these variables when evaluating the expressions.
|
|
Packit |
a4aae4 |
@param dataset This string is passed to the read() methods.
|
|
Packit |
a4aae4 |
@return True if the expression is true, false otherwise. */
|
|
Packit |
a4aae4 |
bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (expr.empty()) {
|
|
Packit |
a4aae4 |
DBG(cerr << "No selection recorded" << endl);
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Eval selection" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// A CE is made up of zero or more clauses, each of which has a boolean
|
|
Packit |
a4aae4 |
// value. The value of the CE is the logical AND of the clause
|
|
Packit |
a4aae4 |
// values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
|
|
Packit |
a4aae4 |
// CEs.
|
|
Packit |
a4aae4 |
bool result = true;
|
|
Packit |
a4aae4 |
for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
|
|
Packit |
a4aae4 |
// A selection expression *must* contain only boolean clauses!
|
|
Packit |
a4aae4 |
if (!((*i)->boolean_clause()))
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
|
|
Packit |
a4aae4 |
result = result && (*i)->value(dds);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return result;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Parse the constraint expression given the current DDS.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Evaluate the constraint expression; return the value of the expression.
|
|
Packit |
a4aae4 |
As a side effect, mark the DDS so that BaseType's mfuncs can be used to
|
|
Packit |
a4aae4 |
correctly read the variable's value and send it to the client.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param constraint A string containing the constraint expression.
|
|
Packit |
a4aae4 |
@param dds The DDS that provides the environment within which the
|
|
Packit |
a4aae4 |
constraint is evaluated.
|
|
Packit |
a4aae4 |
@exception Throws Error if the constraint does not parse. */
|
|
Packit |
a4aae4 |
void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
void *buffer = ce_expr_string(constraint.c_str());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Toggle this to debug the parser. A last resort...
|
|
Packit |
a4aae4 |
ce_exprdebug = false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ce_expr_switch_to_buffer(buffer);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ce_parser_arg arg(this, &dds;;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// For all errors, exprparse will throw Error.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
ce_exprparse(&arg;;
|
|
Packit |
a4aae4 |
ce_expr_delete_buffer(buffer);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
// Make sure to remove the buffer when there's an error
|
|
Packit |
a4aae4 |
ce_expr_delete_buffer(buffer);
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|