bes  Updated for version 3.20.13
HDFEOS2CFStrField.cc
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
3 // It retrieves HDF-EOS2 swath/grid one dimensional character(DFNT_CHAR) array to DAP String for the CF option.
4 // Authors: MuQun Yang <myang6@hdfgroup.org> Eunsoo Seo
5 // Copyright (c) 2010-2012 The HDF Group
7 
8 #ifdef USE_HDFEOS2_LIB
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 "HDFEOS2CFStrField.h"
22 #include "HDF4RequestHandler.h"
23 
24 using namespace std;
25 using namespace libdap;
26 
27 
28 
29 bool
30 HDFEOS2CFStrField::read ()
31 {
32 
33  BESDEBUG("h4","Coming to HDFEOS2CFStrField read "<<endl);
34 
35  if(length() == 0)
36  return true;
37 
38  bool check_pass_fileid_key = HDF4RequestHandler::get_pass_fileid();
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.data(), step.data(), count.data());
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  int32 (*openfunc) (char *, intn);
77  intn (*closefunc) (int32);
78  int32 (*attachfunc) (int32, char *);
79  intn (*detachfunc) (int32);
80  intn (*fieldinfofunc) (int32, char *, int32 *, int32 *, int32 *, char *);
81  intn (*readfieldfunc) (int32, char *, int32 *, int32 *, int32 *, void *);
82 
83 
84  // Define function pointers to handle the swath
85  if(grid_or_swath == 0) {
86  openfunc = GDopen;
87  closefunc = GDclose;
88  attachfunc = GDattach;
89  detachfunc = GDdetach;
90  fieldinfofunc = GDfieldinfo;
91  readfieldfunc = GDreadfield;
92 
93  }
94  else {
95  openfunc = SWopen;
96  closefunc = SWclose;
97  attachfunc = SWattach;
98  detachfunc = SWdetach;
99  fieldinfofunc = SWfieldinfo;
100  readfieldfunc = SWreadfield;
101  }
102 
103  int32 gfid = -1;
104  if (false == check_pass_fileid_key) {
105 
106  // Obtain the EOS object ID(either grid or swath)
107  gfid = openfunc (const_cast < char *>(filename.c_str ()), DFACC_READ);
108  if (gfid < 0) {
109  ostringstream eherr;
110  eherr << "File " << filename.c_str () << " cannot be open.";
111  throw InternalErr (__FILE__, __LINE__, eherr.str ());
112  }
113 
114  }
115  else
116  gfid = gsfd;
117 
118  int32 gsid = attachfunc (gfid, const_cast < char *>(objname.c_str ()));
119  if (gsid < 0) {
120  if(false == check_pass_fileid_key)
121  closefunc(gfid);
122  ostringstream eherr;
123  eherr << "Grid/Swath " << objname.c_str () << " cannot be attached.";
124  throw InternalErr (__FILE__, __LINE__, eherr.str ());
125  }
126 
127  // Initialize the temp. returned value.
128  intn r = 0;
129  int32 tmp_rank = 0;
130  char tmp_dimlist[1024];
131  int32 tmp_dims[rank+1];
132  int32 field_dtype = 0;
133 
134  r = fieldinfofunc (gsid, const_cast < char *>(varname.c_str ()),
135  &tmp_rank, tmp_dims, &field_dtype, tmp_dimlist);
136  if (r != 0) {
137  detachfunc(gsid);
138  if(false == check_pass_fileid_key)
139  closefunc(gfid);
140  ostringstream eherr;
141  eherr << "Field " << varname.c_str () << " information cannot be obtained.";
142  throw InternalErr (__FILE__, __LINE__, eherr.str ());
143  }
144 
145  offset32[rank] = 0;
146  count32[rank] = tmp_dims[rank];
147  step32[rank] = 1;
148  int32 last_dim_size = tmp_dims[rank];
149 
150  vector<char>val;
151  val.resize(nelms*count32[rank]);
152 
153  r = readfieldfunc(gsid,const_cast<char*>(varname.c_str()),
154  offset32.data(), step32.data(), count32.data(), val.data());
155 
156  if (r != 0) {
157  detachfunc(gsid);
158  if(false == check_pass_fileid_key)
159  closefunc(gfid);
160  ostringstream eherr;
161  eherr << "swath or grid readdata failed.";
162  throw InternalErr (__FILE__, __LINE__, eherr.str ());
163  }
164 
165  vector<string>final_val;
166  final_val.resize(nelms);
167  vector<char> temp_buf;
168  temp_buf.resize(last_dim_size+1);
169 
170  // The array values of the last dimension should be saved as the
171  // string.
172  for (int i = 0; i<nelms;i++) {
173  strncpy(temp_buf.data(),val.data()+last_dim_size*i,last_dim_size);
174  temp_buf[last_dim_size]='\0';
175  final_val[i] = temp_buf.data();
176  }
177  set_value(final_val.data(),nelms);
178 
179  detachfunc(gsid);
180  if(false == check_pass_fileid_key)
181  closefunc(gfid);
182 
183  return false;
184 }
185 
186 int
187 HDFEOS2CFStrField::format_constraint (int *offset, int *step, int *count)
188 {
189  int nels = 1;
190  int id = 0;
191 
192  Dim_iter p = dim_begin ();
193  while (p != dim_end ()) {
194 
195  int start = dimension_start (p, true);
196  int stride = dimension_stride (p, true);
197  int stop = dimension_stop (p, true);
198 
199  // Check for illegal constraint
200  if (start > stop) {
201  ostringstream oss;
202  oss << "Array/Grid hyperslab start point "<< start <<
203  " is greater than stop point " << stop <<".";
204  throw Error(malformed_expr, oss.str());
205  }
206 
207  offset[id] = start;
208  step[id] = stride;
209  count[id] = ((stop - start) / stride) + 1; // count of elements
210  nels *= count[id]; // total number of values for variable
211 
212  BESDEBUG ("h4",
213  "=format_constraint():"
214  << "id=" << id << " offset=" << offset[id]
215  << " step=" << step[id]
216  << " count=" << count[id]
217  << endl);
218 
219  id++;
220  p++;
221  }
222 
223  return nels;
224 }
225 
226 
227 #endif
This class provides a way to map HDFEOS2 character >1D array to DAP Str array for the CF option.