bes  Updated for version 3.20.6
FFArray.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
4 // DAP2 data server.
5 
6 // Copyright (c) 2005 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // (c) COPYRIGHT URI/MIT 1997-99
26 // Please read the full copyright statement in the file COPYRIGHT.
27 //
28 // Authors: reza (Reza Nekovei)
29 
30 // FreeFrom sub-class implementation for FFByte,...FFGrid.
31 // The files are patterned after the subcalssing examples
32 // Test<type>.c,h files.
33 //
34 // ReZa 6/18/97
35 
36 #include "config_ff.h"
37 
38 static char rcsid[] not_used = { "$Id$" };
39 
40 #include <cstring>
41 #include <iostream>
42 #include <string>
43 
44 #include <BESDebug.h>
45 
46 #include <dods-datatypes.h>
47 #include <D4Attributes.h>
48 #include <D4Group.h>
49 #include <Error.h>
50 #include <InternalErr.h>
51 
52 #include "FFArray.h"
53 #include "util_ff.h"
54 #include "util.h"
55 
56 BaseType *
57 FFArray::ptr_duplicate()
58 {
59  return new FFArray(*this);
60 }
61 
62 FFArray::FFArray(const string &n, const string &d, BaseType *v, const string &iff) :
63  Array(n, d, v), d_input_format_file(iff)
64 {
65 }
66 
67 FFArray::~FFArray()
68 {
69 }
70 
71 // parse constraint expr. and make coordinate point location for an array.
72 // return number of elements to read.
73 
74 long FFArray::Arr_constraint(long *cor, long *step, long *edg, string *dim_nms, bool *has_stride)
75 {
76  long start, stride, stop;
77 
78  int id = 0;
79  long nels = 1;
80  *has_stride = false;
81 
82  Array::Dim_iter i = dim_begin();
83  while (i != dim_end()) {
84  start = (long) dimension_start(i, true);
85  stride = (long) dimension_stride(i, true);
86  stop = (long) dimension_stop(i, true);
87  string dimname = dimension_name(i);
88 #if 0
89  // Check for empty constraint
90  if (start + stop + stride == 0)
91  return -1;
92 #endif
93  // This code is a correct version of the above, but it _should_ never be called
94  // since libdap::Vector::serialize() will never call Array::read() when length is
95  // zero. Still, a server function might... jhrg 2/17/16
96  if (length() == 0)
97  return -1;
98 
99  dim_nms[id] = dimname;
100  // (void) strcpy(dim_nms[id], dimname.c_str());
101 
102  cor[id] = start;
103  step[id] = stride;
104  edg[id] = ((stop - start) / stride) + 1; // count of elements
105 
106  nels *= edg[id]; // total number of values for variable
107 
108  if (stride != 1)
109  *has_stride = true;
110 
111  ++id;
112  ++i;
113  }
114  return nels;
115 }
116 
117 #if 0
118 // parse constraint expr. and make coordinate point location.
119 // return number of elements to read.
120 
121 long FFArray::Seq_constraint(long *cor, long *step, long *edg, bool *has_stride)
122 {
123  int start, stride, stop;
124  int id = 0;
125  long nels = 1;
126  *has_stride = false;
127 
128  Array::Dim_iter i = dim_begin();
129  while (i != dim_end()) {
130  start = (long) dimension_start(i, true);
131  stride = (long) dimension_stride(i, true);
132  stop = (long) dimension_stop(i, true);
133 #if 0
134  // Check for empty constraint
135  if (start + stop + stride == 0)
136  return -1;
137 #endif
138  if (length() == 0)
139  return -1;
140 
141  cor[id] = start;
142  step[id] = stride;
143  edg[id] = ((stop - start) / stride) + 1; // count of elements
144  nels *= edg[id]; // total number of values for variable
145  if (stride != 1)
146  *has_stride = true;
147 
148  ++id;
149  ++i;
150  }
151  return nels;
152 }
153 #endif
154 
155 #if 0
156 static int hyper_get(void *dest, void *src, unsigned szof, const int dim_num, int index, const int dimsz[],
157  const long start[], const long edge[])
158 {
159  long jump = 1;
160 
161  // The THEN part of this IF handles the cases where we are hyper-slabbing
162  // any dimension *other* than the rightmost dimension. E.G. Suppose
163  // a[10][10][10] is in SRC, for INDEX == 0 and 1 we do the code in the
164  // THEN clause and for INDEX == 2 the ELSE clause is executed.
165 
166  // NOTE: I have added casts for src and dest from void * to char * since
167  // ANSI C++ won't allow pointer arithmetic on void * variables. 4/17/98
168  // jhrg
169 
170  if (dim_num != (index + 1)) {
171  // number of lines, pages, etc to skip
172  for (int i = dim_num - 1; i > index; i--)
173  jump *= dimsz[i];
174 
175  for (int edge_tmp = 0; edge_tmp < edge[index]; edge_tmp++) {
176  void *srctmp = ((char *) src + (start[index] + edge_tmp) * jump * szof);
177  dest = (char *) dest + hyper_get(dest, srctmp, szof, dim_num, index + 1, dimsz, start, edge);
178  }
179  return (0);
180  }
181  else {
182  // number of bytes to jump
183  void *srctmp = (char *) src + start[index] * szof;
184  memcpy(dest, srctmp, (size_t) edge[index] * szof);
185  return (edge[index] * szof);
186  }
187 }
188 #endif
189 
190 #if 0
191 template<class T>
192 static void seq2vects(T * t, FFArray & array)
193 {
194  bool has_stride;
195  int ndim = array.dimensions();
196  long *start = new long[ndim];
197  long *stride = new long[ndim];
198  long *edge = new long[ndim];
199 
200  long count = array.Seq_constraint(start, stride, edge, &has_stride);
201 
202  if (count != -1) { // non-null hyperslab
203  T *t_hs = new T[count];
204  int *dimsz = new int[array.dimensions()];
205 
206  int i = 0;
207  Array::Dim_iter p = array.dim_begin();
208  while (p != array.dim_end()) {
209  dimsz[i] = array.dimension_size(p);
210  ++i;
211  ++p;
212  }
213 
214  hyper_get(t_hs, t, array.var()->width(), ndim, 0, dimsz, start, edge);
215 
216  array.set_read_p(true); // reading is done
217  array.val2buf((void *) t_hs); // put values in the buffer
218 
219  delete[] t_hs;
220  delete[] dimsz;
221  }
222  else {
223  array.set_read_p(true);
224  array.val2buf((void *) t);
225  }
226 
227  delete[] start;
228  delete[] stride;
229  delete[] edge;
230 }
231 #endif
232 
233 // Read cardinal types and ctor types separately. Cardinal types are
234 // stored in arrays of the C++ data type while ctor types are stored
235 // in arrays of the DODS classes used to store those types.
236 //
237 // NB: Currently this code only reads arrays of Byte, Int32 and
238 // Float64. Str and Url as well as all the ctor types are not
239 // supported.
240 //
241 // Throws an Error object if an error was detected.
242 // Returns true if more data still needs to be read, otherwise returns false.
243 
244 bool FFArray::read()
245 {
246  if (read_p()) // Nothing to do
247  return true;
248 
249  bool has_stride;
250  int ndims = dimensions();
251  vector<string> dname(ndims);
252  vector<long> start(ndims);
253  vector<long> stride(ndims);
254  vector<long> edge(ndims);
255  long count = Arr_constraint(&start[0], &stride[0], &edge[0], &dname[0], &has_stride);
256 
257  if (!count) {
258  throw Error(unknown_error, "Constraint returned an empty dataset.");
259  }
260 
261  string output_format = makeND_output_format(name(), var()->type(), var()->width(),
262  ndims, &start[0], &edge[0], &stride[0], &dname[0]);
263 
264  // For each cardinal-type variable, do the following:
265  // Use ff to read the data
266  // Store the (possibly constrained) data
267  // NB: extract_array throws an Error object to signal problems.
268 
269  switch (var()->type()) {
270  case dods_byte_c:
271  extract_array<dods_byte>(dataset(), d_input_format_file, output_format);
272  break;
273 
274  case dods_int16_c:
275  extract_array<dods_int16>(dataset(), d_input_format_file, output_format);
276  break;
277 
278  case dods_uint16_c:
279  extract_array<dods_uint16>(dataset(), d_input_format_file, output_format);
280  break;
281 
282  case dods_int32_c:
283  extract_array<dods_int32>(dataset(), d_input_format_file, output_format);
284  break;
285 
286  case dods_uint32_c:
287  extract_array<dods_uint32>(dataset(), d_input_format_file, output_format);
288  break;
289 
290  case dods_float32_c:
291  extract_array<dods_float32>(dataset(), d_input_format_file, output_format);
292  break;
293 
294  case dods_float64_c:
295  extract_array<dods_float64>(dataset(), d_input_format_file, output_format);
296  break;
297 
298  default:
299  throw InternalErr(__FILE__, __LINE__,
300  (string) "FFArray::read: Unsupported array type " + var()->type_name() + ".");
301  }
302 
303  return true;
304 }
305 
306 // This template reads arrays of simple types into the Array object's _buf
307 // member. It returns true if successful, false otherwise.
308 
309 template<class T>
310 bool FFArray::extract_array(const string &ds, const string &if_fmt, const string &o_fmt)
311 {
312  vector<T> d(length());
313  long bytes = read_ff(ds.c_str(), if_fmt.c_str(), o_fmt.c_str(), (char *) &d[0], width());
314 
315  BESDEBUG("ff", "FFArray::extract_array: Read " << bytes << " bytes." << endl);
316 
317  if (bytes == -1) {
318  throw Error(unknown_error, "Could not read values from the dataset.");
319  }
320  else {
321  set_read_p(true);
322  set_value(d, d.size());
323  }
324 
325  return true;
326 }
FFArray
Definition: FFArray.h:45
Error