1 /******************************************************************************
2 *
3 * Project: Hierarchical Data Format Release 5 (HDF5)
4 * Purpose: HDF5 convenience functions.
5 * Author: Frank Warmerdam <warmerdam@pobox.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "gh5_convenience.h"
30
31 CPL_CVSID("$Id: gh5_convenience.cpp dda7615faa9123735ff5ee6b07418b4abb87c324 2020-05-11 01:42:04 +0200 Even Rouault $")
32
33 /************************************************************************/
34 /* GH5_FetchAttribute(CPLString) */
35 /************************************************************************/
36
GH5_FetchAttribute(hid_t loc_id,const char * pszAttrName,CPLString & osResult,bool bReportError)37 bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
38 CPLString &osResult, bool bReportError )
39
40 {
41 if( !bReportError && H5Aexists(loc_id, pszAttrName) <= 0 )
42 {
43 return false;
44 }
45
46 hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
47
48 osResult.clear();
49
50 if( hAttr < 0 )
51 {
52 if( bReportError )
53 CPLError(CE_Failure, CPLE_AppDefined,
54 "Attempt to read attribute %s failed, not found.",
55 pszAttrName);
56 return false;
57 }
58
59 const hid_t hAttrSpace = H5Aget_space(hAttr);
60 hsize_t anSize[H5S_MAX_RANK] = {};
61 const unsigned int nAttrDims =
62 H5Sget_simple_extent_dims(hAttrSpace, anSize, nullptr);
63 if( nAttrDims != 0 && !(nAttrDims == 1 && anSize[0] == 1) )
64 {
65 H5Sclose(hAttrSpace);
66 H5Aclose(hAttr);
67 return false;
68 }
69
70 hid_t hAttrTypeID = H5Aget_type(hAttr);
71 hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
72
73 bool retVal = false;
74 if( H5Tget_class(hAttrNativeType) == H5T_STRING )
75 {
76 if ( H5Tis_variable_str(hAttrNativeType) )
77 {
78 char* aszBuffer[1] = { nullptr };
79 H5Aread(hAttr, hAttrNativeType, aszBuffer);
80
81 if( aszBuffer[0] )
82 osResult = aszBuffer[0];
83
84 H5Dvlen_reclaim(hAttrNativeType, hAttrSpace, H5P_DEFAULT,
85 aszBuffer);
86 }
87 else
88 {
89 const size_t nAttrSize = H5Tget_size(hAttrTypeID);
90 char *pachBuffer = static_cast<char *>(CPLCalloc(nAttrSize + 1, 1));
91 H5Aread(hAttr, hAttrNativeType, pachBuffer);
92
93 osResult = pachBuffer;
94 CPLFree(pachBuffer);
95 }
96
97 retVal = true;
98 }
99 else
100 {
101 if( bReportError )
102 CPLError(
103 CE_Failure, CPLE_AppDefined,
104 "Attribute %s of unsupported type for conversion to string.",
105 pszAttrName);
106
107 retVal = false;
108 }
109
110 H5Sclose(hAttrSpace);
111 H5Tclose(hAttrNativeType);
112 H5Tclose(hAttrTypeID);
113 H5Aclose(hAttr);
114 return retVal;
115 }
116
117 /************************************************************************/
118 /* GH5_FetchAttribute(double) */
119 /************************************************************************/
120
GH5_FetchAttribute(hid_t loc_id,const char * pszAttrName,double & dfResult,bool bReportError)121 bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
122 double &dfResult, bool bReportError )
123
124 {
125 if( !bReportError && H5Aexists(loc_id, pszAttrName) <= 0 )
126 {
127 return false;
128 }
129
130 const hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
131
132 dfResult = 0.0;
133 if( hAttr < 0 )
134 {
135 if( bReportError )
136 CPLError(CE_Failure, CPLE_AppDefined,
137 "Attempt to read attribute %s failed, not found.",
138 pszAttrName);
139 return false;
140 }
141
142 hid_t hAttrTypeID = H5Aget_type(hAttr);
143 hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
144
145 // Confirm that we have a single element value.
146 hid_t hAttrSpace = H5Aget_space(hAttr);
147 hsize_t anSize[H5S_MAX_RANK] = {};
148 int nAttrDims = H5Sget_simple_extent_dims(hAttrSpace, anSize, nullptr);
149
150 int i, nAttrElements = 1;
151
152 for( i = 0; i < nAttrDims; i++ )
153 {
154 nAttrElements *= (int)anSize[i];
155 }
156
157 if( nAttrElements != 1 )
158 {
159 if( bReportError )
160 CPLError(CE_Failure, CPLE_AppDefined,
161 "Attempt to read attribute %s failed, count=%d, not 1.",
162 pszAttrName, nAttrElements);
163
164 H5Sclose(hAttrSpace);
165 H5Tclose(hAttrNativeType);
166 H5Tclose(hAttrTypeID);
167 H5Aclose(hAttr);
168 return false;
169 }
170
171 // Read the value.
172 void *buf = CPLMalloc(H5Tget_size(hAttrNativeType));
173 H5Aread(hAttr, hAttrNativeType, buf);
174
175 // Translate to double.
176 if( H5Tequal(H5T_NATIVE_SHORT, hAttrNativeType) )
177 dfResult = *((short *)buf);
178 else if( H5Tequal(H5T_NATIVE_INT, hAttrNativeType) )
179 dfResult = *((int *)buf);
180 else if( H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType) )
181 dfResult = *((float *)buf);
182 else if( H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType) )
183 dfResult = *((double *)buf);
184 else
185 {
186 if( bReportError )
187 CPLError(
188 CE_Failure, CPLE_AppDefined,
189 "Attribute %s of unsupported type for conversion to double.",
190 pszAttrName);
191 CPLFree(buf);
192
193 H5Sclose(hAttrSpace);
194 H5Tclose(hAttrNativeType);
195 H5Tclose(hAttrTypeID);
196 H5Aclose(hAttr);
197
198 return false;
199 }
200
201 CPLFree(buf);
202
203 H5Sclose(hAttrSpace);
204 H5Tclose(hAttrNativeType);
205 H5Tclose(hAttrTypeID);
206 H5Aclose(hAttr);
207 return true;
208 }
209
210 /************************************************************************/
211 /* GH5_GetDataType() */
212 /* */
213 /* Transform HDF5 datatype to GDAL datatype */
214 /************************************************************************/
GH5_GetDataType(hid_t TypeID)215 GDALDataType GH5_GetDataType(hid_t TypeID)
216 {
217 if( H5Tequal(H5T_NATIVE_CHAR, TypeID) )
218 return GDT_Byte;
219 else if( H5Tequal(H5T_NATIVE_SCHAR, TypeID) )
220 return GDT_Byte;
221 else if( H5Tequal(H5T_NATIVE_UCHAR, TypeID) )
222 return GDT_Byte;
223 else if( H5Tequal(H5T_NATIVE_SHORT, TypeID) )
224 return GDT_Int16;
225 else if( H5Tequal(H5T_NATIVE_USHORT, TypeID) )
226 return GDT_UInt16;
227 else if( H5Tequal(H5T_NATIVE_INT, TypeID) )
228 return GDT_Int32;
229 else if( H5Tequal(H5T_NATIVE_UINT, TypeID) )
230 return GDT_UInt32;
231 else if( H5Tequal(H5T_NATIVE_LONG, TypeID) )
232 {
233 #if SIZEOF_UNSIGNED_LONG == 4
234 return GDT_Int32;
235 #else
236 return GDT_Unknown;
237 #endif
238 }
239 else if( H5Tequal(H5T_NATIVE_ULONG, TypeID) )
240 {
241 #if SIZEOF_UNSIGNED_LONG == 4
242 return GDT_UInt32;
243 #else
244 return GDT_Unknown;
245 #endif
246 }
247 else if( H5Tequal(H5T_NATIVE_FLOAT, TypeID) )
248 return GDT_Float32;
249 else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
250 return GDT_Float64;
251 #ifdef notdef
252 else if( H5Tequal(H5T_NATIVE_LLONG, TypeID) )
253 return GDT_Unknown;
254 else if( H5Tequal(H5T_NATIVE_ULLONG, TypeID) )
255 return GDT_Unknown;
256 #endif
257
258 return GDT_Unknown;
259 }
260
261 /************************************************************************/
262 /* GH5_CreateAttribute() */
263 /************************************************************************/
264
GH5_CreateAttribute(hid_t loc_id,const char * pszAttrName,hid_t TypeID,unsigned nMaxLen)265 bool GH5_CreateAttribute (hid_t loc_id, const char *pszAttrName,
266 hid_t TypeID, unsigned nMaxLen)
267 {
268 #ifdef notdef_write_variable_length_string
269 if (TypeID == H5T_C_S1)
270 {
271 hsize_t dims[1] = {1};
272 hid_t dataspace = H5Screate_simple(1, dims, nullptr);
273 hid_t type = H5Tcopy(TypeID);
274 H5Tset_size (type, H5T_VARIABLE);
275 hid_t att = H5Acreate(loc_id,pszAttrName, type, dataspace, H5P_DEFAULT);
276 H5Tclose(type);
277 H5Aclose(att);
278 H5Sclose(dataspace);
279 return true;
280 }
281 #endif
282
283 hid_t hDataSpace = H5Screate(H5S_SCALAR);
284 if (hDataSpace < 0)
285 return false;
286
287 hid_t hDataType = H5Tcopy(TypeID);
288 if (hDataType < 0)
289 {
290 H5Sclose (hDataSpace);
291 return false;
292 }
293
294 if (TypeID == H5T_C_S1)
295 {
296 if( H5Tset_size(hDataType, nMaxLen) < 0 )
297 {
298 H5Tclose(hDataType);
299 H5Sclose(hDataSpace);
300 return false;
301 }
302 }
303
304 hid_t hAttr = H5Acreate(loc_id, pszAttrName,
305 hDataType, hDataSpace, H5P_DEFAULT);
306 if (hAttr < 0)
307 {
308 H5Sclose(hDataSpace);
309 H5Tclose(hDataType);
310 return false;
311 }
312
313 H5Aclose(hAttr);
314 H5Sclose(hDataSpace);
315 H5Tclose(hDataType);
316
317 return true;
318 }
319
320 /************************************************************************/
321 /* GH5_WriteAttribute() */
322 /************************************************************************/
323
GH5_WriteAttribute(hid_t loc_id,const char * pszAttrName,const char * pszValue)324 bool GH5_WriteAttribute (hid_t loc_id, const char *pszAttrName,
325 const char* pszValue)
326 {
327
328 hid_t hAttr = H5Aopen_name (loc_id, pszAttrName);
329 if (hAttr < 0)
330 return false;
331
332 hid_t hDataType = H5Aget_type (hAttr);
333 if (hDataType < 0)
334 {
335 H5Aclose (hAttr);
336 return false;
337 }
338
339 hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
340 bool bSuccess = false;
341 if( H5Tget_class(hAttrNativeType) == H5T_STRING )
342 {
343 #ifdef notdef_write_variable_length_string
344 bSuccess = H5Awrite(hAttr, hDataType, &pszValue) >= 0;
345 #else
346 bSuccess = H5Awrite(hAttr, hDataType, pszValue) >= 0;
347 #endif
348 }
349 else
350 {
351 CPLError(CE_Failure, CPLE_AppDefined,
352 "Attribute %s is not of type string", pszAttrName);
353 }
354
355 H5Tclose(hAttrNativeType);
356 H5Tclose(hDataType);
357 H5Aclose(hAttr);
358
359 return bSuccess;
360 }
361
362 /************************************************************************/
363 /* GH5_WriteAttribute() */
364 /************************************************************************/
365
GH5_WriteAttribute(hid_t loc_id,const char * pszAttrName,double dfValue)366 bool GH5_WriteAttribute (hid_t loc_id, const char *pszAttrName,
367 double dfValue)
368 {
369
370 hid_t hAttr = H5Aopen_name (loc_id, pszAttrName);
371 if (hAttr < 0)
372 return false;
373
374 hid_t hDataType = H5Aget_type (hAttr);
375 if (hDataType < 0)
376 {
377 H5Aclose (hAttr);
378 return false;
379 }
380
381 hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
382 bool bSuccess = false;
383 if( H5Tequal(hAttrNativeType, H5T_NATIVE_FLOAT) )
384 {
385 float fVal = static_cast<float>(dfValue);
386 bSuccess = H5Awrite(hAttr, hAttrNativeType, &fVal) >= 0;
387 }
388 else if( H5Tequal(hAttrNativeType, H5T_NATIVE_DOUBLE) )
389 {
390 bSuccess = H5Awrite(hAttr, hAttrNativeType, &dfValue) >= 0;
391 }
392 else
393 {
394 CPLError(CE_Failure, CPLE_AppDefined,
395 "Attribute %s is not of type float or double", pszAttrName);
396 }
397
398 H5Tclose(hAttrNativeType);
399 H5Aclose(hAttr);
400 H5Tclose(hDataType);
401
402 return bSuccess;
403 }
404
405 /************************************************************************/
406 /* GH5_WriteAttribute() */
407 /************************************************************************/
408
GH5_WriteAttribute(hid_t loc_id,const char * pszAttrName,unsigned nValue)409 bool GH5_WriteAttribute (hid_t loc_id, const char *pszAttrName,
410 unsigned nValue)
411 {
412
413 hid_t hAttr = H5Aopen_name (loc_id, pszAttrName);
414 if (hAttr < 0)
415 return false;
416
417 hid_t hDataType = H5Aget_type (hAttr);
418 if (hDataType < 0)
419 {
420 H5Aclose (hAttr);
421 return false;
422 }
423
424 hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
425 bool bSuccess = false;
426 if( H5Tequal(hAttrNativeType, H5T_NATIVE_INT) ||
427 H5Tequal(hAttrNativeType, H5T_NATIVE_UINT) )
428 {
429 bSuccess = H5Awrite(hAttr, hAttrNativeType, &nValue) >= 0;
430 }
431 else
432 {
433 CPLError(CE_Failure, CPLE_AppDefined,
434 "Attribute %s is not of type int/uint", pszAttrName);
435 }
436
437 H5Tclose(hAttrNativeType);
438 H5Aclose(hAttr);
439 H5Tclose(hDataType);
440
441 return bSuccess;
442 }
443