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
40using namespace std;
41using 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
52string 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.
85string
86HDF5CFDAPUtil::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
96void 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
112string 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
172D4AttributeType 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
221H5DataType
222HDF5CFDAPUtil::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
229string
230HDF5CFDAPUtil:: 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.
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.