bes Updated for version 3.20.13
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
53using namespace std;
54using namespace libdap;
55
56namespace functions {
57
58// For the comparisons here, we should use an epsilon to catch issues
59// with floating point values. jhrg 01/12/06
60template<class T>
61static bool
62compare(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.
85template<class T>
86void
87GSEClause::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
104template<class T>
105void
106GSEClause::set_start_stop()
107{
108 vector<T> vals(d_map->length());
109 d_map->value(vals.data());
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
156void
157GSEClause::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
191GSEClause::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
214GSEClause::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
236GSEClause::~GSEClause()
237{
238 delete d_map;
239}
240
243bool
244GSEClause::OK() const
245{
246 if (!d_map)
247 return false;
248
249 // More ...
250
251 return true;
252}
253
256Array *
257GSEClause::get_map() const
258{
259 return d_map;
260}
261
266void
267GSEClause::set_map(Array *map)
268{
269 d_map = map;
270}
271
274string
275GSEClause::get_map_name() const
276{
277 return d_map->name();
278}
279
283int
284GSEClause::get_start() const
285{
286 return d_start;
287}
288
291void
292GSEClause::set_start(int start)
293{
294 d_start = start;
295}
296
300int
301GSEClause::get_stop() const
302{
303 DBG(cerr << "Returning stop index value of: " << d_stop << endl);
304 return d_stop;
305}
306
309void
310GSEClause::set_stop(int stop)
311{
312 d_stop = stop;
313}
314
319string
320GSEClause::get_map_min_value() const
321{
322 return d_map_min_value;
323}
324
329string
330GSEClause::get_map_max_value() const
331{
332 return d_map_max_value;
333}
334
335} // namespace functions
336
exception thrown if internal error encountered