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 16088 2007-03-28 21:42:19Z 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     T *vals = 0;
00128     d_map->buf2val((void **)&vals);
00129 
00130     // Set the map's max and min values for use in error messages (it's a lot
00131     // easier to do here, now, than later... 9/20/2001 jhrg)
00132     set_map_min_max_value<T>(vals[d_start], vals[d_stop]);
00133 
00134     // Starting at the current start point in the map (initially index position
00135     // zero), scan forward until the comparison is true. Set the new value
00136     // of d_start to that location. Note that each clause applies to exactly
00137     // one map. The 'i <= end' test keeps us from setting start _past_ the
00138     // end ;-)
00139     int i = d_start;
00140     int end = d_stop;
00141     while (i <= end && !compare<T>(vals[i], d_op1, d_value1))
00142         i++;
00143 
00144     d_start = i;
00145 
00146     // Now scan backward from the end. We scan all the way to the actual start
00147     // although it would probably work to stop at 'i >= d_start'.
00148     i = end;
00149     while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1))
00150         i--;
00151     d_stop = i;
00152 
00153     // Every clause must have one operator but the second is optional since
00154     // the more complex form of a clause is optional. That is, the above two
00155     // loops took care of constraints like 'x < 7' but we need the following
00156     // for ones like '3 < x < 7'.
00157     if (d_op2 != dods_nop_op) {
00158         int i = d_start;
00159         int end = d_stop;
00160         while (i <= end && !compare<T>(vals[i], d_op2, d_value2))
00161             i++;
00162 
00163         d_start = i;
00164 
00165         i = end;
00166         while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2))
00167             i--;
00168 
00169         d_stop = i;
00170     }
00171 }
00172 
00173 void
00174 GSEClause::compute_indices()
00175 {
00176     switch (d_map->var()->type()) {
00177     case dods_byte_c:
00178         set_start_stop<dods_byte>();
00179         break;
00180     case dods_int16_c:
00181         set_start_stop<dods_int16>();
00182         break;
00183     case dods_uint16_c:
00184         set_start_stop<dods_uint16>();
00185         break;
00186     case dods_int32_c:
00187         set_start_stop<dods_int32>();
00188         break;
00189     case dods_uint32_c:
00190         set_start_stop<dods_uint32>();
00191         break;
00192     case dods_float32_c:
00193         set_start_stop<dods_float32>();
00194         break;
00195     case dods_float64_c:
00196         set_start_stop<dods_float64>();
00197         break;
00198     default:
00199         throw Error(malformed_expr,
00200                     "Grid selection using non-numeric map vectors is not supported");
00201     }
00202 
00203 }
00204 
00205 // Public methods
00206 
00208 GSEClause::GSEClause(Grid *grid, const string &map, const double value,
00209                      const relop op)
00210         : d_map(0),
00211         d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
00212         d_map_min_value(""), d_map_max_value("")
00213 {
00214     d_map = dynamic_cast<Array *>(grid->var(map));
00215     if (!d_map)
00216         throw Error(string("The map variable '") + map
00217                     + string("' does not exist in the grid '")
00218                     + grid->name() + string("'."));
00219 
00220     DBG(cerr << d_map->toString());
00221 
00222     // Initialize the start and stop indices.
00223     Array::Dim_iter iter = d_map->dim_begin();
00224     d_start = d_map->dimension_start(iter);
00225     d_stop = d_map->dimension_stop(iter);
00226 
00227     compute_indices();
00228 }
00229 
00231 GSEClause::GSEClause(Grid *grid, const string &map, const double value1,
00232                      const relop op1, const double value2, const relop op2)
00233         : d_map(0),
00234         d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
00235         d_map_min_value(""), d_map_max_value("")
00236 {
00237     d_map = dynamic_cast<Array *>(grid->var(map));
00238     if (!d_map)
00239         throw Error(string("The map variable '") + map
00240                     + string("' does not exist in the grid '")
00241                     + grid->name() + string("'."));
00242 
00243     DBG(cerr << d_map->toString());
00244 
00245     // Initialize the start and stop indices.
00246     Array::Dim_iter iter = d_map->dim_begin();
00247     d_start = d_map->dimension_start(iter);
00248     d_stop = d_map->dimension_stop(iter);
00249 
00250     compute_indices();
00251 }
00252 
00255 bool
00256 GSEClause::OK() const
00257 {
00258     if (!d_map)
00259         return false;
00260 
00261     // More ...
00262 
00263     return true;
00264 }
00265 
00268 Array *
00269 GSEClause::get_map() const
00270 {
00271     return d_map;
00272 }
00273 
00278 void
00279 GSEClause::set_map(Array *map)
00280 {
00281     d_map = map;
00282 }
00283 
00286 string
00287 GSEClause::get_map_name() const
00288 {
00289     return d_map->name();
00290 }
00291 
00295 int
00296 GSEClause::get_start() const
00297 {
00298     return d_start;
00299 }
00300 
00303 void
00304 GSEClause::set_start(int start)
00305 {
00306     d_start = start;
00307 }
00308 
00312 int
00313 GSEClause::get_stop() const
00314 {
00315     DBG(cerr << "Returning stop index value of: " << d_stop << endl);
00316     return d_stop;
00317 }
00318 
00321 void
00322 GSEClause::set_stop(int stop)
00323 {
00324     d_stop = stop;
00325 }
00326 
00331 string
00332 GSEClause::get_map_min_value() const
00333 {
00334     return d_map_min_value;
00335 }
00336 
00341 string
00342 GSEClause::get_map_max_value() const
00343 {
00344     return d_map_max_value;
00345 }
00346 

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7