bes  Updated for version 3.20.10
h5cfdaputil.cc
Go to the documentation of this file.
1 // This file is part of hdf5_handler: an HDF5 file handler for the OPeNDAP
2 // data server.
3 
4 // Copyright (c) 2011-2016 The HDF Group, Inc. and OPeNDAP, Inc.
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
22 // Suite 203, Champaign, IL 61820
23 
35 
36 
37 #include "h5cfdaputil.h"
38 #include <math.h>
39 
40 using namespace std;
41 using namespace libdap;
42 
43 // Part of a large fix for attributes. Escaping the values of the attributes
44 // may have been a bad idea. It breaks using JSON, for example. If this is a
45 // bad idea - to turn of escaping - then we'll have to figure out how to store
46 // 'serialized JSON' in attributes because it's being used in netcdf/hdf files.
47 // If we stick with this, there's clearly a more performant solution - eliminate
48 // the calls to this code.
49 // jhrg 6/25/21
50 #define ESCAPE_STRING_ATTRIBUTES 0
51 
52 string HDF5CFDAPUtil::escattr(string s)
53 {
54  const string printable = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+={[}]|\\:;<,>.?/'\"\n\t\r";
55  const string ESC = "\\";
56 #if ESCAPE_STRING_ATTRIBUTES
57  const string DOUBLE_ESC = ESC + ESC;
58  const string QUOTE = "\"";
59  const string ESCQUOTE = ESC + QUOTE;
60 
61  // escape \ with a second backslash
62  size_t ind = 0;
63  while ((ind = s.find(ESC, ind)) != string::npos) {
64  s.replace(ind, 1, DOUBLE_ESC);
65  ind += DOUBLE_ESC.length();
66  }
67 
68  // escape " with backslash
69  ind = 0;
70  while ((ind = s.find(QUOTE, ind)) != string::npos) {
71  s.replace(ind, 1, ESCQUOTE);
72  ind += ESCQUOTE.length();
73  }
74 #endif
75 
76  // escape non-printing characters with octal escape
77  size_t ind = 0;
78  while ((ind = s.find_first_not_of(printable, ind)) != string::npos)
79  s.replace(ind, 1, ESC + octstring(s[ind]));
80 
81  return s;
82 }
83 
84 // present the string in octal base.
85 string
86 HDF5CFDAPUtil::octstring(unsigned char val)
87 {
88  ostringstream buf;
89  buf << oct << setw(3) << setfill('0')
90  << static_cast<unsigned int>(val);
91 
92  return buf.str();
93 }
94 
95 
96 void HDF5CFDAPUtil::replace_double_quote(string & str) {
97 
98  const string offend_char = "\"";
99  const string replace_str = "&quote";
100  size_t found_quote = 0;
101  size_t start_pos = 0;
102  while (found_quote != string::npos) {
103  found_quote = str.find(offend_char,start_pos);
104  if (found_quote!= string::npos){
105  str.replace(found_quote,offend_char.size(),replace_str);
106  start_pos = found_quote+1;
107  }
108  }
109 }
110 
111 
112 string HDF5CFDAPUtil::print_type(H5DataType type) {
113 
114  // The list is based on libdap/AttrTable.h.
115  // We added DAP4 INT64 and UINT64 support.
116  string DAPUNSUPPORTED ="Unsupported";
117  string DAPBYTE ="Byte";
118  string DAPINT16 ="Int16";
119  string DAPUINT16 ="Uint16";
120  string DAPINT32 ="Int32";
121  string DAPUINT32 ="Uint32";
122  string DAPFLOAT32 ="Float32";
123  string DAPFLOAT64 ="Float64";
124  string DAP4INT64 ="Int64";
125  string DAP4UINT64 ="UInt64";
126  string DAPSTRING = "String";
127 
128  switch (type) {
129 
130  case H5UCHAR:
131  return DAPBYTE;
132 
133  case H5CHAR:
134  return DAPINT16;
135 
136  case H5INT16:
137  return DAPINT16;
138 
139  case H5UINT16:
140  return DAPUINT16;
141 
142  case H5INT32:
143  return DAPINT32;
144 
145  case H5UINT32:
146  return DAPUINT32;
147 
148  case H5FLOAT32:
149  return DAPFLOAT32;
150 
151  case H5FLOAT64:
152  return DAPFLOAT64;
153 
154  case H5FSTRING:
155  case H5VSTRING:
156  return DAPSTRING;
157  case H5INT64:
158  return DAP4INT64;
159  case H5UINT64:
160  return DAP4UINT64;
161  case H5REFERENCE:
162  case H5COMPOUND:
163  case H5ARRAY:
164  return DAPUNSUPPORTED;
165 
166  default:
167  return DAPUNSUPPORTED;
168  }
169 
170 }
171 
172 D4AttributeType HDF5CFDAPUtil::print_type_dap4(H5DataType type) {
173 
174  switch (type) {
175 
176  case H5UCHAR:
177  return attr_byte_c;
178 
179  case H5CHAR:
180  return attr_int8_c;
181 
182  case H5INT16:
183  return attr_int16_c;
184 
185  case H5UINT16:
186  return attr_uint16_c;
187 
188  case H5INT32:
189  return attr_int32_c;
190 
191  case H5UINT32:
192  return attr_uint32_c;
193 
194  case H5INT64:
195  return attr_int64_c;
196 
197  case H5UINT64:
198  return attr_uint64_c;
199 
200  case H5FLOAT32:
201  return attr_float32_c;
202 
203  case H5FLOAT64:
204  return attr_float64_c;
205 
206  case H5FSTRING:
207  case H5VSTRING:
208  return attr_str_c;
209  case H5REFERENCE:
210  case H5COMPOUND:
211  case H5ARRAY:
212  return attr_null_c;
213 
214  default:
215  return attr_null_c;
216  }
217 
218 }
219 
220 
221 H5DataType
222 HDF5CFDAPUtil::get_mem_dtype(H5DataType dtype,size_t mem_dtype_size ) {
223 
224  // Currently in addition to "char" to "int16", all other memory datatype will be the same as the datatype.
225  // So we have a short cut for this function
226  return ((H5INT16 == dtype) && (1 == mem_dtype_size))?H5CHAR:dtype;
227 }
228 
229 string
230 HDF5CFDAPUtil:: print_attr(H5DataType type, int loc, void *vals)
231 {
232  ostringstream rep;
233 
234  union {
235  unsigned char* ucp;
236  char *cp;
237  short *sp;
238  unsigned short *usp;
239  int *ip;
240  unsigned int *uip;
241  long long *llp;
242  unsigned long long *ullp;
243  float *fp;
244  double *dp;
245  } gp;
246 
247  switch (type) {
248 
249  case H5UCHAR:
250  {
251  unsigned char uc;
252  gp.ucp = (unsigned char *) vals;
253 
254  uc = *(gp.ucp+loc);
255  rep << (int)uc;
256 
257  return rep.str();
258  }
259 
260  case H5CHAR:
261  {
262  gp.cp = (char *) vals;
263  char c;
264  c = *(gp.cp+loc);
265  // Since the character may be a special character and DAP may not be able to represent so supposedly we should escape the character
266  // by calling the escattr function. However, HDF5 native char maps to DAP Int16. So the mapping assumes that users will never
267  // use HDF5 native char or HDF5 unsigned native char to represent characters. Instead HDF5 string should be used to represent characters.
268  // So don't do any escaping of H5CHAR for now. KY 2016-10-14
269  rep <<(int)c;
270  return rep.str();
271  }
272 
273 
274  case H5INT16:
275  {
276  gp.sp = (short *) vals;
277  rep<< *(gp.sp+loc);
278  return rep.str();
279  }
280 
281  case H5UINT16:
282 
283  {
284  gp.usp = (unsigned short *) vals;
285  rep << *(gp.usp+loc);
286  return rep.str();
287  }
288 
289 
290  case H5INT32:
291  {
292  gp.ip = (int *) vals;
293  rep << *(gp.ip+loc);
294  return rep.str();
295  }
296 
297  case H5UINT32:
298  {
299  gp.uip = (unsigned int *) vals;
300  rep << *(gp.uip+loc);
301  return rep.str();
302  }
303  case H5INT64: // For DAP4 CF support only
304  {
305  gp.llp = (long long *) vals;
306  rep << *(gp.llp+loc);
307  return rep.str();
308  }
309 
310  case H5UINT64: // For DAP4 CF support only
311  {
312  gp.ullp = (unsigned long long *) vals;
313  rep << *(gp.ullp+loc);
314  return rep.str();
315  }
316 
317 
318 
319  case H5FLOAT32:
320  {
321  float attr_val = *(float*)vals;
322  bool is_a_fin = isfinite(attr_val);
323  gp.fp = (float *) vals;
324  rep << showpoint;
325  rep << setprecision(10);
326  rep << *(gp.fp+loc);
327  string tmp_rep_str = rep.str();
328  if (tmp_rep_str.find('.') == string::npos
329  && tmp_rep_str.find('e') == string::npos
330  && tmp_rep_str.find('E') == string::npos
331  && (true == is_a_fin)){
332  rep<<".";
333  }
334  return rep.str();
335  }
336 
337  case H5FLOAT64:
338  {
339  double attr_val = *(double*)vals;
340  bool is_a_fin = isfinite(attr_val);
341  gp.dp = (double *) vals;
342  rep << std::showpoint;
343  rep << std::setprecision(17);
344  rep << *(gp.dp+loc);
345  string tmp_rep_str = rep.str();
346  if (tmp_rep_str.find('.') == string::npos
347  && tmp_rep_str.find('e') == string::npos
348  && tmp_rep_str.find('E') == string::npos
349  && (true == is_a_fin)) {
350  rep << ".";
351  }
352  return rep.str();
353  }
354  default:
355  return string("UNKNOWN");
356  }
357 
358 }
359 
360 // This helper function is used for 64-bit integer DAP4 support.
361 // We need to support the attributes of all types for 64-bit integer variables.
362 D4AttributeType HDF5CFDAPUtil::daptype_strrep_to_dap4_attrtype(std::string s){
363 
364  if (s == "Byte")
365  return attr_byte_c;
366  else if (s == "Int8")
367  return attr_int8_c;
368  else if (s == "UInt8") // This may never be used.
369  return attr_uint8_c;
370  else if (s == "Int16")
371  return attr_int16_c;
372  else if (s == "UInt16")
373  return attr_uint16_c;
374  else if (s == "Int32")
375  return attr_int32_c;
376  else if (s == "UInt32")
377  return attr_uint32_c;
378  else if (s == "Int64")
379  return attr_int64_c;
380  else if (s == "UInt64")
381  return attr_uint64_c;
382  else if (s == "Float32")
383  return attr_float32_c;
384  else if (s == "Float64")
385  return attr_float64_c;
386  else if (s == "String")
387  return attr_str_c;
388  else if (s == "Url")
389  return attr_url_c;
390  else
391  return attr_null_c;
392 
393 
394 }
395 
396 
static string escattr(string s)
Definition: h5cfdaputil.cc:52
static string octstring(unsigned char val)
Helper function for escattr.
Definition: h5cfdaputil.cc:86
static D4AttributeType daptype_strrep_to_dap4_attrtype(std::string s)
Definition: h5cfdaputil.cc:362
Helper functions for generating DAS attributes and a function to check BES Key.