bes  Updated for version 3.20.10
GSEClause.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1999
27 // Please read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 // The Grid Selection Expression Clause class.
33 
34 
35 #include "config.h"
36 
37 #include <iostream>
38 #include <sstream>
39 
40 #include <libdap/Array.h>
41 #include <libdap/Grid.h>
42 #include <libdap/dods-datatypes.h>
43 //#include <libdap/Error.h>
44 //#include <libdap/InternalErr.h>
45 #include <libdap/debug.h>
46 
47 #include "BESInternalError.h"
48 
49 #include "GSEClause.h"
50 #include <libdap/parser.h>
51 #include "gse.tab.hh"
52 
53 using namespace std;
54 using namespace libdap;
55 
56 namespace functions {
57 
58 // For the comparisons here, we should use an epsilon to catch issues
59 // with floating point values. jhrg 01/12/06
60 template<class T>
61 static bool
62 compare(T elem, relop op, double value)
63 {
64  switch (op) {
65  case dods_greater_op:
66  return elem > value;
67  case dods_greater_equal_op:
68  return elem >= value;
69  case dods_less_op:
70  return elem < value;
71  case dods_less_equal_op:
72  return elem <= value;
73  case dods_equal_op:
74  return elem == value;
75  case dods_not_equal_op:
76  return elem != value;
77  case dods_nop_op:
78  throw Error(malformed_expr, "Attempt to use NOP in Grid selection.");
79  default:
80  throw Error(malformed_expr, "Unknown relational operator in Grid selection.");
81  }
82 }
83 
84 // These values are used in error messages, hence the strings.
85 template<class T>
86 void
87 GSEClause::set_map_min_max_value(T min, T max)
88 {
89  DBG(cerr << "Inside set map min max value " << min << ", " << max << endl);
90  std::ostringstream oss1;
91  oss1 << min;
92  d_map_min_value = oss1.str();
93 
94  std::ostringstream oss2;
95  oss2 << max;
96  d_map_max_value = oss2.str();
97 }
98 
99 // Read the map array, scan, set start and stop.
100 //
101 // I switched to vals.at(x) instead of vals[x] because sonar scan was
102 // complaining about access beyond the end of memory. The 'at()' method
103 // is much more complex, so if we can go back to the
104 template<class T>
105 void
106 GSEClause::set_start_stop()
107 {
108  vector<T> vals(d_map->length());
109  d_map->value(&vals[0]);
110 
111  if (!((unsigned long)d_start < vals.size() && (unsigned long)d_stop < vals.size()))
112  throw BESInternalError("Access beyond the bounds of a Grid Map.", __FILE__, __LINE__);
113 
114  // Set the map's max and min values for use in error messages (it's a lot
115  // easier to do here, now, than later... 9/20/2001 jhrg)
116  set_map_min_max_value<T>(vals[d_start], vals[d_stop]);
117 
118  // Starting at the current start point in the map (initially index position
119  // zero), scan forward until the comparison is true. Set the new value
120  // of d_start to that location. Note that each clause applies to exactly
121  // one map. The 'i <= end' test keeps us from setting start _past_ the
122  // end ;-)
123  int i = d_start;
124  int end = d_stop;
125  while (i <= end && !compare<T>(vals[i], d_op1, d_value1))
126  ++i;
127  d_start = i;
128 
129  // Now scan backward from the end. We scan all the way to the actual start,
130  // although it would probably work to stop at 'i >= d_start'.
131  i = end;
132  while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1))
133  --i;
134  d_stop = i;
135 
136  // Every clause must have one operator but the second is optional since
137  // the more complex form of a clause is optional. That is, the above two
138  // loops took care of constraints like 'x < 7' but we need the following
139  // for ones like '3 < x < 7'.
140  if (d_op2 != dods_nop_op) {
141  i = d_start;
142  end = d_stop;
143  while (i <= end && !compare<T>(vals[i], d_op2, d_value2))
144  ++i;
145 
146  d_start = i;
147 
148  i = end;
149  while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2))
150  --i;
151 
152  d_stop = i;
153  }
154 }
155 
156 void
157 GSEClause::compute_indices()
158 {
159  switch (d_map->var()->type()) {
160  case dods_byte_c:
161  set_start_stop<dods_byte>();
162  break;
163  case dods_int16_c:
164  set_start_stop<dods_int16>();
165  break;
166  case dods_uint16_c:
167  set_start_stop<dods_uint16>();
168  break;
169  case dods_int32_c:
170  set_start_stop<dods_int32>();
171  break;
172  case dods_uint32_c:
173  set_start_stop<dods_uint32>();
174  break;
175  case dods_float32_c:
176  set_start_stop<dods_float32>();
177  break;
178  case dods_float64_c:
179  set_start_stop<dods_float64>();
180  break;
181  default:
182  throw Error(malformed_expr,
183  "Grid selection using non-numeric map vectors is not supported");
184  }
185 
186 }
187 
188 // Public methods
189 
191 GSEClause::GSEClause(Grid *grid, const string &map, const double value,
192  const relop op)
193  : d_map(0),
194  d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
195  d_map_min_value(""), d_map_max_value("")
196 {
197  d_map = dynamic_cast<Array *>(grid->var(map));
198  if (!d_map)
199  throw Error(string("The map variable '") + map
200  + string("' does not exist in the grid '")
201  + grid->name() + string("'."));
202 
203  DBG(cerr << d_map->toString());
204 
205  // Initialize the start and stop indices.
206  Array::Dim_iter iter = d_map->dim_begin();
207  d_start = d_map->dimension_start(iter);
208  d_stop = d_map->dimension_stop(iter);
209 
210  compute_indices();
211 }
212 
214 GSEClause::GSEClause(Grid *grid, const string &map, const double value1,
215  const relop op1, const double value2, const relop op2)
216  : d_map(0),
217  d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
218  d_map_min_value(""), d_map_max_value("")
219 {
220  d_map = dynamic_cast<Array *>(grid->var(map));
221  if (!d_map)
222  throw Error(string("The map variable '") + map
223  + string("' does not exist in the grid '")
224  + grid->name() + string("'."));
225 
226  DBG(cerr << d_map->toString());
227 
228  // Initialize the start and stop indices.
229  Array::Dim_iter iter = d_map->dim_begin();
230  d_start = d_map->dimension_start(iter);
231  d_stop = d_map->dimension_stop(iter);
232 
233  compute_indices();
234 }
235 
236 GSEClause::~GSEClause()
237 {
238  delete d_map;
239 }
240 
243 bool
244 GSEClause::OK() const
245 {
246  if (!d_map)
247  return false;
248 
249  // More ...
250 
251  return true;
252 }
253 
256 Array *
257 GSEClause::get_map() const
258 {
259  return d_map;
260 }
261 
266 void
267 GSEClause::set_map(Array *map)
268 {
269  d_map = map;
270 }
271 
274 string
275 GSEClause::get_map_name() const
276 {
277  return d_map->name();
278 }
279 
283 int
284 GSEClause::get_start() const
285 {
286  return d_start;
287 }
288 
291 void
292 GSEClause::set_start(int start)
293 {
294  d_start = start;
295 }
296 
300 int
301 GSEClause::get_stop() const
302 {
303  DBG(cerr << "Returning stop index value of: " << d_stop << endl);
304  return d_stop;
305 }
306 
309 void
310 GSEClause::set_stop(int stop)
311 {
312  d_stop = stop;
313 }
314 
319 string
320 GSEClause::get_map_min_value() const
321 {
322  return d_map_min_value;
323 }
324 
329 string
330 GSEClause::get_map_max_value() const
331 {
332  return d_map_max_value;
333 }
334 
335 } // namespace functions
336 
exception thrown if internal error encountered