31#include "D4CEScanner.h"
32#include "D4ConstraintEvaluator.h"
33#include "d4_ce_parser.tab.hh"
37#include "D4Dimensions.h"
41#include "Constructor.h"
42#include "D4Sequence.h"
45#include "D4FilterClause.h"
52#define PREVENT_XXS_VIA_CE 1
53#if NDEBUG && !PREVENT_XXS_VIA_CE
54#error("Never release libdap with PREVENT_XXS_VIA_CE turned off")
59bool D4ConstraintEvaluator::parse(
const std::string &expr)
64 DBG(cerr <<
"Entering D4ConstraintEvaluator::parse: " << endl);
65 DBG(cerr <<
"Entering D4ConstraintEvaluator::expr: " << expr <<endl);
66 std::istringstream iss(expr);
67 D4CEScanner scanner(iss);
68 D4CEParser parser(scanner, *
this );
70 if (trace_parsing()) {
71 parser.set_debug_level(1);
72 parser.set_debug_stream(std::cerr);
76 d_dmr->set_ce_empty(
true);
78 return parser.parse() == 0;
87void D4ConstraintEvaluator::throw_not_found(
const string &,
const string &)
90 throw Error(no_such_variable,
string(
"The constraint expression referenced a variable that was not found in the dataset."));
92 throw Error(no_such_variable, d_expr +
": The variable " +
id +
" was not found in the dataset (" + ident +
").");
96void D4ConstraintEvaluator::throw_not_array(
const string &,
const string &)
99 throw Error(no_such_variable,
string(
"The constraint expression referenced an Array that was not found in the dataset."));
101 throw Error(no_such_variable, d_expr +
": The variable '" +
id +
"' is not an Array variable (" + ident +
").");
105void D4ConstraintEvaluator::search_for_and_mark_arrays(
BaseType *btp)
107 DBG(cerr <<
"Entering D4ConstraintEvaluator::search_for_and_mark_arrays...(" << btp->name() <<
")" << endl);
109 assert(btp->is_constructor_type());
111 Constructor *ctor =
static_cast<Constructor*
>(btp);
112 for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) {
113 switch ((*i)->type()) {
115 DBG(cerr <<
"Found an array: " << (*i)->name() << endl);
116 mark_array_variable(*i);
118 case dods_structure_c:
119 case dods_sequence_c:
120 DBG(cerr <<
"Found a ctor: " << (*i)->name() << endl);
121 search_for_and_mark_arrays(*i);
139D4ConstraintEvaluator::mark_variable(
BaseType *btp)
143 DBG(cerr <<
"In D4ConstraintEvaluator::mark_variable... (" << btp->name() <<
"; " << btp->type_name() <<
")" << endl);
145 btp->set_send_p(
true);
147 if (btp->type() == dods_array_c) {
148 mark_array_variable(btp);
152 if (btp->is_constructor_type()) {
153 search_for_and_mark_arrays(btp);
155 else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) {
156 search_for_and_mark_arrays(btp->var());
160 BaseType *parent = btp->get_parent();
162 parent->BaseType::set_send_p(
true);
163 parent = parent->get_parent();
171 for (
Array::Dim_iter d = map->dim_begin(), e = map->dim_end(); d != e; ++d) {
172 if (source_dim->name() == (*d).name)
return true;
194D4ConstraintEvaluator::mark_array_variable(
BaseType *btp)
196 assert(btp->type() == dods_array_c);
198 Array *a =
static_cast<Array*
>(btp);
203 if (d_indexes.empty()) {
204 for (
Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) {
205 D4Dimension *dim = a->dimension_D4dim(d);
207 a->add_constraint(d, dim);
213 if (d_indexes.size() != a->dimensions())
214 throw Error(malformed_expr,
"The index constraint for '" + btp->name() +
"' does not match its rank.");
218 DBG(cerr <<
"dimension size " << a->dimension_size_ll(d,
false) << endl);
220 for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
222 if ((*i).stride > (
unsigned long long) (a->dimension_stop(d,
false) - a->dimension_start(d,
false)) + 1)
224 if ((*i).stride > (
unsigned long long) (a->dimension_stop_ll(d,
false) - a->dimension_start_ll(d,
false)) + 1)
225 throw Error(malformed_expr,
226 "For '" + btp->name()
227 +
"', the index stride value is greater than the number of elements in the Array");
229 && ((*i).stop) > (
unsigned long long) (a->dimension_stop_ll(d,
false) - a->dimension_start_ll(d,
false)) + 1)
231 && ((*i).stop) > (
unsigned long long) (a->dimension_stop(d,
false) - a->dimension_start(d,
false)) + 1)
233 throw Error(malformed_expr,
234 "For '" + btp->name()
235 +
"', the index stop value is greater than the number of elements in the Array");
237 D4Dimension *dim = a->dimension_D4dim(d);
244 if (dim && (*i).empty) {
248 a->add_constraint(d, dim);
257 DBG(cerr <<
"Entering: LOCAL D4 constraint" << endl);
260 a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
262 a->add_constraint_ll(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
273 if (!a->maps()->empty()) {
274 int map_size = a->maps()->size();
280 for (
int map_index = 0; map_index <map_size; map_index++) {
281 for (D4Maps::D4MapsIter m = a->maps()->map_begin(), e = a->maps()->map_end(); m != e; ++m) {
283 if ((*m)->array() == 0)
284 throw Error(malformed_expr,
285 "An array with Maps was found, but one of the Maps was not defined correctly.");
287 auto root =
dynamic_cast<D4Group*
>(a->get_ancestor());
289 throw InternalErr(__FILE__, __LINE__,
"Expected a valid ancestor Group.");
290 auto *map = (*m)->array(root);
294 if (dim && array_uses_shared_dimension(map, dim)) {
295 D4Map *map_to_be_removed = *m;
296 a->maps()->remove_map(map_to_be_removed);
297 delete map_to_be_removed;
323D4ConstraintEvaluator::slice_dimension(
const std::string &
id,
const index &i)
325 D4Dimension *dim = dmr()->root()->find_dim(
id);
327 if (i.stride > dim->size())
328 throw Error(malformed_expr,
329 "For '" +
id +
"', the index stride value is greater than the size of the dimension");
330 if (!i.rest && (i.stop > dim->size() - 1))
331 throw Error(malformed_expr,
"For '" +
id +
"', the index stop value is greater than the size of the dimension");
333 dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1 : i.stop);
338D4ConstraintEvaluator::index D4ConstraintEvaluator::make_index(
const std::string &i)
340 unsigned long long v = get_uint64(i.c_str());
341 return index(v, 1, v,
false,
false ,
"");
344D4ConstraintEvaluator::index D4ConstraintEvaluator::make_index(
const std::string &i,
const std::string &s,
345 const std::string &e)
347 int64_t initial = get_uint64(i.c_str());
348 int64_t end = get_uint64(e.c_str());
350 throw Error(malformed_expr,
string(
"The start value of an array index is past the stop value."));
352 return index(initial, get_uint64(s.c_str()), end,
false,
false ,
"");
355D4ConstraintEvaluator::index D4ConstraintEvaluator::make_index(
const std::string &i,
unsigned long long s,
356 const std::string &e)
358 int64_t initial = get_uint64(i.c_str());
359 int64_t end = get_uint64(e.c_str());
361 throw Error(malformed_expr,
string(
"The start value of an array index is past the stop value."));
363 return index(initial, s, end,
false,
false ,
"");
366D4ConstraintEvaluator::index D4ConstraintEvaluator::make_index(
const std::string &i,
const std::string &s)
368 return index(get_uint64(i.c_str()), get_uint64(s.c_str()), 0,
true,
false ,
"");
371D4ConstraintEvaluator::index D4ConstraintEvaluator::make_index(
const std::string &i,
unsigned long long s)
373 return index(get_uint64(i.c_str()), s, 0,
true,
false ,
"");
376static string expr_msg(
const std::string &op,
const std::string &arg1,
const std::string &arg2)
378 return "(" + arg1 +
" " + op +
" " + arg2 +
").";
398static D4FilterClause::ops get_op_code(
const std::string &op)
400 DBGN(cerr <<
"Entering " << __PRETTY_FUNCTION__ << endl <<
"op: " << op << endl);
403 return D4FilterClause::less;
405 return D4FilterClause::greater;
407 return D4FilterClause::less_equal;
409 return D4FilterClause::greater_equal;
411 return D4FilterClause::equal;
413 return D4FilterClause::not_equal;
415 return D4FilterClause::match;
417 throw Error(malformed_expr,
"The opertator '" + op +
"' is not supported.");
441void D4ConstraintEvaluator::add_filter_clause(
const std::string &op,
const std::string &arg1,
const std::string &arg2)
443 DBG(cerr <<
"Entering: " << __PRETTY_FUNCTION__ << endl);
446 D4Sequence *s =
dynamic_cast<D4Sequence*
>(top_basetype());
448 throw Error(malformed_expr,
449 "When a filter expression is used, it must be bound to a Sequence variable: " + expr_msg(op, arg1, arg2));
451 DBG(cerr <<
"s->name(): " << s->name() << endl);
454 BaseType *a1 = s->var(arg1);
455 BaseType *a2 = s->var(arg2);
456 DBG(cerr <<
"a1: " << a1 <<
", a2: " << a2 << endl);
459 throw Error(malformed_expr,
460 "One of the arguments in a filter expression must be a constant: " + expr_msg(op, arg1, arg2));
462 throw Error(malformed_expr,
463 "One of the arguments in a filter expression must be a variable in a Sequence: "
464 + expr_msg(op, arg1, arg2));
468 s->clauses().add_clause(
new D4FilterClause(get_op_code(op),
new D4RValue(a1),
D4RValueFactory(arg2)));
471 s->clauses().add_clause(
new D4FilterClause(get_op_code(op),
D4RValueFactory(arg1),
new D4RValue(a2)));
482D4ConstraintEvaluator::remove_quotes(
string &s)
484 if (*s.begin() ==
'\"' && *(s.end() - 1) ==
'\"') {
486 s.erase(s.end() - 1);
498void D4ConstraintEvaluator::error(
const libdap::location &,
const std::string &m)
501#if PREVENT_XXS_VIA_CE
502 oss <<
"Constraint expression parse error: " << m << ends;
504 oss << l <<
": " << m << ends;
506 throw Error(malformed_expr, oss.str());
A multidimensional array of identical data types.
std::vector< dimension >::iterator Dim_iter
The basic data type for the DODS DAP types.
A class for error processing.
top level DAP object to house generic methods
D4RValue * D4RValueFactory(std::string cpps)
Build an appropriate RValue.