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 16967 2007-08-20 23:39:01Z 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.h"
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 // Private methods
00064 
00065 GSEClause::GSEClause()
00066 {
00067     throw InternalErr(__FILE__, __LINE__, "default ctor called for GSEClause");
00068 }
00069 
00070 GSEClause::GSEClause(const GSEClause &)
00071 {
00072     throw InternalErr(__FILE__, __LINE__, "copy ctor called for GSEClause");
00073 }
00074 
00075 GSEClause &GSEClause::operator=(GSEClause &)
00076 {
00077     throw InternalErr(__FILE__, __LINE__, "assigment called for GSEClause");
00078 }
00079 
00080 // For the comparisions here, we should use an epsilon to catch issues
00081 // with floating point values. jhrg 01/12/06
00082 template<class T>
00083 static bool
00084 compare(T elem, relop op, double value)
00085 {
00086     switch (op) {
00087     case dods_greater_op:
00088         return elem > value;
00089     case dods_greater_equal_op:
00090         return elem >= value;
00091     case dods_less_op:
00092         return elem < value;
00093     case dods_less_equal_op:
00094         return elem <= value;
00095     case dods_equal_op:
00096         return elem == value;
00097     case dods_not_equal_op:
00098         return elem != value;
00099     case dods_nop_op:
00100         throw Error(malformed_expr, "Attempt to use NOP in Grid selection.");
00101     default:
00102         throw Error(malformed_expr, "Unknown relational operator in Grid selection.");
00103     }
00104 }
00105 
00106 // These values are used in error messages, hence the strings.
00107 template<class T>
00108 void
00109 GSEClause::set_map_min_max_value(T min, T max)
00110 {
00111     DBG(cerr << "Inside set map min max value " << min << ", " << max << endl);
00112     std::ostringstream oss1;
00113     oss1 << min;
00114     d_map_min_value = oss1.str();
00115 
00116     std::ostringstream oss2;
00117     oss2 << max;
00118     d_map_max_value = oss2.str();
00119 }
00120 
00121 
00122 template<class T>
00123 void
00124 GSEClause::set_start_stop()
00125 {
00126     // Read the map array, scan, set start and stop.
00127 #if 0
00128     T *vals = 0;
00129     d_map->buf2val((void **)&vals);
00130 #endif
00131     T *vals = new T[d_map->length()];
00132     d_map->value(vals);
00133 
00134     // Set the map's max and min values for use in error messages (it's a lot
00135     // easier to do here, now, than later... 9/20/2001 jhrg)
00136     set_map_min_max_value<T>(vals[d_start], vals[d_stop]);
00137 
00138     // Starting at the current start point in the map (initially index position
00139     // zero), scan forward until the comparison is true. Set the new value
00140     // of d_start to that location. Note that each clause applies to exactly
00141     // one map. The 'i <= end' test keeps us from setting start _past_ the
00142     // end ;-)
00143     int i = d_start;
00144     int end = d_stop;
00145     while (i <= end && !compare<T>(vals[i], d_op1, d_value1))
00146         i++;
00147 
00148     d_start = i;
00149 
00150     // Now scan backward from the end. We scan all the way to the actual start
00151     // although it would probably work to stop at 'i >= d_start'.
00152     i = end;
00153     while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1))
00154         i--;
00155     d_stop = i;
00156 
00157     // Every clause must have one operator but the second is optional since
00158     // the more complex form of a clause is optional. That is, the above two
00159     // loops took care of constraints like 'x < 7' but we need the following
00160     // for ones like '3 < x < 7'.
00161     if (d_op2 != dods_nop_op) {
00162         int i = d_start;
00163         int end = d_stop;
00164         while (i <= end && !compare<T>(vals[i], d_op2, d_value2))
00165             i++;
00166 
00167         d_start = i;
00168 
00169         i = end;
00170         while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2))
00171             i--;
00172 
00173         d_stop = i;
00174     }
00175 }
00176 
00177 void
00178 GSEClause::compute_indices()
00179 {
00180     switch (d_map->var()->type()) {
00181     case dods_byte_c:
00182         set_start_stop<dods_byte>();
00183         break;
00184     case dods_int16_c:
00185         set_start_stop<dods_int16>();
00186         break;
00187     case dods_uint16_c:
00188         set_start_stop<dods_uint16>();
00189         break;
00190     case dods_int32_c:
00191         set_start_stop<dods_int32>();
00192         break;
00193     case dods_uint32_c:
00194         set_start_stop<dods_uint32>();
00195         break;
00196     case dods_float32_c:
00197         set_start_stop<dods_float32>();
00198         break;
00199     case dods_float64_c:
00200         set_start_stop<dods_float64>();
00201         break;
00202     default:
00203         throw Error(malformed_expr,
00204                     "Grid selection using non-numeric map vectors is not supported");
00205     }
00206 
00207 }
00208 
00209 // Public methods
00210 
00212 GSEClause::GSEClause(Grid *grid, const string &map, const double value,
00213                      const relop op)
00214         : d_map(0),
00215         d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
00216         d_map_min_value(""), d_map_max_value("")
00217 {
00218     d_map = dynamic_cast<Array *>(grid->var(map));
00219     if (!d_map)
00220         throw Error(string("The map variable '") + map
00221                     + string("' does not exist in the grid '")
00222                     + grid->name() + string("'."));
00223 
00224     DBG(cerr << d_map->toString());
00225 
00226     // Initialize the start and stop indices.
00227     Array::Dim_iter iter = d_map->dim_begin();
00228     d_start = d_map->dimension_start(iter);
00229     d_stop = d_map->dimension_stop(iter);
00230 
00231     compute_indices();
00232 }
00233 
00235 GSEClause::GSEClause(Grid *grid, const string &map, const double value1,
00236                      const relop op1, const double value2, const relop op2)
00237         : d_map(0),
00238         d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
00239         d_map_min_value(""), d_map_max_value("")
00240 {
00241     d_map = dynamic_cast<Array *>(grid->var(map));
00242     if (!d_map)
00243         throw Error(string("The map variable '") + map
00244                     + string("' does not exist in the grid '")
00245                     + grid->name() + string("'."));
00246 
00247     DBG(cerr << d_map->toString());
00248 
00249     // Initialize the start and stop indices.
00250     Array::Dim_iter iter = d_map->dim_begin();
00251     d_start = d_map->dimension_start(iter);
00252     d_stop = d_map->dimension_stop(iter);
00253 
00254     compute_indices();
00255 }
00256 
00259 bool
00260 GSEClause::OK() const
00261 {
00262     if (!d_map)
00263         return false;
00264 
00265     // More ...
00266 
00267     return true;
00268 }
00269 
00272 Array *
00273 GSEClause::get_map() const
00274 {
00275     return d_map;
00276 }
00277 
00282 void
00283 GSEClause::set_map(Array *map)
00284 {
00285     d_map = map;
00286 }
00287 
00290 string
00291 GSEClause::get_map_name() const
00292 {
00293     return d_map->name();
00294 }
00295 
00299 int
00300 GSEClause::get_start() const
00301 {
00302     return d_start;
00303 }
00304 
00307 void
00308 GSEClause::set_start(int start)
00309 {
00310     d_start = start;
00311 }
00312 
00316 int
00317 GSEClause::get_stop() const
00318 {
00319     DBG(cerr << "Returning stop index value of: " << d_stop << endl);
00320     return d_stop;
00321 }
00322 
00325 void
00326 GSEClause::set_stop(int stop)
00327 {
00328     d_stop = stop;
00329 }
00330 
00335 string
00336 GSEClause::get_map_min_value() const
00337 {
00338     return d_map_min_value;
00339 }
00340 
00345 string
00346 GSEClause::get_map_max_value() const
00347 {
00348     return d_map_max_value;
00349 }
00350 

Generated on Wed Jan 2 04:13:16 2008 for libdap++ by  doxygen 1.5.4