libdap++ Updated for version 3.8.2

GSEClause.cc

Go to the documentation of this file.
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