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 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 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 /************************************************************************/ 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 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 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 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 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