bes Updated for version 3.20.10
HDFCFStrField.cc
1
2// 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
23using namespace std;
24using namespace libdap;
25
26
27bool
28HDFCFStrField::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
267int
268HDFCFStrField::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