OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDF5CFUtil.cc
Go to the documentation of this file.
1 // This file is part of the hdf5_handler implementing for the CF-compliant
2 // Copyright (c) 2011-2013 The HDF Group, Inc. and OPeNDAP, Inc.
3 //
4 // This is free software; you can redistribute it and/or modify it under the
5 // terms of the GNU Lesser General Public License as published by the Free
6 // Software Foundation; either version 2.1 of the License, or (at your
7 // option) any later version.
8 //
9 // This software is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 // License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 //
18 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
19 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
20 // Suite 203, Champaign, IL 61820
21 
31 
32 #include "HDF5CFUtil.h"
33 #include <set>
34 #include <sstream>
35 #include <stdlib.h>
36 #include<InternalErr.h>
37 using namespace libdap;
38 
39 
42 {
43  size_t size = 0;
44  int sign = -2;
45 
46  switch (H5Tget_class(h5_type_id)) {
47 
48  case H5T_INTEGER:
49  size = H5Tget_size(h5_type_id);
50  sign = H5Tget_sign(h5_type_id);
51 
52  if (size == 1) { // Either signed char or unsigned char
53  if (sign == H5T_SGN_2)
54  return H5CHAR;
55  else
56  return H5UCHAR;
57  }
58  else if (size == 2) {
59  if (sign == H5T_SGN_2)
60  return H5INT16;
61  else
62  return H5UINT16;
63  }
64  else if (size == 4) {
65  if (sign == H5T_SGN_2)
66  return H5INT32;
67  else
68  return H5UINT32;
69  }
70  else if (size == 8) {
71  if (sign == H5T_SGN_2)
72  return H5INT64;
73  else
74  return H5UINT64;
75  }
76  else return H5UNSUPTYPE;
77 
78  case H5T_FLOAT:
79  size = H5Tget_size(h5_type_id);
80 
81  if (size == 4) return H5FLOAT32;
82  else if (size == 8) return H5FLOAT64;
83  else return H5UNSUPTYPE;
84 
85  case H5T_STRING:
86  if (H5Tis_variable_str(h5_type_id))
87  return H5VSTRING;
88  else return H5FSTRING;
89 
90  case H5T_REFERENCE:
91  return H5REFERENCE;
92 
93 
94  case H5T_COMPOUND:
95  return H5COMPOUND;
96 
97  case H5T_ARRAY:
98  return H5ARRAY;
99 
100  default:
101  return H5UNSUPTYPE;
102 
103  }
104 }
105 
107  if ((H5UNSUPTYPE == dtype)||(H5REFERENCE == dtype)
108  || (H5COMPOUND == dtype) || (H5ARRAY == dtype)
109  || (H5INT64 == dtype) ||(H5UINT64 == dtype))
110  return false;
111  else
112  return true;
113 }
114 
116 
117  string ret_str="";
118  size_t last_fslash_pos = s.find_last_of("/");
119  if (string::npos != last_fslash_pos &&
120  last_fslash_pos != (s.size()-1))
121  ret_str=s.substr(last_fslash_pos+1);
122  return ret_str;
123 }
124 
125 string HDF5CFUtil::trim_string(hid_t ty_id,const string s, int num_sect, size_t sect_size, vector<size_t>& sect_newsize) {
126 
127  string temp_sect_str = "";
128  string temp_sect_newstr = "";
129  string final_str="";
130 
131  for (int i = 0; i < num_sect; i++) {
132 
133  if (i != (num_sect-1))
134  temp_sect_str = s.substr(i*sect_size,sect_size);
135  else
136  temp_sect_str = s.substr((num_sect-1)*sect_size,s.size()-(num_sect-1)*sect_size);
137 
138  size_t temp_pos = 0;
139 
140  if (H5T_STR_NULLTERM == H5Tget_strpad(ty_id))
141  temp_pos = temp_sect_str.find_first_of('\0');
142  else if (H5T_STR_SPACEPAD == H5Tget_strpad(ty_id))
143  temp_pos = temp_sect_str.find_last_not_of(' ')+1;
144  else temp_pos = temp_sect_str.find_last_not_of('0')+1;// NULL PAD
145 
146  if (temp_pos != string::npos) {
147 
148  // Here I only add a space at the end of each section for the SPACEPAD case,
149  // but not for NULL TERM
150  // or NULL PAD. Two reasons: C++ string doesn't need NULL TERM.
151  // We don't know and don't see any NULL PAD applications for NASA data.
152  if (H5T_STR_SPACEPAD == H5Tget_strpad(ty_id)) {
153 
154  if (temp_pos == temp_sect_str.size())
155  temp_sect_newstr = temp_sect_str +" ";
156  else
157  temp_sect_newstr = temp_sect_str.substr(0,temp_pos+1);
158 
159  sect_newsize[i] = temp_pos +1;
160  }
161  else {
162  temp_sect_newstr = temp_sect_str.substr(0,temp_pos);
163  sect_newsize[i] = temp_pos ;
164  }
165 
166  }
167 
168  else {// NULL is not found, adding a NULL at the end of this string.
169 
170  temp_sect_newstr = temp_sect_str;
171 
172  // Here I only add a space for the SPACEPAD, but not for NULL TERM
173  // or NULL PAD. Two reasons: C++ string doesn't need NULL TERM.
174  // We don't know and don't see any NULL PAD applications for NASA data.
175  if (H5T_STR_SPACEPAD == H5Tget_strpad(ty_id)) {
176  temp_sect_newstr.resize(temp_sect_str.size()+1);
177  temp_sect_newstr.append(1,' ');
178  sect_newsize[i] = sect_size + 1;
179  }
180  else
181  sect_newsize[i] = sect_size;
182  }
183  final_str+=temp_sect_newstr;
184  }
185 
186  return final_str;
187 }
188 
189 // Obtain the unique name for the clashed names and save it to set namelist.
190 
191 void HDF5CFUtil::gen_unique_name(string &str,set<string>& namelist, int&clash_index) {
192 
193  pair<set<string>::iterator,bool> ret;
194  string newstr = "";
195  stringstream sclash_index;
196  sclash_index << clash_index;
197  newstr = str + sclash_index.str();
198 
199  ret = namelist.insert(newstr);
200  if (false == ret.second) {
201  clash_index++;
202  gen_unique_name(str,namelist,clash_index);
203  }
204  else
205  str = newstr;
206 }
207 
208 
209 // From a string separated by a separator to a list of string,
210 // for example, split "ab,c" to {"ab","c"}
211 void
212 HDF5CFUtil::Split(const char *s, int len, char sep, std::vector<std::string> &names)
213 {
214  names.clear();
215  for (int i = 0, j = 0; j <= len; ++j) {
216  if ((j == len && len) || s[j] == sep) {
217  string elem(s + i, j - i);
218  names.push_back(elem);
219  i = j + 1;
220  continue;
221  }
222  }
223 }
224 
225 
226 // Assume sz is Null terminated string.
227 void
228 HDF5CFUtil::Split(const char *sz, char sep, std::vector<std::string> &names)
229 {
230  Split(sz, (int)strlen(sz), sep, names);
231 }
232 
233 void HDF5CFUtil::parser_gpm_l3_gridheader(const vector<char>& value,
234  int& latsize, int&lonsize,
235  float& lat_start, float& lon_start,
236  float& lat_res, float& lon_res,
237  bool check_reg_orig ){
238 
239  //bool cr_reg = false;
240  //bool sw_origin = true;
241  //float lat_res = 1.;
242  //float lon_res = 1.;
243  float lat_north = 0.;
244  float lat_south = 0.;
245  float lon_east = 0.;
246  float lon_west = 0.;
247 
248  vector<string> ind_elems;
249  char sep='\n';
250  HDF5CFUtil::Split(&value[0],sep,ind_elems);
251 
252  // The number of elements in the GridHeader is 9. The string vector will add a leftover. So the size should be 10.
253  if(ind_elems.size()!=10)
254  throw InternalErr(__FILE__,__LINE__,"The number of elements in the TRMM level 3 GridHeader is not right.");
255 
256  if(false == check_reg_orig) {
257  if (0 != ind_elems[1].find("Registration=CENTER"))
258  throw InternalErr(__FILE__,__LINE__,"The TRMM grid registration is not center.");
259  }
260 
261  if (0 == ind_elems[2].find("LatitudeResolution")){
262 
263  size_t equal_pos = ind_elems[2].find_first_of('=');
264  if(string::npos == equal_pos)
265  throw InternalErr(__FILE__,__LINE__,"Cannot find latitude resolution for TRMM level 3 products");
266 
267  size_t scolon_pos = ind_elems[2].find_first_of(';');
268  if(string::npos == scolon_pos)
269  throw InternalErr(__FILE__,__LINE__,"Cannot find latitude resolution for TRMM level 3 products");
270  if (equal_pos < scolon_pos){
271 
272  string latres_str = ind_elems[2].substr(equal_pos+1,scolon_pos-equal_pos-1);
273  lat_res = strtof(latres_str.c_str(),NULL);
274  }
275  else
276  throw InternalErr(__FILE__,__LINE__,"latitude resolution is not right for TRMM level 3 products");
277  }
278  else
279  throw InternalErr(__FILE__,__LINE__,"The TRMM grid LatitudeResolution doesn't exist.");
280 
281  if (0 == ind_elems[3].find("LongitudeResolution")){
282 
283  size_t equal_pos = ind_elems[3].find_first_of('=');
284  if(string::npos == equal_pos)
285  throw InternalErr(__FILE__,__LINE__,"Cannot find longitude resolution for TRMM level 3 products");
286 
287  size_t scolon_pos = ind_elems[3].find_first_of(';');
288  if(string::npos == scolon_pos)
289  throw InternalErr(__FILE__,__LINE__,"Cannot find longitude resolution for TRMM level 3 products");
290  if (equal_pos < scolon_pos){
291  string lonres_str = ind_elems[3].substr(equal_pos+1,scolon_pos-equal_pos-1);
292  lon_res = strtof(lonres_str.c_str(),NULL);
293  }
294  else
295  throw InternalErr(__FILE__,__LINE__,"longitude resolution is not right for TRMM level 3 products");
296  }
297  else
298  throw InternalErr(__FILE__,__LINE__,"The TRMM grid LongitudeResolution doesn't exist.");
299 
300  if (0 == ind_elems[4].find("NorthBoundingCoordinate")){
301 
302  size_t equal_pos = ind_elems[4].find_first_of('=');
303  if(string::npos == equal_pos)
304  throw InternalErr(__FILE__,__LINE__,"Cannot find latitude resolution for TRMM level 3 products");
305 
306  size_t scolon_pos = ind_elems[4].find_first_of(';');
307  if(string::npos == scolon_pos)
308  throw InternalErr(__FILE__,__LINE__,"Cannot find latitude resolution for TRMM level 3 products");
309  if (equal_pos < scolon_pos){
310  string north_bounding_str = ind_elems[4].substr(equal_pos+1,scolon_pos-equal_pos-1);
311  lat_north = strtof(north_bounding_str.c_str(),NULL);
312  }
313  else
314  throw InternalErr(__FILE__,__LINE__,"NorthBoundingCoordinate is not right for TRMM level 3 products");
315 
316  }
317  else
318  throw InternalErr(__FILE__,__LINE__,"The TRMM grid NorthBoundingCoordinate doesn't exist.");
319 
320  if (0 == ind_elems[5].find("SouthBoundingCoordinate")){
321 
322  size_t equal_pos = ind_elems[5].find_first_of('=');
323  if(string::npos == equal_pos)
324  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
325 
326  size_t scolon_pos = ind_elems[5].find_first_of(';');
327  if(string::npos == scolon_pos)
328  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
329  if (equal_pos < scolon_pos){
330  string lat_south_str = ind_elems[5].substr(equal_pos+1,scolon_pos-equal_pos-1);
331  lat_south = strtof(lat_south_str.c_str(),NULL);
332  }
333  else
334  throw InternalErr(__FILE__,__LINE__,"south bound coordinate is not right for TRMM level 3 products");
335 
336  }
337  else
338  throw InternalErr(__FILE__,__LINE__,"The TRMM grid SouthBoundingCoordinate doesn't exist.");
339 
340  if (0 == ind_elems[6].find("EastBoundingCoordinate")){
341 
342  size_t equal_pos = ind_elems[6].find_first_of('=');
343  if(string::npos == equal_pos)
344  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
345 
346  size_t scolon_pos = ind_elems[6].find_first_of(';');
347  if(string::npos == scolon_pos)
348  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
349  if (equal_pos < scolon_pos){
350  string lon_east_str = ind_elems[6].substr(equal_pos+1,scolon_pos-equal_pos-1);
351  lon_east = strtof(lon_east_str.c_str(),NULL);
352  }
353  else
354  throw InternalErr(__FILE__,__LINE__,"south bound coordinate is not right for TRMM level 3 products");
355 
356  }
357  else
358  throw InternalErr(__FILE__,__LINE__,"The TRMM grid EastBoundingCoordinate doesn't exist.");
359 
360  if (0 == ind_elems[7].find("WestBoundingCoordinate")){
361 
362  size_t equal_pos = ind_elems[7].find_first_of('=');
363  if(string::npos == equal_pos)
364  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
365 
366  size_t scolon_pos = ind_elems[7].find_first_of(';');
367  if(string::npos == scolon_pos)
368  throw InternalErr(__FILE__,__LINE__,"Cannot find south bound coordinate for TRMM level 3 products");
369  if (equal_pos < scolon_pos){
370  string lon_west_str = ind_elems[7].substr(equal_pos+1,scolon_pos-equal_pos-1);
371  lon_west = strtof(lon_west_str.c_str(),NULL);
372 //cerr<<"latres str is "<<lon_west_str <<endl;
373 //cerr<<"latres is "<<lon_west <<endl;
374  }
375  else
376  throw InternalErr(__FILE__,__LINE__,"south bound coordinate is not right for TRMM level 3 products");
377 
378  }
379  else
380  throw InternalErr(__FILE__,__LINE__,"The TRMM grid WestBoundingCoordinate doesn't exist.");
381 
382  if (false == check_reg_orig) {
383  if (0 != ind_elems[8].find("Origin=SOUTHWEST"))
384  throw InternalErr(__FILE__,__LINE__,"The TRMM grid origin is not SOUTHWEST.");
385  }
386 
387  // Since we only treat the case when the Registration is center, so the size should be the
388  // regular number size - 1.
389  latsize =(int)((lat_north-lat_south)/lat_res);
390  lonsize =(int)((lon_east-lon_west)/lon_res);
391  lat_start = lat_south;
392  lon_start = lon_west;
393 }
394 
395 void HDF5CFUtil::close_fileid(hid_t file_id,bool pass_fileid) {
396  if(false == pass_fileid) {
397  if(file_id != -1)
398  H5Fclose(file_id);
399  }
400 
401 }
402 
403 
static void close_fileid(hid_t, bool)
Definition: HDF5CFUtil.cc:395
static void parser_gpm_l3_gridheader(const std::vector< char > &value, int &latsize, int &lonsize, float &lat_start, float &lon_start, float &lat_res, float &lon_res, bool check_reg_orig)
Definition: HDF5CFUtil.cc:233
static class NCMLUtil overview
H5DataType
Definition: HDF5CFUtil.h:54
static void gen_unique_name(std::string &str, std::set< std::string > &namelist, int &clash_index)
Definition: HDF5CFUtil.cc:191
#define NULL
Definition: wcsUtil.h:65
static std::string obtain_string_after_lastslash(const std::string s)
Definition: HDF5CFUtil.cc:115
static void Split(const char *s, int len, char sep, std::vector< std::string > &names)
From a string separated by a separator to a list of string, for example, split "ab,c" to {"ab","c"}.
Definition: HDF5CFUtil.cc:212
This file includes several helper functions for translating HDF5 to CF-compliant. ...
static bool cf_strict_support_type(H5DataType dtype)
Definition: HDF5CFUtil.cc:106
static std::string trim_string(hid_t dtypeid, const std::string s, int num_sect, size_t section_size, std::vector< size_t > &sect_newsize)
Trim the string with many NULL terms or garbage characters to simply a string with a NULL terminator...
Definition: HDF5CFUtil.cc:125
static H5DataType H5type_to_H5DAPtype(hid_t h5_type_id)
Map HDF5 Datatype to the intermediate H5DAPtype for the future use.
Definition: HDF5CFUtil.cc:41