libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 // The Grid Selection Expression Clause class. 00033 00034 00035 #include "config.h" 00036 00037 static char id[] not_used = 00038 {"$Id: GSEClause.cc 18282 2008-03-01 01:36:12Z jimg $" 00039 }; 00040 00041 #include <iostream> 00042 #include <sstream> 00043 00044 #include "dods-datatypes.h" 00045 #include "Error.h" 00046 #include "InternalErr.h" 00047 00048 #include "debug.h" 00049 #include "GSEClause.h" 00050 #include "parser.h" 00051 #include "gse.tab.hh" 00052 00053 using namespace std; 00054 00055 int gse_parse(void *arg); 00056 void gse_restart(FILE *in); 00057 00058 // Glue routines declared in gse.lex 00059 void gse_switch_to_buffer(void *new_buffer); 00060 void gse_delete_buffer(void * buffer); 00061 void *gse_string(const char *yy_str); 00062 00063 namespace libdap { 00064 00065 // Private methods 00066 00067 GSEClause::GSEClause() 00068 { 00069 throw InternalErr(__FILE__, __LINE__, "default ctor called for GSEClause"); 00070 } 00071 00072 GSEClause::GSEClause(const GSEClause &) 00073 { 00074 throw InternalErr(__FILE__, __LINE__, "copy ctor called for GSEClause"); 00075 } 00076 00077 GSEClause &GSEClause::operator=(GSEClause &) 00078 { 00079 throw InternalErr(__FILE__, __LINE__, "assigment called for GSEClause"); 00080 } 00081 00082 // For the comparisions here, we should use an epsilon to catch issues 00083 // with floating point values. jhrg 01/12/06 00084 template<class T> 00085 static bool 00086 compare(T elem, relop op, double value) 00087 { 00088 switch (op) { 00089 case dods_greater_op: 00090 return elem > value; 00091 case dods_greater_equal_op: 00092 return elem >= value; 00093 case dods_less_op: 00094 return elem < value; 00095 case dods_less_equal_op: 00096 return elem <= value; 00097 case dods_equal_op: 00098 return elem == value; 00099 case dods_not_equal_op: 00100 return elem != value; 00101 case dods_nop_op: 00102 throw Error(malformed_expr, "Attempt to use NOP in Grid selection."); 00103 default: 00104 throw Error(malformed_expr, "Unknown relational operator in Grid selection."); 00105 } 00106 } 00107 00108 // These values are used in error messages, hence the strings. 00109 template<class T> 00110 void 00111 GSEClause::set_map_min_max_value(T min, T max) 00112 { 00113 DBG(cerr << "Inside set map min max value " << min << ", " << max << endl); 00114 std::ostringstream oss1; 00115 oss1 << min; 00116 d_map_min_value = oss1.str(); 00117 00118 std::ostringstream oss2; 00119 oss2 << max; 00120 d_map_max_value = oss2.str(); 00121 } 00122 00123 // Read the map array, scan, set start and stop. 00124 template<class T> 00125 void 00126 GSEClause::set_start_stop() 00127 { 00128 T *vals = new T[d_map->length()]; 00129 d_map->value(vals); 00130 00131 // Set the map's max and min values for use in error messages (it's a lot 00132 // easier to do here, now, than later... 9/20/2001 jhrg) 00133 set_map_min_max_value<T>(vals[d_start], vals[d_stop]); 00134 00135 // Starting at the current start point in the map (initially index position 00136 // zero), scan forward until the comparison is true. Set the new value 00137 // of d_start to that location. Note that each clause applies to exactly 00138 // one map. The 'i <= end' test keeps us from setting start _past_ the 00139 // end ;-) 00140 int i = d_start; 00141 int end = d_stop; 00142 while (i <= end && !compare<T>(vals[i], d_op1, d_value1)) 00143 i++; 00144 00145 d_start = i; 00146 00147 // Now scan backward from the end. We scan all the way to the actual start 00148 // although it would probably work to stop at 'i >= d_start'. 00149 i = end; 00150 while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1)) 00151 i--; 00152 d_stop = i; 00153 00154 // Every clause must have one operator but the second is optional since 00155 // the more complex form of a clause is optional. That is, the above two 00156 // loops took care of constraints like 'x < 7' but we need the following 00157 // for ones like '3 < x < 7'. 00158 if (d_op2 != dods_nop_op) { 00159 int i = d_start; 00160 int end = d_stop; 00161 while (i <= end && !compare<T>(vals[i], d_op2, d_value2)) 00162 i++; 00163 00164 d_start = i; 00165 00166 i = end; 00167 while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2)) 00168 i--; 00169 00170 d_stop = i; 00171 } 00172 } 00173 00174 void 00175 GSEClause::compute_indices() 00176 { 00177 switch (d_map->var()->type()) { 00178 case dods_byte_c: 00179 set_start_stop<dods_byte>(); 00180 break; 00181 case dods_int16_c: 00182 set_start_stop<dods_int16>(); 00183 break; 00184 case dods_uint16_c: 00185 set_start_stop<dods_uint16>(); 00186 break; 00187 case dods_int32_c: 00188 set_start_stop<dods_int32>(); 00189 break; 00190 case dods_uint32_c: 00191 set_start_stop<dods_uint32>(); 00192 break; 00193 case dods_float32_c: 00194 set_start_stop<dods_float32>(); 00195 break; 00196 case dods_float64_c: 00197 set_start_stop<dods_float64>(); 00198 break; 00199 default: 00200 throw Error(malformed_expr, 00201 "Grid selection using non-numeric map vectors is not supported"); 00202 } 00203 00204 } 00205 00206 // Public methods 00207 00209 GSEClause::GSEClause(Grid *grid, const string &map, const double value, 00210 const relop op) 00211 : d_map(0), 00212 d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op), 00213 d_map_min_value(""), d_map_max_value("") 00214 { 00215 d_map = dynamic_cast<Array *>(grid->var(map)); 00216 if (!d_map) 00217 throw Error(string("The map variable '") + map 00218 + string("' does not exist in the grid '") 00219 + grid->name() + string("'.")); 00220 00221 DBG(cerr << d_map->toString()); 00222 00223 // Initialize the start and stop indices. 00224 Array::Dim_iter iter = d_map->dim_begin(); 00225 d_start = d_map->dimension_start(iter); 00226 d_stop = d_map->dimension_stop(iter); 00227 00228 compute_indices(); 00229 } 00230 00232 GSEClause::GSEClause(Grid *grid, const string &map, const double value1, 00233 const relop op1, const double value2, const relop op2) 00234 : d_map(0), 00235 d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2), 00236 d_map_min_value(""), d_map_max_value("") 00237 { 00238 d_map = dynamic_cast<Array *>(grid->var(map)); 00239 if (!d_map) 00240 throw Error(string("The map variable '") + map 00241 + string("' does not exist in the grid '") 00242 + grid->name() + string("'.")); 00243 00244 DBG(cerr << d_map->toString()); 00245 00246 // Initialize the start and stop indices. 00247 Array::Dim_iter iter = d_map->dim_begin(); 00248 d_start = d_map->dimension_start(iter); 00249 d_stop = d_map->dimension_stop(iter); 00250 00251 compute_indices(); 00252 } 00253 00256 bool 00257 GSEClause::OK() const 00258 { 00259 if (!d_map) 00260 return false; 00261 00262 // More ... 00263 00264 return true; 00265 } 00266 00269 Array * 00270 GSEClause::get_map() const 00271 { 00272 return d_map; 00273 } 00274 00279 void 00280 GSEClause::set_map(Array *map) 00281 { 00282 d_map = map; 00283 } 00284 00287 string 00288 GSEClause::get_map_name() const 00289 { 00290 return d_map->name(); 00291 } 00292 00296 int 00297 GSEClause::get_start() const 00298 { 00299 return d_start; 00300 } 00301 00304 void 00305 GSEClause::set_start(int start) 00306 { 00307 d_start = start; 00308 } 00309 00313 int 00314 GSEClause::get_stop() const 00315 { 00316 DBG(cerr << "Returning stop index value of: " << d_stop << endl); 00317 return d_stop; 00318 } 00319 00322 void 00323 GSEClause::set_stop(int stop) 00324 { 00325 d_stop = stop; 00326 } 00327 00332 string 00333 GSEClause::get_map_min_value() const 00334 { 00335 return d_map_min_value; 00336 } 00337 00342 string 00343 GSEClause::get_map_max_value() const 00344 { 00345 return d_map_max_value; 00346 } 00347 00348 } // namespace libdap 00349