39 {
"$Id: ce_functions.cc 24370 2011-03-28 16:21:32Z jimg $"
52 #undef FUNCTION_DAP // undef so the dap() function always returns an error;
88 double w32strtod(
const char *,
char **);
104 inline bool double_eq(
double lhs,
double rhs,
double epsilon = 1.0e-5)
107 return (lhs - rhs) < ((lhs + rhs) / epsilon);
109 return (rhs - lhs) < ((lhs + rhs) / epsilon);
123 "The function requires a DAP string argument.");
127 "The CE Evaluator built an argument list where some constants held no values.");
129 string s =
dynamic_cast<Str&
>(*arg).
value();
131 DBG(cerr <<
"s: " << s << endl);
136 template<
class T>
static void set_array_using_double_helper(Array * a,
137 double *src,
int src_len)
139 T *values =
new T[src_len];
140 for (
int i = 0; i < src_len; ++i)
141 values[i] = (T) src[i];
144 a->val2buf(values,
true);
146 a->set_value(values, src_len);
176 "The function requires a DAP numeric-type array argument.");
182 if (dest->
length() != src_len)
184 "The source and destination array sizes don't match ("
194 set_array_using_double_helper<dods_byte>(dest, src, src_len);
197 set_array_using_double_helper<dods_uint16>(dest, src, src_len);
200 set_array_using_double_helper<dods_int16>(dest, src, src_len);
203 set_array_using_double_helper<dods_uint32>(dest, src, src_len);
206 set_array_using_double_helper<dods_int32>(dest, src, src_len);
209 set_array_using_double_helper<dods_float32>(dest, src, src_len);
212 set_array_using_double_helper<dods_float64>(dest, src, src_len);
216 "The argument list built by the CE parser contained an unsupported numeric type.");
223 template<
class T>
static double *extract_double_array_helper(Array * a)
225 int length = a->length();
227 T *b =
new T[length];
230 double *dest =
new double[length];
231 for (
int i = 0; i < length; ++i)
232 dest[i] = (
double) b[i];
248 "The function requires a DAP numeric-type array argument.");
252 string(
"The Array '") + a->
name() +
253 "'does not contain values.");
261 return extract_double_array_helper<dods_byte>(a);
263 return extract_double_array_helper<dods_uint16>(a);
265 return extract_double_array_helper<dods_int16>(a);
267 return extract_double_array_helper<dods_uint32>(a);
269 return extract_double_array_helper<dods_int32>(a);
271 return extract_double_array_helper<dods_float32>(a);
273 return extract_double_array_helper<dods_float64>(a);
276 "The argument list built by the CE parser contained an unsupported numeric type.");
293 "The function requires a DAP numeric-type argument.");
297 "The CE Evaluator built an argument list where some constants held no values.");
303 switch (arg->
type()) {
305 return (
double)(
dynamic_cast<Byte&
>(*arg).
value());
307 return (
double)(
dynamic_cast<UInt16&
>(*arg).
value());
309 return (
double)(
dynamic_cast<Int16&
>(*arg).
value());
311 return (
double)(
dynamic_cast<UInt32&
>(*arg).
value());
313 return (
double)(
dynamic_cast<Int32&
>(*arg).
value());
320 "The argument list built by the CE parser contained an unsupported numeric type.");
335 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
337 <function name=\"geogrid\" version=\"1.2\"/>\
338 <function name=\"grid\" version=\"1.0\"/>\
339 <function name=\"linear_scale\" version=\"1.0b1\"/>\
340 <function name=\"version\" version=\"1.0\"/>\
341 <function name=\"dap\" version=\"1.0\"/>\
346 Str *response =
new Str(
"version");
358 throw Error(
"The 'dap' function must be called with a version number.\n\
359 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#dap");
363 dds.set_dap_version(pv);
365 throw Error(
"The 'dap' function is not supported in lieu of Constraint expression 'keywords.'\n\
366 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#keywords");
370 static void parse_gse_expression(gse_arg * arg, BaseType * expr)
375 bool status =
gse_parse((
void *) arg) == 0;
381 static void apply_grid_selection_expr(Grid * grid, GSEClause * clause)
385 Grid::Map_iter map_i = grid->map_begin();
386 while (map_i != grid->map_end() && (*map_i)->name() != clause->get_map_name())
389 if (map_i == grid->map_end())
390 throw Error(
malformed_expr,
"The map vector '" + clause->get_map_name()
391 +
"' is not in the grid '" + grid->name() +
"'.");
394 Array::Dim_iter grid_dim = (grid->get_array()->dim_begin() + (map_i - grid->map_begin()));
396 Array *map = dynamic_cast < Array * >((*map_i));
398 throw InternalErr(__FILE__, __LINE__,
"Expected an Array");
399 int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
400 int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
405 <<
"The expressions passed to grid() do not result in an inclusive \n"
406 <<
"subset of '" << clause->get_map_name()
407 <<
"'. The map's values range " <<
"from "
408 << clause->get_map_min_value() <<
" to "
409 << clause->get_map_max_value() <<
".";
413 DBG(cerr <<
"Setting constraint on " << map->name()
414 <<
"[" << start <<
":" << stop <<
"]" << endl);
417 map->add_constraint(map->dim_begin(), start, 1, stop);
418 grid->get_array()->add_constraint(grid_dim, start, 1, stop);
421 static void apply_grid_selection_expressions(Grid * grid,
422 vector < GSEClause * >clauses)
424 vector < GSEClause * >::iterator clause_i = clauses.begin();
425 while (clause_i != clauses.end())
426 apply_grid_selection_expr(grid, *clause_i++);
428 grid->set_read_p(
false);
470 DBG(cerr <<
"Entering function_grid..." << endl);
473 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
474 "<function name=\"grid\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#grid\">\n" +
478 Str *response =
new Str(
"info");
484 Grid *original_grid = dynamic_cast <
Grid * >(argv[0]);
491 Grid *l_grid = dynamic_cast <
Grid * >(btp);
494 throw InternalErr(__FILE__, __LINE__,
"Expected a Grid.");
497 DBG(cerr <<
"grid: past initialization code" << endl);
507 (*i++)->set_send_p(
true);
510 DBG(cerr <<
"grid: past map read" << endl);
516 vector < GSEClause * > clauses;
518 for (
int i = 1; i < argc; ++i) {
519 parse_gse_expression(arg, argv[i]);
525 apply_grid_selection_expressions(l_grid, clauses);
527 DBG(cerr <<
"grid: past gse application" << endl);
575 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
576 "<function name=\"geogrid\" version=\"1.2\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid\">\n"+
580 Str *response =
new Str(
"version");
595 if (argc < 1 || !(l_grid = dynamic_cast < Grid * >(argv[0]->ptr_duplicate())))
600 throw Error(
malformed_expr,
"Wrong number of arguments to geogrid() (expected at least 5 args). See geogrid() for more information.");
602 bool grid_lat_lon_form;
605 if (!(l_lat = dynamic_cast < Array * >(argv[1])))
606 grid_lat_lon_form =
false;
607 else if (!(l_lon = dynamic_cast < Array * >(argv[2])))
608 throw Error(
malformed_expr,
"When using the Grid, Lat, Lon form of geogrid() both the lat and lon maps must be given (lon map missing)!");
610 grid_lat_lon_form =
true;
612 if (grid_lat_lon_form && argc < 7)
613 throw Error(
malformed_expr,
"Wrong number of arguments to geogrid() (expected at least 7 args). See geogrid() for more information.");
632 (*i++)->set_send_p(
true);
639 DBG(cerr <<
"geogrid: past map read" << endl);
643 int min_arg_count = (grid_lat_lon_form) ? 7 : 5;
644 if (argc > min_arg_count) {
647 vector < GSEClause * > clauses;
649 for (
int i = min_arg_count; i < argc; ++i) {
650 parse_gse_expression(arg, argv[i]);
656 apply_grid_selection_expressions(l_grid, clauses);
666 int box_index_offset = (grid_lat_lon_form) ? 3 : 1;
672 DBG(cerr <<
"geogrid: past bounding box set" << endl);
676 DBG(cerr <<
"geogrid: past apply constraint" << endl);
686 catch (exception & e) {
689 (
"A C++ exception was thrown from inside geogrid(): ")
699 static double string_to_double(
const char *val)
706 double v = w32strtod(val, &ptr);
708 double v = strtod(val, &ptr);
711 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
713 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
716 double abs_val = fabs(v);
718 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
732 static double get_attribute_double_value(BaseType *var,
733 vector<string> &attributes)
737 AttrTable &attr = var->get_attr_table();
738 string attribute_value =
"";
740 vector<string>::iterator i = attributes.begin();
741 while (attribute_value ==
"" && i != attributes.end()) {
745 attribute_value = attr.get_attr(*i++);
750 if (attribute_value.empty()) {
752 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attributes);
754 throw Error(
malformed_expr,
string(
"No COARDS/CF '") + values.substr(0, values.length() - 2)
755 +
"' attribute was found for the variable '"
756 + var->name() +
"'.");
759 return string_to_double(
remove_quotes(attribute_value).c_str());
762 static double get_attribute_double_value(BaseType *var,
const string &attribute)
764 AttrTable &attr = var->get_attr_table();
765 string attribute_value = attr.get_attr(attribute);
769 if (attribute_value.empty()) {
771 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attribute);
774 +
"' attribute was found for the variable '"
775 + var->name() +
"'.");
778 return string_to_double(
remove_quotes(attribute_value).c_str());
781 static double get_y_intercept(BaseType *var)
783 vector<string> attributes;
784 attributes.push_back(
"add_offset");
785 attributes.push_back(
"add_off");
786 return get_attribute_double_value(var, attributes);
789 static double get_slope(BaseType *var)
791 return get_attribute_double_value(var,
"scale_factor");
794 static double get_missing_value(BaseType *var)
796 return get_attribute_double_value(var,
"missing_value");
815 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
816 "<function name=\"linear_scale\" version=\"1.0b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#linear_scale\">\n" +
820 Str *response =
new Str(
"info");
827 DBG(cerr <<
"argc = " << argc << endl);
828 if (!(argc == 1 || argc == 3 || argc == 4))
829 throw Error(
malformed_expr,
"Wrong number of arguments to linear_scale(). See linear_scale() for more information");
832 bool use_missing =
false;
833 double m, b, missing = 0.0;
839 }
else if (argc == 3) {
844 m = get_slope(argv[0]);
850 b = get_y_intercept(argv[0]);
860 missing = get_missing_value(argv[0]);
868 DBG(cerr <<
"m: " << m <<
", b: " << b << endl);
DBG(cerr <<
"use_missing: " << use_missing <<
", missing: " << missing << endl);
875 Array &source = *
dynamic_cast<Grid&
>(*argv[0]).get_array();
879 int length = source.
length();
882 DBG2(cerr <<
"data[" << i <<
"]: " << data[i] << endl);
883 if (!use_missing || !
double_eq(data[i], missing))
884 data[i] = data[i] * m + b;
885 DBG2(cerr <<
" >> data[" << i <<
"]: " << data[i] << endl);
893 source.
val2buf(static_cast<void*>(data),
false);
900 }
else if (argv[0]->is_vector_type()) {
901 Array &source =
dynamic_cast<Array&
>(*argv[0]);
911 int length = source.
length();
914 if (!use_missing || !
double_eq(data[i], missing))
915 data[i] = data[i] * m + b;
922 source.
val2buf(static_cast<void*>(data),
false);
928 }
else if (argv[0]->is_simple_type() && !(argv[0]->type() ==
dods_str_c
931 if (!use_missing || !
double_eq(data, missing))
934 dest =
new Float64(argv[0]->name());
936 dest->
val2buf(static_cast<void*>(&data));
939 throw Error(
malformed_expr,
"The linear_scale() function works only for numeric Grids, Arrays and scalars.");
968 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
969 "<function name=\"geoarray\" version=\"0.9b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geoarray\">\n" +
973 Str *response =
new Str(
"version");
974 response->set_value(info);
979 DBG(cerr <<
"argc = " << argc << endl);
980 if (!(argc == 5 || argc == 9 || argc == 11))
981 throw Error(
malformed_expr,
"Wrong number of arguments to geoarray(). See geoarray() for more information.");
984 Array *l_array = dynamic_cast < Array * >(argv[0]->ptr_duplicate());
986 throw Error(
malformed_expr,
"The first argument to geoarray() must be an Array variable!");
998 ArrayGeoConstraint agc(l_array);
1000 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1002 agc.apply_constraint_to_data();
1003 *btpp = agc.get_constrained_array();
1012 ArrayGeoConstraint agc (l_array, var_left, var_top, var_right, var_bottom);
1014 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1016 agc.apply_constraint_to_data();
1017 *btpp = agc.get_constrained_array();
1028 ArrayGeoConstraint agc(l_array,
1029 var_left, var_top, var_right, var_bottom,
1032 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1034 agc.apply_constraint_to_data();
1035 *btpp = agc.get_constrained_array();
1040 throw InternalErr(__FILE__, __LINE__,
"Wrong number of args to geoarray.");
1046 catch (exception & e) {
1049 (
"A C++ exception was thrown from inside geoarray(): ")
1054 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 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
void function_geoarray(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
void set_bounding_box(double top, double left, double bottom, double right)
virtual dods_int32 value() const
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.
void function_grid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
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)
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)
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
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.
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.
bool double_eq(double lhs, double rhs, double epsilon=1.0e-5)
Holds a 32-bit signed integer.
virtual void apply_constraint_to_data()