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