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