libdap  Updated for version 3.20.6
libdap4 is an implementation of OPeNDAP's DAP protocol.
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 <Array.h>
41 #include <Grid.h>
42 #include <dods-datatypes.h>
43 #include <Error.h>
44 #include <InternalErr.h>
45 #include <debug.h>
46 
47 #include "GSEClause.h"
48 #include "parser.h"
49 #include "gse.tab.hh"
50 
51 using namespace std;
52 using namespace libdap;
53 
54 namespace functions {
55 
56 // For the comparisons here, we should use an epsilon to catch issues
57 // with floating point values. jhrg 01/12/06
58 template<class T>
59 static bool
60 compare(T elem, relop op, double value)
61 {
62  switch (op) {
63  case dods_greater_op:
64  return elem > value;
65  case dods_greater_equal_op:
66  return elem >= value;
67  case dods_less_op:
68  return elem < value;
69  case dods_less_equal_op:
70  return elem <= value;
71  case dods_equal_op:
72  return elem == value;
73  case dods_not_equal_op:
74  return elem != value;
75  case dods_nop_op:
76  throw Error(malformed_expr, "Attempt to use NOP in Grid selection.");
77  default:
78  throw Error(malformed_expr, "Unknown relational operator in Grid selection.");
79  }
80 }
81 
82 // These values are used in error messages, hence the strings.
83 template<class T>
84 void
85 GSEClause::set_map_min_max_value(T min, T max)
86 {
87  DBG(cerr << "Inside set map min max value " << min << ", " << max << endl);
88  std::ostringstream oss1;
89  oss1 << min;
90  d_map_min_value = oss1.str();
91 
92  std::ostringstream oss2;
93  oss2 << max;
94  d_map_max_value = oss2.str();
95 }
96 
97 // Read the map array, scan, set start and stop.
98 template<class T>
99 void
100 GSEClause::set_start_stop()
101 {
102  T *vals = new T[d_map->length()];
103  d_map->value(vals);
104 
105  // Set the map's max and min values for use in error messages (it's a lot
106  // easier to do here, now, than later... 9/20/2001 jhrg)
107  set_map_min_max_value<T>(vals[d_start], vals[d_stop]);
108 
109  // Starting at the current start point in the map (initially index position
110  // zero), scan forward until the comparison is true. Set the new value
111  // of d_start to that location. Note that each clause applies to exactly
112  // one map. The 'i <= end' test keeps us from setting start _past_ the
113  // end ;-)
114  int i = d_start;
115  int end = d_stop;
116  while (i <= end && !compare<T>(vals[i], d_op1, d_value1))
117  i++;
118 
119  d_start = i;
120 
121  // Now scan backward from the end. We scan all the way to the actual start
122  // although it would probably work to stop at 'i >= d_start'.
123  i = end;
124  while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1))
125  i--;
126  d_stop = i;
127 
128  // Every clause must have one operator but the second is optional since
129  // the more complex form of a clause is optional. That is, the above two
130  // loops took care of constraints like 'x < 7' but we need the following
131  // for ones like '3 < x < 7'.
132  if (d_op2 != dods_nop_op) {
133  int i = d_start;
134  int end = d_stop;
135  while (i <= end && !compare<T>(vals[i], d_op2, d_value2))
136  i++;
137 
138  d_start = i;
139 
140  i = end;
141  while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2))
142  i--;
143 
144  d_stop = i;
145  }
146 
147  delete[] vals;
148 }
149 
150 void
151 GSEClause::compute_indices()
152 {
153  switch (d_map->var()->type()) {
154  case dods_byte_c:
155  set_start_stop<dods_byte>();
156  break;
157  case dods_int16_c:
158  set_start_stop<dods_int16>();
159  break;
160  case dods_uint16_c:
161  set_start_stop<dods_uint16>();
162  break;
163  case dods_int32_c:
164  set_start_stop<dods_int32>();
165  break;
166  case dods_uint32_c:
167  set_start_stop<dods_uint32>();
168  break;
169  case dods_float32_c:
170  set_start_stop<dods_float32>();
171  break;
172  case dods_float64_c:
173  set_start_stop<dods_float64>();
174  break;
175  default:
176  throw Error(malformed_expr,
177  "Grid selection using non-numeric map vectors is not supported");
178  }
179 
180 }
181 
182 // Public methods
183 
185 GSEClause::GSEClause(Grid *grid, const string &map, const double value,
186  const relop op)
187  : d_map(0),
188  d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
189  d_map_min_value(""), d_map_max_value("")
190 {
191  d_map = dynamic_cast<Array *>(grid->var(map));
192  if (!d_map)
193  throw Error(string("The map variable '") + map
194  + string("' does not exist in the grid '")
195  + grid->name() + string("'."));
196 
197  DBG(cerr << d_map->toString());
198 
199  // Initialize the start and stop indices.
200  Array::Dim_iter iter = d_map->dim_begin();
201  d_start = d_map->dimension_start(iter);
202  d_stop = d_map->dimension_stop(iter);
203 
204  compute_indices();
205 }
206 
208 GSEClause::GSEClause(Grid *grid, const string &map, const double value1,
209  const relop op1, const double value2, const relop op2)
210  : d_map(0),
211  d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
212  d_map_min_value(""), d_map_max_value("")
213 {
214  d_map = dynamic_cast<Array *>(grid->var(map));
215  if (!d_map)
216  throw Error(string("The map variable '") + map
217  + string("' does not exist in the grid '")
218  + grid->name() + string("'."));
219 
220  DBG(cerr << d_map->toString());
221 
222  // Initialize the start and stop indices.
223  Array::Dim_iter iter = d_map->dim_begin();
224  d_start = d_map->dimension_start(iter);
225  d_stop = d_map->dimension_stop(iter);
226 
227  compute_indices();
228 }
229 
230 GSEClause::~GSEClause()
231 {
232  delete d_map;
233 }
234 
237 bool
239 {
240  if (!d_map)
241  return false;
242 
243  // More ...
244 
245  return true;
246 }
247 
250 Array *
252 {
253  return d_map;
254 }
255 
260 void
262 {
263  d_map = map;
264 }
265 
268 string
270 {
271  return d_map->name();
272 }
273 
277 int
279 {
280  return d_start;
281 }
282 
285 void
287 {
288  d_start = start;
289 }
290 
294 int
296 {
297  DBG(cerr << "Returning stop index value of: " << d_stop << endl);
298  return d_stop;
299 }
300 
303 void
305 {
306  d_stop = stop;
307 }
308 
313 string
315 {
316  return d_map_min_value;
317 }
318 
323 string
325 {
326  return d_map_max_value;
327 }
328 
329 } // namespace functions
330 
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:320
string get_map_max_value() const
Get the maximum map vector value.
Definition: GSEClause.cc:324
virtual BaseType * var(const string &name, bool exact_match=true, btp_stack *s=0)
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition: Constructor.cc:267
STL namespace.
int get_stop() const
Get the stopping index of the clause&#39;s map variable as constrained by this clause.
Definition: GSEClause.cc:295
top level DAP object to house generic methods
Definition: AISConnect.cc:30
std::vector< dimension >::iterator Dim_iter
Definition: Array.h:206
Holds the Grid data type.
Definition: Grid.h:122
void set_stop(int stop)
Set the stopping index.
Definition: GSEClause.cc:304
bool OK() const
Definition: GSEClause.cc:238
libdap::Array * get_map() const
Get a pointer to the map variable constrained by this clause.
Definition: GSEClause.cc:251
void set_start(int start)
Set the starting index.
Definition: GSEClause.cc:286
void set_map(libdap::Array *map)
Set the pointer to the map vector contrained by this clause.
Definition: GSEClause.cc:261
int get_start() const
Get the starting index of the clause&#39;s map variable as constrained by this clause.
Definition: GSEClause.cc:278
A class for error processing.
Definition: Error.h:92
string get_map_name() const
Get the name of the map variable constrained by this clause.
Definition: GSEClause.cc:269
string get_map_min_value() const
Get the minimum map vector value.
Definition: GSEClause.cc:314
A multidimensional array of identical data types.
Definition: Array.h:112