38 static char rcsid[]
not_used = {
"$Id: ce_functions.cc 25915 2012-10-24 00:14:58Z jimg $" };
51 #undef FUNCTION_DAP // undef so the dap() function always returns an error;
87 double w32strtod(
const char *,
char **);
103 inline bool double_eq(
double lhs,
double rhs,
double epsilon = 1.0e-5)
106 return (lhs - rhs) < ((lhs + rhs) / epsilon);
108 return (rhs - lhs) < ((lhs + rhs) / epsilon);
125 "The CE Evaluator built an argument list where some constants held no values.");
127 string s =
dynamic_cast<Str&
> (*arg).
value();
129 DBG(cerr <<
"s: " << s << endl);
135 template<
class T>
static void set_array_using_double_helper(Array * a,
double *src,
int src_len)
137 T *values =
new T[src_len];
138 for (
int i = 0; i < src_len; ++i)
139 values[i] = (T) src[i];
142 a->val2buf(values,
true);
144 a->set_value(values, src_len);
172 throw InternalErr(__FILE__, __LINE__,
"The function requires a DAP numeric-type array argument.");
178 if (dest->
length() != src_len)
182 "The source and destination array sizes don't match (" +
long_to_string(src_len) +
" versus "
191 set_array_using_double_helper<dods_byte> (dest, src, src_len);
194 set_array_using_double_helper<dods_uint16> (dest, src, src_len);
197 set_array_using_double_helper<dods_int16> (dest, src, src_len);
200 set_array_using_double_helper<dods_uint32> (dest, src, src_len);
203 set_array_using_double_helper<dods_int32> (dest, src, src_len);
206 set_array_using_double_helper<dods_float32> (dest, src, src_len);
209 set_array_using_double_helper<dods_float64> (dest, src, src_len);
213 "The argument list built by the CE parser contained an unsupported numeric type.");
220 template<
class T>
static double *extract_double_array_helper(Array * a)
222 int length = a->length();
224 T *b =
new T[length];
227 double *dest =
new double[length];
228 for (
int i = 0; i < length; ++i)
229 dest[i] = (
double) b[i];
247 throw InternalErr(__FILE__, __LINE__,
string(
"The Array '") + a->
name() +
"'does not contain values.");
255 return extract_double_array_helper<dods_byte> (a);
257 return extract_double_array_helper<dods_uint16> (a);
259 return extract_double_array_helper<dods_int16> (a);
261 return extract_double_array_helper<dods_uint32> (a);
263 return extract_double_array_helper<dods_int32> (a);
265 return extract_double_array_helper<dods_float32> (a);
267 return extract_double_array_helper<dods_float64> (a);
270 "The argument list built by the CE parser contained an unsupported numeric type.");
289 "The CE Evaluator built an argument list where some constants held no values.");
295 switch (arg->
type()) {
297 return (
double) (
dynamic_cast<Byte&
> (*arg).
value());
299 return (
double) (
dynamic_cast<UInt16&
> (*arg).
value());
301 return (
double) (
dynamic_cast<Int16&
> (*arg).
value());
303 return (
double) (
dynamic_cast<UInt32&
> (*arg).
value());
305 return (
double) (
dynamic_cast<Int32&
> (*arg).
value());
307 return (
double) (
dynamic_cast<Float32&
> (*arg).
value());
312 "The argument list built by the CE parser contained an unsupported numeric type.");
326 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
328 <function name=\"geogrid\" version=\"1.2\"/>\
329 <function name=\"grid\" version=\"1.0\"/>\
330 <function name=\"linear_scale\" version=\"1.0b1\"/>\
331 <function name=\"version\" version=\"1.0\"/>\
332 <function name=\"dap\" version=\"1.0\"/>\
337 Str *response =
new Str(
"version");
348 throw Error(
"The 'dap' function must be called with a version number.\n\
349 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#dap");
353 dds.set_dap_version(pv);
356 "The 'dap' function is not supported in lieu of Constraint expression 'keywords.'\n\
357 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#keywords");
361 static void parse_gse_expression(gse_arg * arg, BaseType * expr)
366 bool status =
gse_parse((
void *) arg) == 0;
372 static void apply_grid_selection_expr(Grid * grid, GSEClause * clause)
376 Grid::Map_iter map_i = grid->map_begin();
377 while (map_i != grid->map_end() && (*map_i)->name() != clause->get_map_name())
380 if (map_i == grid->map_end())
382 "The map vector '" + clause->get_map_name() +
"' is not in the grid '" + grid->name() +
"'.");
385 Array::Dim_iter grid_dim = (grid->get_array()->dim_begin() + (map_i - grid->map_begin()));
387 Array *map =
dynamic_cast<Array *
> ((*map_i));
389 throw InternalErr(__FILE__, __LINE__,
"Expected an Array");
390 int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
391 int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
395 msg <<
"The expressions passed to grid() do not result in an inclusive \n" <<
"subset of '"
396 << clause->get_map_name() <<
"'. The map's values range " <<
"from " << clause->get_map_min_value()
397 <<
" to " << clause->get_map_max_value() <<
".";
401 DBG(cerr <<
"Setting constraint on " << map->name()
402 <<
"[" << start <<
":" << stop <<
"]" << endl);
405 map->add_constraint(map->dim_begin(), start, 1, stop);
406 grid->get_array()->add_constraint(grid_dim, start, 1, stop);
409 static void apply_grid_selection_expressions(Grid * grid, vector<GSEClause *> clauses)
411 vector<GSEClause *>::iterator clause_i = clauses.begin();
412 while (clause_i != clauses.end())
413 apply_grid_selection_expr(grid, *clause_i++);
415 grid->set_read_p(
false);
437 if (!(l_lat = dynamic_cast<Array *>(dds.
var(
"Latitude")))
438 || !(l_lon =
dynamic_cast<Array *
>(dds.
var(
"Latitude"))))
443 l_lat =
dynamic_cast<Array*
>(argv[0]);
444 l_lon =
dynamic_cast<Array*
>(argv[1]);
445 if (!l_lat || !l_lon)
518 DBG(cerr <<
"Entering function_grid..." << endl);
522 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
523 +
"<function name=\"grid\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#grid\">\n"
527 Str *response =
new Str(
"info");
533 Grid *original_grid =
dynamic_cast<Grid *
> (argv[0]);
540 Grid *l_grid =
dynamic_cast<Grid *
> (btp);
543 throw InternalErr(__FILE__, __LINE__,
"Expected a Grid.");
546 DBG(cerr <<
"grid: past initialization code" << endl);
556 (*i++)->set_send_p(
true);
560 DBG(cerr <<
"grid: past map read" << endl);
566 vector<GSEClause *> clauses;
568 for (
int i = 1; i < argc; ++i) {
569 parse_gse_expression(arg, argv[i]);
575 apply_grid_selection_expressions(l_grid, clauses);
577 DBG(cerr <<
"grid: past gse application" << endl);
631 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
632 +
"<function name=\"geogrid\" version=\"1.2\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid\">\n"
636 Str *response =
new Str(
"version");
651 if (argc < 1 || !(l_grid = dynamic_cast<Grid *> (argv[0]->ptr_duplicate())))
657 "Wrong number of arguments to geogrid() (expected at least 5 args). See geogrid() for more information.");
659 bool grid_lat_lon_form;
662 if (!(l_lat = dynamic_cast<Array *> (argv[1])))
663 grid_lat_lon_form =
false;
664 else if (!(l_lon = dynamic_cast<Array *> (argv[2])))
666 "When using the Grid, Lat, Lon form of geogrid() both the lat and lon maps must be given (lon map missing)!");
668 grid_lat_lon_form =
true;
670 if (grid_lat_lon_form && argc < 7)
672 "Wrong number of arguments to geogrid() (expected at least 7 args). See geogrid() for more information.");
691 (*i++)->set_send_p(
true);
698 DBG(cerr <<
"geogrid: past map read" << endl);
702 int min_arg_count = (grid_lat_lon_form) ? 7 : 5;
703 if (argc > min_arg_count) {
706 vector<GSEClause *> clauses;
708 for (
int i = min_arg_count; i < argc; ++i) {
709 parse_gse_expression(arg, argv[i]);
715 apply_grid_selection_expressions(l_grid, clauses);
725 int box_index_offset = (grid_lat_lon_form) ? 3 : 1;
731 DBG(cerr <<
"geogrid: past bounding box set" << endl);
735 DBG(cerr <<
"geogrid: past apply constraint" << endl);
743 }
catch (exception & e) {
744 throw InternalErr(
string(
"A C++ exception was thrown from inside geogrid(): ") + e.what());
753 static double string_to_double(
const char *val)
760 double v = w32strtod(val, &ptr);
762 double v = strtod(val, &ptr);
765 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE)) || *ptr !=
'\0') {
766 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
769 double abs_val = fabs(v);
771 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
785 static double get_attribute_double_value(BaseType *var, vector<string> &attributes)
789 AttrTable &attr = var->get_attr_table();
790 string attribute_value =
"";
792 vector<string>::iterator i = attributes.begin();
793 while (attribute_value ==
"" && i != attributes.end()) {
797 attribute_value = attr.get_attr(*i++);
802 if (attribute_value.empty()) {
804 return get_attribute_double_value(dynamic_cast<Grid&> (*var).get_array(), attributes);
808 string(
"No COARDS/CF '") + values.substr(0, values.length() - 2)
809 +
"' attribute was found for the variable '" + var->name() +
"'.");
812 return string_to_double(
remove_quotes(attribute_value).c_str());
815 static double get_attribute_double_value(BaseType *var,
const string &attribute)
817 AttrTable &attr = var->get_attr_table();
818 string attribute_value = attr.get_attr(attribute);
822 if (attribute_value.empty()) {
824 return get_attribute_double_value(dynamic_cast<Grid&> (*var).get_array(), attribute);
827 string(
"No COARDS '") + attribute +
"' attribute was found for the variable '" + var->name() +
"'.");
830 return string_to_double(
remove_quotes(attribute_value).c_str());
833 static double get_y_intercept(BaseType *var)
835 vector<string> attributes;
836 attributes.push_back(
"add_offset");
837 attributes.push_back(
"add_off");
838 return get_attribute_double_value(var, attributes);
841 static double get_slope(BaseType *var)
843 return get_attribute_double_value(var,
"scale_factor");
846 static double get_missing_value(BaseType *var)
848 return get_attribute_double_value(var,
"missing_value");
867 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
868 +
"<function name=\"linear_scale\" version=\"1.0b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#linear_scale\">\n"
872 Str *response =
new Str(
"info");
879 DBG(cerr <<
"argc = " << argc << endl);
880 if (!(argc == 1 || argc == 3 || argc == 4))
882 "Wrong number of arguments to linear_scale(). See linear_scale() for more information");
885 bool use_missing =
false;
886 double m, b, missing = 0.0;
893 else if (argc == 3) {
899 m = get_slope(argv[0]);
905 b = get_y_intercept(argv[0]);
914 missing = get_missing_value(argv[0]);
921 DBG(cerr <<
"m: " << m <<
", b: " << b << endl);
DBG(cerr <<
"use_missing: " << use_missing <<
", missing: " << missing << endl);
930 Array *source =
dynamic_cast<Grid*
>(argv[0])->get_array();
935 int length = source->
length();
936 for (
int i = 0; i < length; ++i)
937 data[i] = data[i] * m + b;
941 DBG2(cerr <<
"data[" << i <<
"]: " << data[i] << endl);
942 if (!use_missing || !
double_eq(data[i], missing))
943 data[i] = data[i] * m + b;
944 DBG2(cerr <<
" >> data[" << i <<
"]: " << data[i] << endl);
953 source.
val2buf(static_cast<void*>(data),
false);
963 Grid &source =
dynamic_cast<Grid&
>(*argv[0]);
965 DBG(cerr <<
"Grid send_p: " << source.
send_p() << endl);
980 for (
int i = 0; i < length; ++i)
981 data[i] = data[i] * m + b;
986 while (s != source.
map_end()) {
1006 while (s != source.
map_end()) {
1011 vector<dods_byte> v(a->
length());
1017 vector<dods_float32> v(a->
length());
1023 throw Error(
"Non-numeric Grid Map not supported by linear_scale().");
1030 DBG(cerr <<
"Grid send_p: " << result->
send_p() << endl);
1035 else if (argv[0]->is_vector_type()) {
1037 Array &source =
dynamic_cast<Array&
> (*argv[0]);
1047 int length = source.
length();
1049 while (i < length) {
1050 if (!use_missing || !
double_eq(data[i], missing))
1051 data[i] = data[i] * m + b;
1058 source.
val2buf(static_cast<void*> (data),
false);
1065 Array &source =
dynamic_cast<Array&
>(*argv[0]);
1076 int length = source.
length();
1077 for (
int i = 0; i < length; ++i)
1078 data[i] = data[i] * m + b;
1089 else if (argv[0]->is_simple_type() && !(argv[0]->type() ==
dods_str_c || argv[0]->type() ==
dods_url_c)) {
1091 if (!use_missing || !
double_eq(data, missing))
1092 data = data * m + b;
1101 throw Error(
malformed_expr,
"The linear_scale() function works only for numeric Grids, Arrays and scalars.");
1130 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
1131 "<function name=\"geoarray\" version=\"0.9b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geoarray\">\n" +
1135 Str *response =
new Str(
"version");
1136 response->set_value(info);
1141 DBG(cerr <<
"argc = " << argc << endl);
1142 if (!(argc == 5 || argc == 9 || argc == 11))
1143 throw Error(
malformed_expr,
"Wrong number of arguments to geoarray(). See geoarray() for more information.");
1146 Array *l_array = dynamic_cast < Array * >(argv[0]->ptr_duplicate());
1148 throw Error(
malformed_expr,
"The first argument to geoarray() must be an Array variable!");
1160 ArrayGeoConstraint agc(l_array);
1162 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1164 agc.apply_constraint_to_data();
1165 *btpp = agc.get_constrained_array();
1174 ArrayGeoConstraint agc (l_array, var_left, var_top, var_right, var_bottom);
1176 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1178 agc.apply_constraint_to_data();
1179 *btpp = agc.get_constrained_array();
1190 ArrayGeoConstraint agc(l_array,
1191 var_left, var_top, var_right, var_bottom,
1194 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1196 agc.apply_constraint_to_data();
1197 *btpp = agc.get_constrained_array();
1202 throw InternalErr(__FILE__, __LINE__,
"Wrong number of args to geoarray.");
1208 catch (exception & e) {
1211 (
"A C++ exception was thrown from inside geoarray(): ")
1216 throw InternalErr(__FILE__, __LINE__,
"Impossible condition in geoarray.");
virtual bool read()
Read data into a local buffer.
void gse_delete_buffer(void *buffer)
virtual bool read_p()
Has this variable been read?
virtual dods_byte value() const
void gse_restart(FILE *in)
void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
virtual bool set_value(dods_float64 val)
virtual dods_int16 value() const
virtual dods_uint32 value() const
virtual int length() const
Holds an unsigned 16-bit integer.
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
virtual BaseType * get_parent()
void * gse_string(const char *yy_str)
void register_functions(ConstraintEvaluator &ce)
string extract_string_argument(BaseType *arg)
virtual dods_uint16 value() const
BaseType * var(const string &n, BaseType::btp_stack &s)
void function_geoarray(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
virtual void value(dods_byte *b) const
Get a copy of the data held by this variable. Read data from this variable's internal storage and loa...
void set_bounding_box(double top, double left, double bottom, double right)
virtual dods_int32 value() const
virtual void set_send_p(bool state)
virtual void add_var(BaseType *bt, Part part=nil)
Holds a structure (aggregate) type.
Type type() const
Returns the type of the class instance.
virtual dods_float64 value() const
Holds a 32-bit floating point value.
void function_linear_scale(int argc, BaseType *argv[], DDS &, BaseType **btpp)
A class for software fault reporting.
virtual Grid * get_constrained_grid() const
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Holds character string data.
Map_iter map_begin()
Returns an iterator referencing the first Map vector.
void set_array_using_double(Array *dest, double *src, int src_len)
double * extract_double_array(Array *a)
virtual BaseType * ptr_duplicate()
virtual string value() const
Holds a 16-bit signed integer value.
virtual void set_send_p(bool state)
void function_grid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
void append_dim(int size, string name="")
Add a dimension of a given size.
Holds the Grid data type.
void gse_switch_to_buffer(void *new_buffer)
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer. Thrown if called for Structure, Sequence or Grid.
void function_dap(int, BaseType *[], DDS &, ConstraintEvaluator &)
virtual bool set_value(const string &value)
void function_miic_ex2(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
Array * get_array()
Returns the Grid Array. This method returns the array using an Array*, so no cast is required...
std::vector< BaseType * >::iterator Map_iter
double extract_double_value(BaseType *arg)
string name() const
Returns the name of the class instance.
virtual BaseType * ptr_duplicate()=0
string long_to_string(long val, int base)
Evaluate a constraint expression.
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
void function_version(int, BaseType *[], DDS &, BaseType **btpp)
string remove_quotes(const string &s)
void add_function(const string &name, bool_func f)
Add a boolean function to the list.
The basic data type for the DODS DAP types.
void function_geogrid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
Holds a 64-bit (double precision) floating point value.
void add_var_nocopy(BaseType *v, Part p=nil)
virtual dods_float32 value() const
virtual bool is_simple_type()
Returns true if the instance is a numeric, string or URL type variable.
virtual bool set_value(dods_byte *val, int sz)
set the value of a byte array
A class for error processing.
Holds a 32-bit unsigned integer.
A multidimensional array of identical data types.
virtual bool send_p()
Should this variable be sent?
bool double_eq(double lhs, double rhs, double epsilon=1.0e-5)
Holds a 32-bit signed integer.
virtual void apply_constraint_to_data()