OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
ugrid_utils.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003,2011,2012 OPeNDAP, Inc.
7 // Authors: Nathan Potter <ndp@opendap.org>
8 // James Gallagher <jgallagher@opendap.org>
9 // Scott Moe <smeest1@gmail.com>
10 // Bill Howe <billhowe@cs.washington.edu>
11 //
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
16 //
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 //
26 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
27 
28 
29 //#define DODS_DEBUG
30 
31 #include "config.h"
32 
33 #if 0
34 #include <limits.h>
35 
36 #include <cstdlib> // used by strtod()
37 #include <cerrno>
38 #include <cmath>
39 #include <iostream>
40 #include <sstream>
41 #include <cxxabi.h>
42 
43 
44 #include "BaseType.h"
45 #include "Byte.h"
46 #include "Int16.h"
47 #include "UInt16.h"
48 #include "Int32.h"
49 #include "UInt32.h"
50 #include "Float32.h"
51 #include "Float64.h"
52 #include "Str.h"
53 #include "Url.h"
54 #include "Array.h"
55 #include "Structure.h"
56 #include "Sequence.h"
57 #include "Grid.h"
58 #include "Error.h"
59 #endif
60 
61 #include <vector>
62 #include <sstream>
63 
64 #include <gridfields/array.h>
65 
66 #include "BaseType.h"
67 #include "Array.h"
68 
69 #include "debug.h"
70 #include "util.h"
71 
72 #include "ugrid_utils.h"
73 
74 using namespace std;
75 //using namespace libdap;
76 
77 namespace ugrid {
78 
79 #if 0
80 
83 template<typename DODS, typename T>T *extract_array_helper(libdap::Array *a) {
84  int length = a->length();
85 
86  DBG(
87  int status;
88  char *dodsTypeName = abi::__cxa_demangle(typeid(DODS).name(), 0, 0, &status);;
89  char *tTypeName = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);;
90  )
91 
92  DBG(cerr << "extract_array_helper() - " << "Extracting data from DAP Array '" << a->name() <<"'"<< endl);
93  DBG(cerr << "extract_array_helper() - " << "Allocating " << length << " of type "<< dodsTypeName << endl);
94  DODS *src = new DODS[length];
95 
96  DBG(cerr << "extract_array_helper() - " << "Copying values from DAP Array "<< a->name() <<
97  " to an array of type '" << dodsTypeName <<"'. targetAddress=" << src << endl);
98  a->value(src);
99  DBG(cerr << "extract_array_helper() - " << "Copy complete." << endl);
100 
101  DBG(cerr << "extract_array_helper() - " << "Allocating " << length << " of type "<< tTypeName << endl);
102  T *dest = new T[length];
103 
104  DBG(cerr << "extract_array_helper() - " << "Casting/Copying array of type '" <<
105  dodsTypeName<<"' to an array of type '" << tTypeName << "'" << endl);
106  for (int i = 0; i < length; ++i)
107  dest[i] = (T) src[i];
108 
109  DBG(cerr << "extract_array_helper() - " << "Copy complete." << endl);
110 
111 
112  // We're done with b, so get rid of it.
113  DBG(cerr << "extract_array_helper() - " << "Releasing memory for an array of size "<< length <<
114  " and type '" << dodsTypeName <<"'"<< endl);
115  delete [] src;
116 
117  DBG(cerr << "extract_array_helper() - " << "Returning extracted values from DAP Array '" << a->name() <<"'"<< endl);
118 
119  return dest;
120 }
121 #endif
122 #if 0
123 
133 static GF::Array *extract_gridfield_array(Array *a) {
134  if ((a->type() == dods_array_c && !a->var()->is_simple_type())
135  || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
136  throw Error(malformed_expr,
137  "The function requires a DAP numeric-type array argument.");
138 
139  DBG(cerr << "extract_gridfield_array() - " << "Reading data values into DAP Array '" << a->name() <<"'"<< endl);
140  a->set_send_p(true);
141  a->read();
142 
143  // Construct a GridField array from a DODS array
144  GF::Array *gfa;
145 
146  switch (a->var()->type()) {
147  case dods_byte_c:
148  {
149  gfa = new GF::Array(a->var()->name(), GF::INT);
150  int *values = extract_array_helper<dods_byte, int>(a);
151  gfa->shareIntData(values, a->length());
152  break;
153  }
154  case dods_uint16_c:
155  {
156  gfa = new GF::Array(a->var()->name(), GF::INT);
157  int *values = extract_array_helper<dods_uint16, int>(a);
158  gfa->shareIntData(values, a->length());
159  break;
160  }
161  case dods_int16_c:
162  {
163  gfa = new GF::Array(a->var()->name(), GF::INT);
164  int *values = extract_array_helper<dods_int16, int>(a);
165  gfa->shareIntData(values, a->length());
166  break;
167  }
168  case dods_uint32_c:
169  {
170  gfa = new GF::Array(a->var()->name(), GF::INT);
171  int *values = extract_array_helper<dods_uint32, int>(a);
172  gfa->shareIntData(values, a->length());
173  break;
174  }
175  case dods_int32_c:
176  {
177  gfa = new GF::Array(a->var()->name(), GF::INT);
178  int *values = extract_array_helper<dods_int32, int>(a);
179  gfa->shareIntData(values, a->length());
180  break;
181  }
182  case dods_float32_c:
183  {
184  gfa = new GF::Array(a->var()->name(), GF::FLOAT);
185  float *values = extract_array_helper<dods_float32, float>(a);
186  gfa->shareFloatData(values, a->length());
187  break;
188  }
189  case dods_float64_c:
190  {
191  gfa = new GF::Array(a->var()->name(), GF::FLOAT);
192  float *values = extract_array_helper<dods_float64, float>(a);
193  gfa->shareFloatData(values, a->length());
194  break;
195  }
196  default:
197  throw InternalErr(__FILE__, __LINE__,
198  "Unknown DAP type encountered when converting to gridfields array");
199  }
200 
201 
202  return gfa;
203 }
204 
205 #endif
206 
207 
208 GF::e_Type getGridfieldsInternalTypeMap(Type type){
209 
210  switch (type) {
211  case dods_byte_c:
212  case dods_uint16_c:
213  case dods_int16_c:
214  case dods_uint32_c:
215  case dods_int32_c:
216  {
217  return GF::INT;
218  break;
219  }
220  case dods_float32_c:
221  case dods_float64_c:
222  {
223  return GF::FLOAT;
224  break;
225  }
226  default:
227  throw InternalErr(__FILE__, __LINE__,
228  "Unknown DAP type encountered when converting to gridfields internal type.");
229  }
230 }
231 
232 
233 Type getGridfieldsReturnType(Type type){
234  GF::e_Type gfInternalType = getGridfieldsInternalTypeMap(type);
235 
236  Type retType;
237  switch (gfInternalType) {
238  case GF::INT:
239  {
240  retType = dods_int32_c;
241  break;
242  }
243  case GF::FLOAT:
244  {
245  retType = dods_float64_c;
246  break;
247  }
248  default:
249  throw InternalErr(__FILE__, __LINE__,
250  "Unknown GF::e_Type type encountered when resolving gridfields result type mapping for dap type " +
251  libdap::type_name(type));
252  }
253  DBG(cerr << " getGridfieldsReturnType() - Return type for " << libdap::type_name(type) <<
254  " is " << libdap::type_name(retType) << endl);
255 
256  return retType;
257 }
258 
259 
260 Type getGridfieldsReturnType(libdap::Array *a){
261  return getGridfieldsReturnType(a->var()->type());
262 }
263 
264 
265 GF::Array *newGFIndexArray(string name, long size, vector<int*> *sharedIntArrays){
266  GF::Array *gfa = new GF::Array(name, GF::INT);
267  int *values = new int[size];
268  for(long i=0; i<size ;i++){
269  values[i] = i;
270  }
271  gfa->shareIntData(values, size);
272  sharedIntArrays->push_back(values);
273  return gfa;
274 }
275 
276 
287 GF::Array *extractGridFieldArray(libdap::Array *a, vector<int*> *sharedIntArrays, vector<float*> *sharedFloatArrays) {
288  if ((a->type() == dods_array_c && !a->var()->is_simple_type())
289  || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
290  throw Error(malformed_expr,
291  "The function requires a DAP numeric-type array argument.");
292 
293  DBG(cerr << "extract_gridfield_array() - " << "Reading data values into DAP Array '" << a->name() <<"'"<< endl);
294  a->set_send_p(true);
295  a->read();
296 
297  // Construct a GridField array from a DODS array
298  GF::Array *gfa;
299 
300  switch (a->var()->type()) {
301  case dods_byte_c:
302  {
303  gfa = new GF::Array(a->var()->name(), GF::INT);
304  int *values = extract_array_helper<dods_byte, int>(a);
305  gfa->shareIntData(values, a->length());
306  sharedIntArrays->push_back(values);
307  break;
308  }
309  case dods_uint16_c:
310  {
311  gfa = new GF::Array(a->var()->name(), GF::INT);
312  int *values = extract_array_helper<dods_uint16, int>(a);
313  gfa->shareIntData(values, a->length());
314  sharedIntArrays->push_back(values);
315  break;
316  }
317  case dods_int16_c:
318  {
319  gfa = new GF::Array(a->var()->name(), GF::INT);
320  int *values = extract_array_helper<dods_int16, int>(a);
321  gfa->shareIntData(values, a->length());
322  sharedIntArrays->push_back(values);
323  break;
324  }
325  case dods_uint32_c:
326  {
327  gfa = new GF::Array(a->var()->name(), GF::INT);
328  int *values = extract_array_helper<dods_uint32, int>(a);
329  gfa->shareIntData(values, a->length());
330  sharedIntArrays->push_back(values);
331  break;
332  }
333  case dods_int32_c:
334  {
335  gfa = new GF::Array(a->var()->name(), GF::INT);
336  int *values = extract_array_helper<dods_int32, int>(a);
337  gfa->shareIntData(values, a->length());
338  sharedIntArrays->push_back(values);
339  break;
340  }
341  case dods_float32_c:
342  {
343  gfa = new GF::Array(a->var()->name(), GF::FLOAT);
344  float *values = extract_array_helper<dods_float32, float>(a);
345  gfa->shareFloatData(values, a->length());
346  sharedFloatArrays->push_back(values);
347  break;
348  }
349  case dods_float64_c:
350  {
351  gfa = new GF::Array(a->var()->name(), GF::FLOAT);
352  float *values = extract_array_helper<dods_float64, float>(a);
353  gfa->shareFloatData(values, a->length());
354  sharedFloatArrays->push_back(values);
355  break;
356  }
357  default:
358  throw InternalErr(__FILE__, __LINE__,
359  "Unknown DAP type encountered when converting to gridfields array");
360  }
361  return gfa;
362 }
363 
364 #if 0
365 
369 template<typename T> T *extractArray(libdap::Array *a) {
370 
371  // Simple types are Byte, ..., Float64, String and Url.
372  if ((a->type() == dods_array_c && !a->var()->is_simple_type())
373  || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
374  throw Error(malformed_expr,
375  "The function requires a DAP numeric-type array argument.");
376 
377  DBG(cerr << "extract_array() - " << "Reading data values into DAP Array '" << a->name() <<"'"<< endl);
378  a->set_send_p(true);
379  a->read();
380  // This test should never pass due to the previous two lines;
381  // reading here seems to make
382  // sense rather than letting the caller forget to do so.
383  // is read() idemopotent?
384  if (!a->read_p())
385  throw InternalErr(__FILE__, __LINE__,
386  string("The Array '") + a->name()
387  + "'does not contain values. send_read_p() not called?");
388 
389 
390 
391  // The types of arguments that the CE Parser will build for numeric
392  // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
393  // Expanded to work for any numeric type so it can be used for more than
394  // just arguments.
395  switch (a->var()->type()) {
396  case dods_byte_c:
397  DBG(cerr << "extract_array() - extracting to an array of 'dods_byte_c'" << endl);
398  return extract_array_helper<dods_byte, T>(a);
399 
400  case dods_uint16_c:
401  DBG(cerr << "extract_array() - extracting to an array of 'dods_uint16_c'" << endl);
402  return extract_array_helper<dods_uint16, T>(a);
403 
404  case dods_int16_c:
405  DBG(cerr << "extract_array() - extracting to an array of 'dods_int16_c'" << endl);
406  return extract_array_helper<dods_int16, T>(a);
407 
408  case dods_uint32_c:
409  DBG(cerr << "extract_array() - extracting to an array of 'dods_uint32_c'" << endl);
410  return extract_array_helper<dods_uint32, T>(a);
411 
412  case dods_int32_c:
413  DBG(cerr << "extract_array() - extracting to an array of 'dods_int32_c'" << endl);
414  return extract_array_helper<dods_int32, T>(a);
415 
416  case dods_float32_c:
417  DBG(cerr << "extract_array() - extracting to an array of 'dods_float32_c'" << endl);
418  // Added the following line. jhrg 8/7/12
419  return extract_array_helper<dods_float32, T>(a);
420 
421  case dods_float64_c:
422  DBG(cerr << "extract_array() - extracting to an array of 'dods_float64_c'" << endl);
423  return extract_array_helper<dods_float64, T>(a);
424 
425  default:
426  throw InternalErr(__FILE__, __LINE__,
427  "The argument list built by the CE parser contained an unsupported numeric type.");
428  }
429 }
430 #endif
431 
436 vector<string> &split(const string &s, char delim, vector<string> &elems)
437 {
438  stringstream ss(s);
439  string item;
440  while (getline(ss, item, delim)) {
441  elems.push_back(item);
442  }
443  return elems;
444 }
445 
449 vector<string> split(const string &s, char delim)
450 {
451  vector<string> elems;
452  return split(s, delim, elems);
453 }
454 
455 // Returns the string value of the attribute called aName, 0 otherwise.
456 string getAttributeValue(BaseType *bt, string aName) {
457 
458  AttrTable &at = bt->get_attr_table();
459  DBG(cerr << "getAttributeValue() - " << "Checking to see if the variable " << bt->name()
460  << "' has an attribute '"<< aName << "'"<<endl);
461 
462  // Confirm that submitted variable has an attribute called aName and return its value.
463  AttrTable::Attr_iter loc = at.simple_find(aName);
464  if (loc != at.attr_end()) {
465  DBG(cerr << "checkAttributeValue() - " << "'" << bt->name() << "' has a attribute named '" << aName << "'"<< endl);
466 #if 0
467  string value = at.get_attr(loc, 0);
468  return value;
469 #endif
470  return at.get_attr(loc, 0);
471  }
472  return "";
473 }
474 
480 bool matchesCfRoleOrStandardName(BaseType *bt, string aValue) {
481  // Confirm that submitted variable has a 'location' attribute whose value is "node".
482  if (!checkAttributeValue(bt, CF_ROLE, aValue)) {
483  // Missing the 'cf_role' attribute? Check for a 'standard_name' attribute whose value is "aValue".
484  if (!checkAttributeValue(bt, CF_STANDARD_NAME, aValue)) {
485  return false;
486  }
487  }
488  return true;
489 }
490 
491 
492 
493 // Returns true iff the submitted BaseType variable has an attribute called aName attribute whose value is aValue.
494 bool checkAttributeValue(BaseType *bt, string aName, string aValue) {
495 
496  AttrTable &at = bt->get_attr_table();
497  DBG(cerr << "checkAttributeValue() - " << "Checking to see if the variable " << bt->name()
498  << "' has an attribute '"<< aName << "' with value '" << aValue << "'"<<endl);
499 
500  // Confirm that submitted variable has an attribute called aName whose value is aValue.
501  AttrTable::Attr_iter loc = at.simple_find(aName);
502  if (loc != at.attr_end()) {
503  DBG(cerr << "checkAttributeValue() - " << "'" << bt->name() << "' has a attribute named '" << aName << "'"<< endl);
504  string value = at.get_attr(loc, 0);
505  DBG(cerr << "checkAttributeValue() - " << "Attribute '"<< aName <<"' has value of '" << value << "'"<< endl);
506  if (value != aValue) {
507  return false;
508  }
509  return true;
510  }
511  return false;
512 
513 }
514 
515 
516 
517 
522 int getNfrom3byNArray(libdap::Array *array)
523 {
524 
525  int dimCount = array->dimensions(true);
526 
527  if (dimCount != 2)
528  throw Error(
529  "Expected a 2 dimensional array. The array '" + array->name()
530  + "' has " + libdap::long_to_string(dimCount) + " dimensions.");
531 
532  // Check the first dimension to be sure it's size is 3.
533  libdap::Array::Dim_iter di = array->dim_begin();
534  if (di->c_size != 3) {
535  string msg =
536  "Expected a 2 dimensional array with shape of 3xN! The array "
537  + array->name() + " has a first " + "dimension of size "
538  + libdap::long_to_string(di->c_size);
539  DBG(cerr << msg << endl);
540  throw Error(malformed_expr, msg);
541  }
542 
543  // Return the size of the second dimension;
544  di++;
545  return di->c_size;
546 
547 }
548 
549 
550 
551 
552 
553 } // namespace ugrid
GF::e_Type getGridfieldsInternalTypeMap(Type type)
Definition: ugrid_utils.cc:208
bool checkAttributeValue(BaseType *bt, string aName, string aValue)
Definition: ugrid_utils.cc:494
#define CF_ROLE
REQUIRED UGrid attribute vocabulary.
Definition: ugrid_utils.h:45
STL namespace.
GF::Array * extractGridFieldArray(libdap::Array *a, vector< int * > *sharedIntArrays, vector< float * > *sharedFloatArrays)
Extract data from a DAP array and return those values in a gridfields array.
Definition: ugrid_utils.cc:287
#define CF_STANDARD_NAME
Definition: ugrid_utils.h:46
GF::Array * newGFIndexArray(string name, long size, vector< int * > *sharedIntArrays)
Definition: ugrid_utils.cc:265
int getNfrom3byNArray(libdap::Array *array)
Retrieves the size of the second dimension from a 3xN array.
Definition: ugrid_utils.cc:522
T * extractArray(libdap::Array *a)
Given a pointer to an Array that holds a numeric type, extract the values and return in an array of T...
Definition: ugrid_utils.h:98
T * extract_array_helper(libdap::Array *a)
DAP Array data extraction helper method.
Definition: ugrid_utils.h:77
bool matchesCfRoleOrStandardName(BaseType *bt, string aValue)
Checks the passed BaseType attributes as follows: If the BaseType has a "cf_role" attribute and it's ...
Definition: ugrid_utils.cc:480
Type getGridfieldsReturnType(libdap::Array *a)
Definition: ugrid_utils.cc:260
string getAttributeValue(BaseType *bt, string aName)
Definition: ugrid_utils.cc:456
vector< string > split(const string &s, char delim)
Splits the string on the passed char.
Definition: ugrid_utils.cc:449