bes  Updated for version 3.20.13
HDFCFStrField.cc
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
3 // It retrieves the HDF4 DFNT_CHAR >1D array and then send to DAP as a DAP string array.
4 // This file is used when the CF option of the handler is turned on.
5 // Authors: MuQun Yang <myang6@hdfgroup.org>
6 // Copyright (c) 2010-2012 The HDF Group
8 
9 #include "config.h"
10 #include "config_hdf.h"
11 
12 #include <iostream>
13 #include <sstream>
14 #include <cassert>
15 #include <libdap/debug.h>
16 #include <libdap/InternalErr.h>
17 #include <BESDebug.h>
18 #include <BESLog.h>
19 
20 #include "HDFCFUtil.h"
21 #include "HDFCFStrField.h"
22 #include "HDF4RequestHandler.h"
23 
24 using namespace std;
25 using namespace libdap;
26 
27 
28 bool
29 HDFCFStrField::read ()
30 {
31 
32  BESDEBUG("h4","Coming to HDFCFStrField read "<<endl);
33  if(length() == 0)
34  return true;
35 
36  bool check_pass_fileid_key = HDF4RequestHandler::get_pass_fileid();
37 
38  // Note that one dimensional character array is one string,
39  // so the rank for character arrays should be rank from string+1
40  // offset32,step32 and count32 will be new subsetting parameters for
41  // character arrays.
42  vector<int32>offset32;
43  offset32.resize(rank+1);
44  vector<int32>count32;
45  count32.resize(rank+1);
46  vector<int32>step32;
47  step32.resize(rank+1);
48  int nelms = 1;
49 
50  if (rank != 0) {
51 
52  // Declare offset, count and step,
53  vector<int>offset;
54  offset.resize(rank);
55  vector<int>count;
56  count.resize(rank);
57  vector<int>step;
58  step.resize(rank);
59 
60  // Declare offset, count and step,
61  // Note that one dimensional character array is one string,
62  // so the rank for character arrays should be rank from string+1
63  // Obtain offset,step and count from the client expression constraint
64  nelms = format_constraint (offset.data(), step.data(), count.data());
65 
66  // Assign the offset32,count32 and step32 up to the dimension rank-1.
67  // Will assign the dimension rank later.
68  for (int i = 0; i < rank; i++) {
69  offset32[i] = (int32) offset[i];
70  count32[i] = (int32) count[i];
71  step32[i] = (int32) step[i];
72  }
73  }
74 
75 
76  // Initialize the temp. returned value.
77  int32 r = 0;
78 
79  // First SDS
80  if(false == is_vdata) {
81 
82  int32 sdid = -1;
83  if(false == check_pass_fileid_key) {
84  sdid = SDstart (filename.c_str (), DFACC_READ);
85  if (sdid < 0) {
86  ostringstream eherr;
87  eherr << "File " << filename.c_str () << " cannot be open.";
88  throw InternalErr (__FILE__, __LINE__, eherr.str ());
89  }
90  }
91  else
92  sdid = h4fd;
93 
94  int32 sdsid = 0;
95 
96  int32 sdsindex = SDreftoindex (sdid, fieldref);
97  if (sdsindex == -1) {
98  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
99  ostringstream eherr;
100  eherr << "SDS index " << sdsindex << " is not right.";
101  throw InternalErr (__FILE__, __LINE__, eherr.str ());
102  }
103 
104  // Obtain this SDS ID.
105  sdsid = SDselect (sdid, sdsindex);
106  if (sdsid < 0) {
107  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
108  ostringstream eherr;
109  eherr << "SDselect failed.";
110  throw InternalErr (__FILE__, __LINE__, eherr.str ());
111  }
112 
113  int32 dim_sizes[H4_MAX_VAR_DIMS];
114  int32 sds_rank;
115  int32 data_type;
116  int32 n_attrs;
117  char name[H4_MAX_NC_NAME];
118 
119  r = SDgetinfo (sdsid, name, &sds_rank, dim_sizes,
120  &data_type, &n_attrs);
121  if(r == FAIL) {
122  SDendaccess(sdsid);
123  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
124  ostringstream eherr;
125  eherr << "SDgetinfo failed.";
126  throw InternalErr (__FILE__, __LINE__, eherr.str ());
127  }
128 
129  if(sds_rank != (rank+1)) {
130  SDendaccess(sdsid);
131  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
132  ostringstream eherr;
133  eherr << "The rank of string doesn't match with the rank of character array";
134  throw InternalErr (__FILE__, __LINE__, eherr.str ());
135 
136  }
137  offset32[rank] = 0;
138  count32[rank] = dim_sizes[rank];
139  step32[rank] = 1;
140  int32 last_dim_size = dim_sizes[rank];
141 
142  vector<char>val;
143  val.resize(nelms*count32[rank]);
144 
145  r = SDreaddata (sdsid, offset32.data(), step32.data(), count32.data(), val.data());
146  if (r != 0) {
147  SDendaccess (sdsid);
148  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
149  ostringstream eherr;
150  eherr << "SDreaddata failed.";
151  throw InternalErr (__FILE__, __LINE__, eherr.str ());
152  }
153 
154  vector<string>final_val;
155  final_val.resize(nelms);
156  vector<char> temp_buf;
157  temp_buf.resize(last_dim_size+1);
158 
159  // Since the number of the dimension for a string is reduced by 1,
160  // the value of each string is the subset of the whole last dimension
161  // of the original array.
162  for (int i = 0; i<nelms;i++) {
163  strncpy(temp_buf.data(),val.data()+last_dim_size*i,last_dim_size);
164  temp_buf[last_dim_size]='\0';
165  final_val[i] = temp_buf.data();
166  }
167  set_value(final_val.data(),nelms);
168  SDendaccess(sdsid);
169  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
170 
171  }
172  else {
173 
174  int32 file_id = -1;
175 
176  if(true == check_pass_fileid_key)
177  file_id = h4fd;
178  else {
179  // Open the file
180  file_id = Hopen (filename.c_str (), DFACC_READ, 0);
181  if (file_id < 0) {
182  ostringstream eherr;
183  eherr << "File " << filename.c_str () << " cannot be open.";
184  throw InternalErr (__FILE__, __LINE__, eherr.str ());
185  }
186  }
187 
188  // Start the Vdata interface
189  if (Vstart (file_id) < 0) {
190  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
191  ostringstream eherr;
192  eherr << "This file cannot be open.";
193  throw InternalErr (__FILE__, __LINE__, eherr.str ());
194  }
195 
196  // Attach the vdata
197  int32 vdata_id = VSattach (file_id, fieldref, "r");
198  if (vdata_id == -1) {
199  Vend (file_id);
200  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
201  ostringstream eherr;
202  eherr << "Vdata cannot be attached.";
203  throw InternalErr (__FILE__, __LINE__, eherr.str ());
204  }
205 
206 
207  // Seek the position of the starting point
208  if (VSseek (vdata_id, offset32[0]) == -1) {
209  VSdetach (vdata_id);
210  Vend (file_id);
211  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
212  ostringstream eherr;
213  eherr << "VSseek failed at " << offset32[0];
214  throw InternalErr (__FILE__, __LINE__, eherr.str ());
215  }
216 
217  // Prepare the vdata field
218  if (VSsetfields (vdata_id, fieldname.c_str ()) == -1) {
219  VSdetach (vdata_id);
220  Vend (file_id);
221  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
222  ostringstream eherr;
223  eherr << "VSsetfields failed with the name " << fieldname;
224  throw InternalErr (__FILE__, __LINE__, eherr.str ());
225  }
226 
227  int32 vdfelms = fieldorder * count32[0] * step32[0];
228 
229  vector<char> val;
230  val.resize(vdfelms);
231 
232  // Read the data
233  r = VSread (vdata_id, (uint8 *) val.data(), 1+(count32[0] -1)* step32[0],
234  FULL_INTERLACE);
235 
236  if (r == -1) {
237  VSdetach (vdata_id);
238  Vend (file_id);
239  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
240  ostringstream eherr;
241  eherr << "VSread failed.";
242  throw InternalErr (__FILE__, __LINE__, eherr.str ());
243  }
244 
245  vector<string>final_val;
246  final_val.resize(nelms);
247 
248  vector<char> temp_buf;
249  temp_buf.resize(fieldorder+1);
250  for (int i = 0; i<nelms;i++) {
251  strncpy(temp_buf.data(),val.data()+fieldorder*i*step32[0],fieldorder);
252  temp_buf[fieldorder]='\0';
253  final_val[i] = temp_buf.data();
254  }
255  set_value(final_val.data(),nelms);
256  VSdetach(vdata_id);
257  Vend(file_id);
258  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
259 
260  }
261 
262  return false;
263 }
264 
265 int
266 HDFCFStrField::format_constraint (int *offset, int *step, int *count)
267 {
268  int nels = 1;
269  int id = 0;
270 
271  Dim_iter p = dim_begin ();
272  while (p != dim_end ()) {
273 
274  int start = dimension_start (p, true);
275  int stride = dimension_stride (p, true);
276  int stop = dimension_stop (p, true);
277 
278  // Check for illegal constraint
279  if (start > stop) {
280  ostringstream oss;
281  oss << "Array/Grid hyperslab start point "<< start <<
282  " is greater than stop point " << stop <<".";
283  throw Error(malformed_expr, oss.str());
284  }
285 
286  offset[id] = start;
287  step[id] = stride;
288  count[id] = ((stop - start) / stride) + 1; // count of elements
289  nels *= count[id]; // total number of values for variable
290 
291  BESDEBUG ("h4",
292  "=format_constraint():"
293  << "id=" << id << " offset=" << offset[id]
294  << " step=" << step[id]
295  << " count=" << count[id]
296  << endl);
297 
298  id++;
299  p++;
300  }// while
301 
302  return nels;
303 }
304 
305 
306 #if 0
307  while (p != dim_end ()) {
308 
309  int start = dimension_start (p, true);
310  int stride = dimension_stride (p, true);
311  int stop = dimension_stop (p, true);
312 
313 
314  // Check for illegical constraint
315  if (stride < 0 || start < 0 || stop < 0 || start > stop) {
316  ostringstream oss;
317 
318  oss << "Array/Grid hyperslab indices are bad: [" << start <<
319  ":" << stride << ":" << stop << "]";
320  throw Error (malformed_expr, oss.str ());
321  }
322 
323  // Check for an empty constraint and use the whole dimension if so.
324  if (start == 0 && stop == 0 && stride == 0) {
325  start = dimension_start (p, false);
326  stride = dimension_stride (p, false);
327  stop = dimension_stop (p, false);
328  }
329 
330  offset[id] = start;
331  step[id] = stride;
332  count[id] = ((stop - start) / stride) + 1;// count of elements
333  nels *= count[id];// total number of values for variable
334 
335  BESDEBUG ("h4",
336  "=format_constraint():"
337  << "id=" << id << " offset=" << offset[id]
338  << " step=" << step[id]
339  << " count=" << count[id]
340  << endl);
341 
342  id++;
343  p++;
344  }
345 
346  return nels;
347 }
348 
349 #endif
350 
static void close_fileid(int32 sdfd, int32 file_id, int32 gridfd, int32 swathfd, bool pass_fileid_key)
Definition: HDFCFUtil.cc:3650