001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h5; 016 017import java.lang.reflect.Array; 018import java.math.BigDecimal; 019import java.math.BigInteger; 020import java.math.MathContext; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.BitSet; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.List; 027import java.util.Map.Entry; 028import java.util.Objects; 029import java.util.Vector; 030 031import hdf.object.Attribute; 032import hdf.object.CompoundDS; 033import hdf.object.Datatype; 034import hdf.object.FileFormat; 035import hdf.object.h5.H5MetaDataContainer; 036 037import hdf.hdf5lib.H5; 038import hdf.hdf5lib.HDF5Constants; 039import hdf.hdf5lib.HDFArray; 040import hdf.hdf5lib.HDFNativeData; 041import hdf.hdf5lib.exceptions.HDF5Exception; 042import hdf.hdf5lib.exceptions.HDF5LibraryException; 043import hdf.hdf5lib.structs.H5O_info_t; 044import hdf.hdf5lib.structs.H5O_token_t; 045 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049/** 050 * This class defines HDF5 datatype characteristics and APIs for a data type. This class provides several 051 * methods to convert an HDF5 datatype identifier to a datatype object, and vice versa. A datatype object is 052 * described by four basic fields: datatype class, size, byte order, and sign, while an HDF5 datatype is 053 * presented by a datatype identifier. 054 * 055 * @version 1.1 9/4/2007 056 * @author Peter X. Cao 057 */ 058public class H5Datatype extends Datatype { 059 private static final long serialVersionUID = -750546422258749792L; 060 061 private static final Logger log = LoggerFactory.getLogger(H5Datatype.class); 062 063 /** 064 * The metadata object for this data object. Members of the metadata are instances of Attribute. 065 */ 066 private H5MetaDataContainer objMetadata; 067 068 /** 069 * The dimension sizes of the reference object 070 */ 071 protected long[] refdims; 072 073 /** the datatype is an object reference */ 074 private boolean isRefObj = false; 075 076 /** the datatype is a region reference */ 077 private boolean isRegRef = false; 078 079 /** the datatype is a standard reference */ 080 private boolean isStdRef = false; 081 082 /** the object properties */ 083 private H5O_info_t objInfo; 084 085 /** 086 * The native class of the datatype. 087 */ 088 private int nativeClass = -1; 089 090 /** The native Precision properties of the number datatype. */ 091 private long nativePrecision = 0; 092 /** The native Offset properties of the number datatype. */ 093 private int nativeOffset = -1; 094 /** The native PadLSB properties of the number datatype. */ 095 private int nativePadLSB = -1; 096 /** The native PadMSB properties of the number datatype. */ 097 private int nativePadMSB = -1; 098 099 /** The native ebias properties of the float datatype. */ 100 private long nativeFPebias = 0; 101 /** The native spos properties of the float datatype. */ 102 private long nativeFPspos = -1; 103 /** The native epos properties of the float datatype. */ 104 private long nativeFPepos = -1; 105 /** The native esize properties of the float datatype. */ 106 private long nativeFPesize = -1; 107 /** The native mpos properties of the float datatype. */ 108 private long nativeFPmpos = -1; 109 /** The native msize properties of the float datatype. */ 110 private long nativeFPmsize = -1; 111 /** The native norm properties of the float datatype. */ 112 private int nativeFPnorm = -1; 113 /** The native inpad properties of the float datatype. */ 114 private int nativeFPinpad = -1; 115 116 /** The native padding properties of the string datatype. */ 117 private int nativeStrPad = -1; 118 /** The native CSET properties of the string datatype. */ 119 private int nativeStrCSET = -1; 120 121 /** 122 * The tag for an opaque datatype. 123 */ 124 private String opaqueTag = null; 125 126 /** 127 * Constructs an named HDF5 data type object for a given file, dataset name and group path. The datatype 128 * object represents an existing named datatype in file. For example, 129 * 130 * <pre> 131 * new H5Datatype(file, "dtype1", "/g0") 132 * </pre> 133 * 134 * constructs a datatype object that corresponds to the dataset,"dset1", at group "/g0". 135 * 136 * @param theFile 137 * the file that contains the datatype. 138 * @param theName 139 * the name of the dataset such as "dset1". 140 * @param thePath 141 * the group path to the dataset such as "/g0/". 142 */ 143 public H5Datatype(FileFormat theFile, String theName, String thePath) 144 { 145 this(theFile, theName, thePath, null); 146 } 147 148 /** 149 * @deprecated Not for public use in the future. <br> 150 * Using {@link #H5Datatype(FileFormat, String, String)} 151 * @param theFile 152 * the file that contains the datatype. 153 * @param theName 154 * the name of the dataset such as "dset1". 155 * @param thePath 156 * the group path to the dataset such as "/g0/". 157 * @param oid 158 * the oid of the dataset. 159 */ 160 @Deprecated 161 public H5Datatype(FileFormat theFile, String theName, String thePath, long[] oid) 162 { 163 super(theFile, theName, thePath, oid); 164 objMetadata = new H5MetaDataContainer(theFile, theName, thePath, this); 165 166 if (theFile != null) { 167 if (oid == null) { 168 // retrieve the object ID 169 byte[] refBuf = null; 170 try { 171 refBuf = 172 H5.H5Rcreate_object(theFile.getFID(), this.getFullName(), HDF5Constants.H5P_DEFAULT); 173 this.oid = HDFNativeData.byteToLong(refBuf); 174 log.trace("constructor REF {} to OID {}", refBuf, this.oid); 175 } 176 catch (Exception ex) { 177 log.debug("constructor ID {} for {} failed H5Rcreate_object", theFile.getFID(), 178 this.getFullName()); 179 } 180 finally { 181 if (refBuf != null) 182 H5.H5Rdestroy(refBuf); 183 } 184 } 185 log.trace("constructor OID {}", this.oid); 186 try { 187 objInfo = H5.H5Oget_info_by_name(theFile.getFID(), this.getFullName(), 188 HDF5Constants.H5O_INFO_BASIC, HDF5Constants.H5P_DEFAULT); 189 } 190 catch (Exception ex) { 191 objInfo = new H5O_info_t(-1L, null, 0, 0, 0L, 0L, 0L, 0L, 0L); 192 } 193 194 long tid = HDF5Constants.H5I_INVALID_HID; 195 try { 196 tid = open(); 197 } 198 catch (Exception ex) { 199 log.debug("constructor H5Topen() failure"); 200 } 201 finally { 202 close(tid); 203 } 204 } 205 else { 206 this.oid = null; 207 objInfo = new H5O_info_t(-1L, null, 0, 0, 0L, 0L, 0L, 0L, 0L); 208 } 209 } 210 211 /** 212 * Constructs a Datatype with specified class, size, byte order and sign. The following is a list of a few 213 * examples of H5Datatype. <ol> <li>to create unsigned native integer<br> H5Datatype type = new 214 * H5Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE); <li>to create 215 * 16-bit signed integer with big endian<br> H5Datatype type = new H5Dataype(Datatype.CLASS_INTEGER, 2, 216 * Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> H5Datatype type = new 217 * H5Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); <li>to create 218 * 64-bit double<br> H5Datatype type = new H5Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, 219 * Datatype.NATIVE); 220 * </ol> 221 * 222 * @param tclass 223 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 224 * @param tsize 225 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. Valid values 226 * are NATIVE or a positive value. For string datatypes, -1 is also a valid value (to create a 227 * variable-length string). 228 * @param torder 229 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 230 * ORDER_NONE and NATIVE. 231 * @param tsign 232 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 233 * @throws Exception 234 * if there is an error 235 */ 236 public H5Datatype(int tclass, int tsize, int torder, int tsign) throws Exception 237 { 238 this(tclass, tsize, torder, tsign, null); 239 } 240 241 /** 242 * Constructs a Datatype with specified class, size, byte order and sign. The following is a list of a few 243 * examples of H5Datatype. <ol> <li>to create unsigned native integer<br> H5Datatype type = new 244 * H5Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE); <li>to create 245 * 16-bit signed integer with big endian<br> H5Datatype type = new H5Dataype(Datatype.CLASS_INTEGER, 2, 246 * Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> H5Datatype type = new 247 * H5Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); <li>to create 248 * 64-bit double<br> H5Datatype type = new H5Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, 249 * Datatype.NATIVE); 250 * </ol> 251 * 252 * @param tclass 253 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 254 * @param tsize 255 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. Valid values 256 * are NATIVE or a positive value. For string datatypes, -1 is also a valid value (to create a 257 * variable-length string). 258 * @param torder 259 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 260 * ORDER_NONE and NATIVE. 261 * @param tsign 262 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 263 * @param tbase 264 * the base datatype of the new datatype 265 * @throws Exception 266 * if there is an error 267 */ 268 public H5Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) throws Exception 269 { 270 this(tclass, tsize, torder, tsign, tbase, null); 271 } 272 273 /** 274 * Constructs a Datatype with specified class, size, byte order and sign. The following is a list of a few 275 * examples of H5Datatype. <ol> <li>to create unsigned native integer<br> H5Datatype type = new 276 * H5Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE); <li>to create 277 * 16-bit signed integer with big endian<br> H5Datatype type = new H5Dataype(Datatype.CLASS_INTEGER, 2, 278 * Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> H5Datatype type = new 279 * H5Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); <li>to create 280 * 64-bit double<br> H5Datatype type = new H5Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, 281 * Datatype.NATIVE); 282 * </ol> 283 * 284 * @param tclass 285 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 286 * @param tsize 287 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. Valid values 288 * are NATIVE or a positive value. For string datatypes, -1 is also a valid value (to create a 289 * variable-length string). 290 * @param torder 291 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 292 * ORDER_NONE and NATIVE. 293 * @param tsign 294 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 295 * @param tbase 296 * the base datatype of the new datatype 297 * @param pbase 298 * the parent datatype of the new datatype 299 * @throws Exception 300 * if there is an error 301 */ 302 public H5Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase, Datatype pbase) 303 throws Exception 304 { 305 super(tclass, tsize, torder, tsign, tbase, pbase); 306 datatypeDescription = getDescription(); 307 } 308 309 /** 310 * Constructs a Datatype with a given native datatype identifier. For example, if the datatype identifier 311 * is a 32-bit unsigned integer created from HDF5, 312 * 313 * <pre> 314 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 315 * Datatype dtype = new Datatype(tid); 316 * </pre> 317 * 318 * will construct a datatype equivalent to new Datatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, 319 * Datatype.SIGN_NONE); 320 * 321 * @see #fromNative(long nativeID) 322 * @param theFile 323 * the file that contains the datatype. 324 * @param nativeID 325 * the native datatype identifier. 326 * @throws Exception 327 * if there is an error 328 */ 329 public H5Datatype(FileFormat theFile, long nativeID) throws Exception { this(theFile, nativeID, null); } 330 331 /** 332 * Constructs a Datatype with a given native datatype identifier. For example, if the datatype identifier 333 * is a 32-bit unsigned integer created from HDF5, 334 * 335 * <pre> 336 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 337 * Datatype dtype = new Datatype(tid); 338 * </pre> 339 * 340 * will construct a datatype equivalent to new Datatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, 341 * Datatype.SIGN_NONE); 342 * 343 * @see #fromNative(long nativeID) 344 * @param theFile 345 * the file that contains the datatype. 346 * @param nativeID 347 * the native datatype identifier. 348 * @param pbase 349 * the parent datatype of the new datatype 350 * @throws Exception 351 * if there is an error 352 */ 353 public H5Datatype(FileFormat theFile, long nativeID, Datatype pbase) throws Exception 354 { 355 super(theFile, nativeID, pbase); 356 fromNative(nativeID); 357 datatypeDescription = getDescription(); 358 } 359 360 /** 361 * Opens access to a named datatype. It calls H5.H5Topen(loc, name). 362 * 363 * @return the datatype identifier if successful; otherwise returns negative value. 364 * @see hdf.hdf5lib.H5#H5Topen(long, String, long) 365 */ 366 @Override 367 public long open() 368 { 369 long tid = HDF5Constants.H5I_INVALID_HID; 370 371 if (fileFormat != null) { 372 try { 373 tid = H5.H5Topen(getFID(), getFullName(), HDF5Constants.H5P_DEFAULT); 374 fromNative(tid); 375 log.trace("open(): tid={}", tid); 376 } 377 catch (HDF5Exception ex) { 378 log.debug("open(): Failed to open datatype {}", getFullName(), ex); 379 tid = HDF5Constants.H5I_INVALID_HID; 380 } 381 } 382 383 return tid; 384 } 385 386 /** 387 * Closes a datatype identifier. It calls H5.H5close(tid). 388 * 389 * @param tid 390 * the datatype ID to close 391 */ 392 @Override 393 public void close(long tid) 394 { 395 if (tid >= 0) { 396 try { 397 H5.H5Tclose(tid); 398 } 399 catch (HDF5Exception ex) { 400 log.debug("close(): H5Tclose(tid {}) failure: ", tid, ex); 401 } 402 } 403 } 404 405 /** 406 * Get the token for this object. 407 * 408 * @return true if it has any attributes, false otherwise. 409 */ 410 public long[] getToken() 411 { 412 H5O_token_t token = objInfo.token; 413 return HDFNativeData.byteToLong(token.data); 414 } 415 416 /** 417 * Check if the object has any attributes attached. 418 * 419 * @return true if it has any attributes, false otherwise. 420 */ 421 @Override 422 public boolean hasAttribute() 423 { 424 objInfo.num_attrs = objMetadata.getObjectAttributeSize(); 425 426 if (objInfo.num_attrs < 0) { 427 long tid = open(); 428 if (tid > 0) { 429 try { 430 objInfo = H5.H5Oget_info(tid); 431 } 432 catch (Exception ex) { 433 objInfo.num_attrs = 0; 434 log.debug("hasAttribute(): get object info failure: ", ex); 435 } 436 finally { 437 close(tid); 438 } 439 objMetadata.setObjectAttributeSize((int)objInfo.num_attrs); 440 } 441 else { 442 log.debug("hasAttribute(): could not open group"); 443 } 444 } 445 446 log.trace("hasAttribute(): nAttributes={}", objInfo.num_attrs); 447 return (objInfo.num_attrs > 0); 448 } 449 450 /** 451 * Converts values in an Enumeration Datatype to names. This method searches the identified enumeration 452 * datatype for the values appearing in <code>inValues</code> and returns the names corresponding to those 453 * values. If a given value is not found in the enumeration datatype, the name corresponding to that value 454 * will be set to <code>"ENUM ERR value"</code> in the string array that is returned. If the method fails 455 * in general, null will be returned instead of a String array. An empty <code>inValues</code> parameter 456 * would cause general failure. 457 * 458 * @param inValues 459 * The array of enumerations values to be converted. 460 * @return The string array of names if successful; otherwise return null. 461 * @throws HDF5Exception 462 * If there is an error at the HDF5 library level. 463 */ 464 public String[] convertEnumValueToName(Object inValues) throws HDF5Exception 465 { 466 log.trace("convertEnumValueToName() inValues={} start", inValues); 467 468 if (inValues == null) { 469 log.debug("convertEnumValueToName() failure: in values null "); 470 return null; 471 } 472 473 int inSize = 0; 474 String[] outNames = null; 475 String cName = inValues.getClass().getName(); 476 boolean isArray = cName.lastIndexOf('[') >= 0; 477 if (isArray) 478 inSize = Array.getLength(inValues); 479 else 480 inSize = 1; 481 482 if (inSize <= 0) { 483 log.debug("convertEnumValueToName() failure: inSize length invalid"); 484 log.debug("convertEnumValueToName(): inValues={} inSize={}", inValues, inSize); 485 return null; 486 } 487 488 if (enumMembers == null || enumMembers.size() <= 0) { 489 log.debug("convertEnumValueToName(): no members"); 490 return null; 491 } 492 493 log.trace("convertEnumValueToName(): inSize={} nMembers={} enums={}", inSize, enumMembers.size(), 494 enumMembers); 495 outNames = new String[inSize]; 496 for (int i = 0; i < inSize; i++) { 497 if (isArray) { 498 if (enumMembers.containsKey(String.valueOf(Array.get(inValues, i)))) 499 outNames[i] = enumMembers.get(String.valueOf(Array.get(inValues, i))); 500 else 501 outNames[i] = "**ENUM ERR " + Array.get(inValues, i) + "**"; 502 } 503 else { 504 if (enumMembers.containsKey(String.valueOf(inValues))) 505 outNames[i] = enumMembers.get(String.valueOf(inValues)); 506 else 507 outNames[i] = "**ENUM ERR " + inValues + "**"; 508 } 509 } 510 511 return outNames; 512 } 513 514 /** 515 * Converts names in an Enumeration Datatype to values. This method searches the identified enumeration 516 * datatype for the names appearing in <code>inValues</code> and returns the values corresponding to those 517 * names. 518 * 519 * @param in 520 * The array of enumerations names to be converted. 521 * @return The int array of values if successful; otherwise return null. 522 * @throws HDF5Exception 523 * If there is an error at the HDF5 library level. 524 */ 525 public Object[] convertEnumNameToValue(String[] in) throws HDF5Exception 526 { 527 int size = 0; 528 529 if (in == null) { 530 log.debug("convertEnumNameToValue() failure: in values null"); 531 return null; 532 } 533 534 if ((size = Array.getLength(in)) <= 0) { 535 log.debug("convertEnumNameToValue() failure: in size not valid"); 536 return null; 537 } 538 539 if (enumMembers == null || enumMembers.size() <= 0) { 540 log.debug("convertEnumNameToValue(): no members"); 541 return null; 542 } 543 544 Object[] out = null; 545 if (datatypeSize == 1) 546 out = new Byte[size]; 547 else if (datatypeSize == 2) 548 out = new Short[size]; 549 else if (datatypeSize == 4) 550 out = new Integer[size]; 551 else if (datatypeSize == 8) 552 out = new Long[size]; 553 else 554 out = new Object[size]; 555 556 for (int i = 0; i < size; i++) { 557 if (in[i] == null || in[i].length() <= 0) 558 continue; 559 560 for (Entry<String, String> entry : enumMembers.entrySet()) { 561 if (Objects.equals(in[i], entry.getValue())) { 562 if (datatypeSize == 1) { 563 log.trace("convertEnumNameToValue(): ENUM is H5T_NATIVE_INT8"); 564 out[i] = Byte.parseByte(entry.getKey()); 565 } 566 else if (datatypeSize == 2) { 567 log.trace("convertEnumNameToValue(): CLASS_INT-ENUM is H5T_NATIVE_INT16"); 568 out[i] = Short.parseShort(entry.getKey()); 569 } 570 else if (datatypeSize == 4) { 571 log.trace("convertEnumNameToValue(): CLASS_INT-ENUM is H5T_NATIVE_INT32"); 572 out[i] = Integer.parseInt(entry.getKey()); 573 } 574 else if (datatypeSize == 8) { 575 log.trace("convertEnumNameToValue(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 576 out[i] = Long.parseLong(entry.getKey()); 577 } 578 else { 579 log.debug("convertEnumNameToValue(): enum datatypeSize incorrect"); 580 out[i] = -1; 581 } 582 break; 583 } 584 } 585 } 586 587 return out; 588 } 589 590 /** 591 * Convert from an array of BigDecimal into an array of bytes 592 * 593 * @param start 594 * The position in the input array of BigDecimal to start 595 * @param len 596 * The number of 'BigDecimal' to convert 597 * @param data 598 * The input array of BigDecimal 599 * @return an array of bytes 600 */ 601 public byte[] bigDecimalToByte(int start, int len, BigDecimal[] data) 602 { 603 int ii; 604 byte[] bd = new byte[(int)datatypeSize]; 605 byte[] bdconv = new byte[(int)datatypeSize]; 606 byte[] bdbytes = new byte[(int)datatypeSize * len]; 607 608 for (ii = 0; ii < len; ii++) { 609 BigDecimal entry = data[start + ii]; 610 bdconv = convertBigDecimalToByte(entry); 611 /* bitsets operate assuming LE order, BigInteger/BigDecimal expect BE */ 612 if (datatypeOrder == ORDER_BE) { 613 int k = 0; 614 for (int j = (int)datatypeSize - 1; j >= 0; j--) 615 bd[k++] = bdconv[j]; 616 } 617 else { 618 try { 619 System.arraycopy(bdconv, 0, bd, 0, (int)datatypeSize); 620 } 621 catch (Exception err) { 622 log.trace("bigDecimalToByte(): arraycopy failure: ", err); 623 } 624 } 625 try { 626 System.arraycopy(bd, 0, bdbytes, ii * 16, 16); 627 } 628 catch (Exception err) { 629 log.trace("bigDecimalToByte(): arraycopy failure: ", err); 630 } 631 } 632 return bdbytes; 633 } 634 635 /** 636 * Convert from a single BigDecimal object from an array of BigDecimal into an array of bytes 637 * 638 * @param start 639 * The position in the input array of BigDecimal to start 640 * @param data 641 * The input Float 642 * @return an array of bytes 643 */ 644 public byte[] bigDecimalToByte(BigDecimal[] data, int start) 645 { 646 byte[] bdbytes = new byte[(int)datatypeSize]; 647 bdbytes = bigDecimalToByte(start, 1, data); 648 return bdbytes; 649 } 650 651 /** 652 * Convert a BigDecimal to a byte array . 653 * 654 * @param num 655 * The BigDecimal number to convert 656 * @return A byte array representing the BigDecimal. 657 */ 658 public byte[] convertBigDecimalToByte(BigDecimal num) 659 { 660 BigInteger sig = new BigInteger(num.unscaledValue().toString()); 661 byte[] bsig = sig.toByteArray(); 662 int scale = num.scale(); 663 byte[] bscale = 664 new byte[] {(byte)(scale >>> 24), (byte)(scale >>> 16), (byte)(scale >>> 8), (byte)(scale)}; 665 byte[] both = new byte[bscale.length + bsig.length]; 666 try { 667 System.arraycopy(bscale, 0, both, 0, bscale.length); 668 System.arraycopy(bsig, 0, both, bscale.length, bsig.length); 669 } 670 catch (Exception err) { 671 log.trace("convertBigDecimalToByte(): arraycopy failure: ", err); 672 } 673 return both; 674 } 675 676 /** 677 * Convert a range from an array of bytes into an array of BigDecimal 678 * 679 * @param start 680 * The position in the input array of bytes to start 681 * @param len 682 * The number of 'BigDecimal' to convert 683 * @param data 684 * The input array of bytes 685 * @return an array of 'len' BigDecimal 686 */ 687 public BigDecimal[] byteToBigDecimal(int start, int len, byte[] data) 688 { 689 int ii; 690 byte[] bd = new byte[(int)datatypeSize]; 691 BigDecimal[] BDarray = new BigDecimal[len]; 692 693 for (ii = 0; ii < len; ii++) { 694 int rawpos = (start + ii) * (int)datatypeSize; 695 /* bitsets operate assuming LE order, BigInteger/BigDecimal expect BE */ 696 if (datatypeOrder == ORDER_BE) { 697 int k = 0; 698 for (int j = (int)datatypeSize - 1; j >= 0; j--) 699 bd[k++] = data[rawpos + j]; 700 } 701 else { 702 try { 703 System.arraycopy(data, rawpos, bd, 0, (int)datatypeSize); 704 } 705 catch (Exception err) { 706 log.trace("byteToBigDecimal(): arraycopy failure: ", err); 707 } 708 } 709 BDarray[ii] = convertByteToBigDecimal(bd); 710 } 711 return BDarray; 712 } 713 714 /** 715 * Convert 4 bytes from an array of bytes into a single BigDecimal 716 * 717 * @param start 718 * The position in the input array of bytes to start 719 * @param data 720 * The input array of bytes 721 * @return The BigDecimal value of the bytes. 722 */ 723 public BigDecimal byteToBigDecimal(byte[] data, int start) 724 { 725 BigDecimal[] bdval = new BigDecimal[1]; 726 bdval = byteToBigDecimal(start, 1, data); 727 return (bdval[0]); 728 } 729 730 /** 731 * Convert byte array data to a BigDecimal. 732 * 733 * @param raw 734 * The byte array to convert to a BigDecimal 735 * @return A BigDecimal representing the byte array. 736 */ 737 public BigDecimal convertByteToBigDecimal(byte[] raw) 738 { 739 BitSet rawset = BitSet.valueOf(raw); 740 741 boolean sign = rawset.get(nativeOffset + (int)nativeFPspos); 742 BitSet mantissaset = rawset.get(nativeOffset + (int)nativeFPmpos, 743 nativeOffset + (int)nativeFPmpos + (int)nativeFPmsize); 744 BitSet exponentset = rawset.get(nativeOffset + (int)nativeFPepos, 745 nativeOffset + (int)nativeFPepos + (int)nativeFPesize); 746 byte[] expraw = Arrays.copyOf(exponentset.toByteArray(), (int)(nativeFPesize + 7) / 8); 747 byte[] bexp = new byte[expraw.length]; 748 /* bitsets operate assuming LE order, BigInteger/BigDecimal expect BE */ 749 if (datatypeOrder == ORDER_LE) { 750 int k = 0; 751 for (int j = expraw.length - 1; j >= 0; j--) 752 bexp[k++] = expraw[j]; 753 } 754 else { 755 try { 756 System.arraycopy(expraw, 0, bexp, 0, expraw.length); 757 } 758 catch (Exception err) { 759 log.trace("convertByteToBigDecimal(): arraycopy failure: ", err); 760 } 761 } 762 BigInteger bscale = new BigInteger(bexp); 763 long scale = bscale.longValue(); 764 scale -= nativeFPebias; 765 double powscale = Math.pow(2, scale); 766 767 byte[] manraw = Arrays.copyOf(mantissaset.toByteArray(), (int)(nativeFPmsize + 7) / 8); 768 byte[] bman = new byte[manraw.length]; 769 /* bitsets operate assuming LE order, BigInteger/BigDecimal expect BE */ 770 if (datatypeOrder == ORDER_BE) { 771 int k = 0; 772 for (int j = manraw.length - 1; j >= 0; j--) 773 bman[k++] = manraw[j]; 774 } 775 else { 776 try { 777 System.arraycopy(manraw, 0, bman, 0, manraw.length); 778 } 779 catch (Exception err) { 780 log.trace("convertByteToBigDecimal(): arraycopy failure: ", err); 781 } 782 } 783 BitSet manset = BitSet.valueOf(bman); 784 785 // calculate mantissa value 786 double val = 0.0; 787 for (int i = 0; i < (int)nativeFPmsize; i++) { 788 if (manset.get((int)nativeFPmsize - 1 - i)) 789 val += Math.pow(2, -(i)); 790 } 791 if (nativeFPnorm == HDF5Constants.H5T_NORM_IMPLIED || nativeFPnorm == HDF5Constants.H5T_NORM_MSBSET) 792 val += 1; 793 BigDecimal sig = BigDecimal.valueOf(val); 794 if (sign) 795 sig.negate(MathContext.DECIMAL128); 796 return sig.multiply(new BigDecimal(powscale, MathContext.DECIMAL128)); 797 } 798 799 /* 800 * (non-Javadoc) 801 * @see hdf.object.Datatype#fromNative(int) 802 */ 803 @Override 804 public void fromNative(long tid) 805 { 806 log.trace("fromNative(): start: tid={}", tid); 807 long tsize = -1; 808 int torder = -1; 809 boolean isChar = false; 810 boolean isUchar = false; 811 812 if (tid < 0) { 813 datatypeClass = CLASS_NO_CLASS; 814 } 815 else { 816 try { 817 nativeClass = H5.H5Tget_class(tid); 818 tsize = H5.H5Tget_size(tid); 819 isVariableStr = H5.H5Tis_variable_str(tid); 820 isVLEN = false; 821 log.trace("fromNative(): tclass={}, tsize={}, torder={}, isVLEN={}", nativeClass, tsize, 822 torder, isVLEN); 823 if (H5.H5Tcommitted(tid)) { 824 isNamed = true; 825 try { 826 setFullname(null, H5.H5Iget_name(tid)); 827 } 828 catch (Exception nex) { 829 log.debug("fromNative(): setName failure: {}", nex.getMessage()); 830 } 831 log.trace("fromNative(): path={} name={}", this.getPath(), this.getName()); 832 } 833 log.trace("fromNative(): isNamed={}", isNamed()); 834 } 835 catch (Exception ex) { 836 log.debug("fromNative(): failure: ", ex); 837 datatypeClass = CLASS_NO_CLASS; 838 } 839 840 try { 841 isUchar = H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_UCHAR); 842 isChar = (H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_CHAR) || isUchar); 843 log.trace("fromNative(): tclass={}, tsize={}, torder={}, isUchar={}, isChar={}", nativeClass, 844 tsize, torder, isUchar, isChar); 845 } 846 catch (Exception ex) { 847 log.debug("fromNative(): native char type failure: ", ex); 848 } 849 850 datatypeOrder = HDF5Constants.H5T_ORDER_NONE; 851 boolean IsAtomic = datatypeClassIsAtomic(nativeClass); 852 if (IsAtomic || (nativeClass == HDF5Constants.H5T_COMPOUND)) { 853 try { 854 torder = H5.H5Tget_order(tid); 855 datatypeOrder = (torder == HDF5Constants.H5T_ORDER_BE) ? ORDER_BE : ORDER_LE; 856 } 857 catch (Exception ex) { 858 log.debug("fromNative(): get_order failure: ", ex); 859 } 860 } 861 862 if (IsAtomic && !datatypeClassIsOpaque(nativeClass)) { 863 try { 864 nativePrecision = H5.H5Tget_precision_long(tid); 865 } 866 catch (Exception ex) { 867 log.debug("fromNative(): get_precision failure: ", ex); 868 } 869 870 try { 871 nativeOffset = H5.H5Tget_offset(tid); 872 } 873 catch (Exception ex) { 874 log.debug("fromNative(): get_offset failure: ", ex); 875 } 876 877 try { 878 int[] pads = new int[2]; 879 H5.H5Tget_pad(tid, pads); 880 nativePadLSB = pads[0]; 881 nativePadMSB = pads[1]; 882 } 883 catch (Exception ex) { 884 log.debug("fromNative(): get_pad failure: ", ex); 885 } 886 } 887 888 log.trace( 889 "fromNative(): isUchar={}, nativePrecision={}, nativeOffset={}, nativePadLSB={}, nativePadMSB={}", 890 isUchar, nativePrecision, nativeOffset, nativePadLSB, nativePadMSB); 891 892 datatypeSign = NATIVE; // default 893 if (nativeClass == HDF5Constants.H5T_ARRAY) { 894 long tmptid = HDF5Constants.H5I_INVALID_HID; 895 datatypeClass = CLASS_ARRAY; 896 try { 897 int ndims = H5.H5Tget_array_ndims(tid); 898 arrayDims = new long[ndims]; 899 H5.H5Tget_array_dims(tid, arrayDims); 900 901 tmptid = H5.H5Tget_super(tid); 902 int nativeBaseClass = H5.H5Tget_class(tmptid); 903 if (nativeBaseClass == HDF5Constants.H5T_REFERENCE) 904 baseType = new H5ReferenceType(this.fileFormat, 1, tmptid); 905 else 906 baseType = new H5Datatype(this.fileFormat, tmptid, this); 907 if (baseType == null) { 908 log.debug("fromNative(): ARRAY datatype has null base type"); 909 throw new Exception("Datatype (ARRAY) has no base datatype"); 910 } 911 912 datatypeSign = baseType.getDatatypeSign(); 913 } 914 catch (Exception ex) { 915 log.debug("fromNative(): array type failure: ", ex); 916 } 917 finally { 918 close(tmptid); 919 } 920 } 921 else if (nativeClass == HDF5Constants.H5T_COMPOUND) { 922 datatypeClass = CLASS_COMPOUND; 923 924 try { 925 int nMembers = H5.H5Tget_nmembers(tid); 926 compoundMemberNames = new Vector<>(nMembers); 927 compoundMemberTypes = new Vector<>(nMembers); 928 compoundMemberOffsets = new Vector<>(nMembers); 929 log.trace("fromNative(): compound type nMembers={} start", nMembers); 930 931 for (int i = 0; i < nMembers; i++) { 932 String memberName = H5.H5Tget_member_name(tid, i); 933 log.trace("fromNative(): compound type [{}] name={} start", i, memberName); 934 long memberOffset = H5.H5Tget_member_offset(tid, i); 935 long memberID = HDF5Constants.H5I_INVALID_HID; 936 H5Datatype membertype = null; 937 try { 938 memberID = H5.H5Tget_member_type(tid, i); 939 int nativeMemberClass = H5.H5Tget_class(memberID); 940 if (nativeMemberClass == HDF5Constants.H5T_REFERENCE) 941 membertype = new H5ReferenceType(this.fileFormat, 1, memberID); 942 else 943 membertype = new H5Datatype(this.fileFormat, memberID, this); 944 } 945 catch (Exception ex1) { 946 log.debug("fromNative(): compound type failure: ", ex1); 947 } 948 finally { 949 close(memberID); 950 } 951 952 compoundMemberNames.add(i, memberName); 953 compoundMemberOffsets.add(i, memberOffset); 954 compoundMemberTypes.add(i, membertype); 955 } 956 } 957 catch (HDF5LibraryException ex) { 958 log.debug("fromNative(): compound type failure: ", ex); 959 } 960 } 961 else if (nativeClass == HDF5Constants.H5T_INTEGER) { 962 datatypeClass = CLASS_INTEGER; 963 try { 964 log.trace("fromNative(): integer type"); 965 int tsign = H5.H5Tget_sign(tid); 966 datatypeSign = (tsign == HDF5Constants.H5T_SGN_NONE) ? SIGN_NONE : SIGN_2; 967 } 968 catch (Exception ex) { 969 log.debug("fromNative(): int type failure: ", ex); 970 } 971 } 972 else if (nativeClass == HDF5Constants.H5T_FLOAT) { 973 datatypeClass = CLASS_FLOAT; 974 try { 975 nativeFPebias = H5.H5Tget_ebias_long(tid); 976 } 977 catch (Exception ex) { 978 log.debug("fromNative(): get_ebias failure: ", ex); 979 } 980 try { 981 long[] fields = new long[5]; 982 H5.H5Tget_fields(tid, fields); 983 nativeFPspos = fields[0]; 984 nativeFPepos = fields[1]; 985 nativeFPesize = fields[2]; 986 nativeFPmpos = fields[3]; 987 nativeFPmsize = fields[4]; 988 } 989 catch (Exception ex) { 990 log.debug("fromNative(): get_fields failure: ", ex); 991 } 992 try { 993 nativeFPnorm = H5.H5Tget_norm(tid); 994 } 995 catch (Exception ex) { 996 log.debug("fromNative(): get_norm failure: ", ex); 997 } 998 try { 999 nativeFPinpad = H5.H5Tget_inpad(tid); 1000 } 1001 catch (Exception ex) { 1002 log.debug("fromNative(): get_inpad failure: ", ex); 1003 } 1004 } 1005 else if (isChar) { 1006 datatypeClass = CLASS_CHAR; 1007 datatypeSign = (isUchar) ? SIGN_NONE : SIGN_2; 1008 log.trace("fromNative(): CLASS_CHAR:datatypeSign={}", datatypeSign); 1009 } 1010 else if (nativeClass == HDF5Constants.H5T_STRING) { 1011 datatypeClass = CLASS_STRING; 1012 try { 1013 isVLEN = H5.H5Tdetect_class(tid, HDF5Constants.H5T_VLEN) || isVariableStr; 1014 log.trace("fromNative(): H5T_STRING:var str type={}", isVLEN); 1015 nativeStrPad = H5.H5Tget_strpad(tid); 1016 } 1017 catch (Exception ex) { 1018 log.debug("fromNative(): var str type failure: ", ex); 1019 } 1020 try { 1021 nativeStrCSET = H5.H5Tget_cset(tid); 1022 } 1023 catch (Exception ex) { 1024 log.debug("fromNative(): H5T_STRING:get_cset failure: ", ex); 1025 } 1026 log.trace("fromNative(): H5T_STRING:nativeStrPad={}, nativeStrCSET={}", nativeStrPad, 1027 nativeStrCSET); 1028 } 1029 else if (nativeClass == HDF5Constants.H5T_REFERENCE) { 1030 datatypeClass = CLASS_REFERENCE; 1031 log.trace("fromNative(): reference type"); 1032 try { 1033 isStdRef = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF); 1034 log.trace("fromNative(): reference type is orig StdRef:{}", isStdRef); 1035 if (H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF)) 1036 tsize = HDF5Constants.H5R_REF_BUF_SIZE; 1037 } 1038 catch (Exception ex) { 1039 log.debug("fromNative(): H5T_STD_REF: ", ex); 1040 } 1041 try { 1042 isRegRef = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 1043 log.trace("fromNative(): reference type isRegRef:{}", isRegRef); 1044 if (isRegRef) 1045 tsize = HDF5Constants.H5R_DSET_REG_REF_BUF_SIZE; 1046 } 1047 catch (Exception ex) { 1048 log.debug("fromNative(): H5T_STD_REF_DSETREG: ", ex); 1049 } 1050 try { 1051 isRefObj = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_OBJ); 1052 log.trace("fromNative(): reference type isRefObj:{}", isRefObj); 1053 if (isRefObj) 1054 tsize = HDF5Constants.H5R_OBJ_REF_BUF_SIZE; 1055 } 1056 catch (Exception ex) { 1057 log.debug("fromNative(): H5T_STD_REF_OBJ: ", ex); 1058 } 1059 } 1060 else if (nativeClass == HDF5Constants.H5T_ENUM) { 1061 datatypeClass = CLASS_ENUM; 1062 long tmptid = HDF5Constants.H5I_INVALID_HID; 1063 long basetid = HDF5Constants.H5I_INVALID_HID; 1064 try { 1065 log.trace("fromNative(): enum type"); 1066 basetid = H5.H5Tget_super(tid); 1067 tmptid = basetid; 1068 basetid = H5.H5Tget_native_type(tmptid); 1069 log.trace("fromNative(): enum type basetid={}", basetid); 1070 if (basetid >= 0) { 1071 baseType = new H5Datatype(this.fileFormat, tmptid, this); 1072 datatypeSign = baseType.getDatatypeSign(); 1073 } 1074 } 1075 catch (Exception ex) { 1076 log.debug("fromNative(): enum type failure: ", ex); 1077 } 1078 finally { 1079 close(tmptid); 1080 close(basetid); 1081 } 1082 try { 1083 int enumMemberCount = H5.H5Tget_nmembers(tid); 1084 String name = null; 1085 String enumStr = null; 1086 byte[] val = new byte[(int)tsize]; 1087 enumMembers = new HashMap<>(); 1088 for (int i = 0; i < enumMemberCount; i++) { 1089 name = H5.H5Tget_member_name(tid, i); 1090 H5.H5Tget_member_value(tid, i, val); 1091 switch ((int)H5.H5Tget_size(tid)) { 1092 case 1: 1093 enumStr = Byte.toString((HDFNativeData.byteToByte(val[0]))[0]); 1094 break; 1095 case 2: 1096 enumStr = Short.toString((HDFNativeData.byteToShort(val))[0]); 1097 break; 1098 case 4: 1099 enumStr = Integer.toString((HDFNativeData.byteToInt(val))[0]); 1100 break; 1101 case 8: 1102 enumStr = Long.toString((HDFNativeData.byteToLong(val))[0]); 1103 break; 1104 default: 1105 enumStr = "-1"; 1106 break; 1107 } 1108 enumMembers.put(enumStr, name); 1109 } 1110 } 1111 catch (Exception ex) { 1112 log.debug("fromNative(): enum type failure: ", ex); 1113 } 1114 } 1115 else if (nativeClass == HDF5Constants.H5T_VLEN) { 1116 long tmptid = HDF5Constants.H5I_INVALID_HID; 1117 datatypeClass = CLASS_VLEN; 1118 isVLEN = true; 1119 try { 1120 log.trace("fromNative(): vlen type"); 1121 tmptid = H5.H5Tget_super(tid); 1122 int nativeBaseClass = H5.H5Tget_class(tmptid); 1123 if (nativeBaseClass == HDF5Constants.H5T_REFERENCE) 1124 baseType = new H5ReferenceType(this.fileFormat, 1, tmptid); 1125 else 1126 baseType = new H5Datatype(this.fileFormat, tmptid, this); 1127 if (baseType == null) { 1128 log.debug("fromNative(): VLEN datatype has null base type"); 1129 throw new Exception("Datatype (VLEN) has no base datatype"); 1130 } 1131 1132 datatypeSign = baseType.getDatatypeSign(); 1133 } 1134 catch (Exception ex) { 1135 log.debug("fromNative(): vlen type failure: ", ex); 1136 } 1137 finally { 1138 close(tmptid); 1139 } 1140 } 1141 else if (nativeClass == HDF5Constants.H5T_BITFIELD) { 1142 datatypeClass = CLASS_BITFIELD; 1143 } 1144 else if (nativeClass == HDF5Constants.H5T_OPAQUE) { 1145 datatypeClass = CLASS_OPAQUE; 1146 1147 try { 1148 opaqueTag = H5.H5Tget_tag(tid); 1149 } 1150 catch (Exception ex) { 1151 log.debug("fromNative(): opaque type tag retrieval failed: ", ex); 1152 opaqueTag = null; 1153 } 1154 } 1155 else { 1156 log.debug("fromNative(): datatypeClass is unknown"); 1157 } 1158 1159 datatypeSize = (isVLEN && !isVariableStr) ? HDF5Constants.H5T_VL_T : tsize; 1160 } 1161 if (datatypeSize == NATIVE) 1162 datatypeNATIVE = true; 1163 else 1164 datatypeNATIVE = false; 1165 log.trace("fromNative(): datatypeClass={} baseType={} datatypeSize={}", datatypeClass, baseType, 1166 datatypeSize); 1167 } 1168 1169 /** 1170 * Get the memory datatype identifier from the datatype file identifier. 1171 * 1172 * @param tid the datatype file identification. 1173 * 1174 * @return the memory datatype identifier if successful, and negative otherwise. 1175 */ 1176 public static long toNative(long tid) 1177 { 1178 // data type information 1179 log.trace("toNative(): tid={} start", tid); 1180 long nativeID = HDF5Constants.H5I_INVALID_HID; 1181 1182 try { 1183 nativeID = H5.H5Tget_native_type(tid); 1184 } 1185 catch (Exception ex) { 1186 log.debug("toNative(): H5Tget_native_type(tid {}) failure: ", tid, ex); 1187 } 1188 1189 try { 1190 if (H5.H5Tis_variable_str(tid)) 1191 H5.H5Tset_size(nativeID, HDF5Constants.H5T_VARIABLE); 1192 } 1193 catch (Exception ex) { 1194 log.debug("toNative(): var str type size failure: ", ex); 1195 } 1196 1197 return nativeID; 1198 } 1199 1200 /* 1201 * (non-Javadoc) 1202 * @see hdf.object.Datatype#createNative() 1203 */ 1204 @SuppressWarnings("rawtypes") 1205 @Override 1206 public long createNative() 1207 { 1208 long tid = HDF5Constants.H5I_INVALID_HID; 1209 long tmptid = HDF5Constants.H5I_INVALID_HID; 1210 1211 String the_path = getFullName(); 1212 // isNamed == true should have non-null fileFormat 1213 if (isNamed()) { 1214 try { 1215 tid = H5.H5Topen(getFID(), the_path, HDF5Constants.H5P_DEFAULT); 1216 } 1217 catch (Exception ex) { 1218 log.debug("createNative(): name {} H5Topen failure: ", the_path, ex); 1219 } 1220 } 1221 else 1222 log.debug("createNative(): isNamed={} and named path={}", isNamed(), the_path); 1223 1224 if (tid >= 0) 1225 return tid; 1226 1227 log.trace("createNative(): datatypeClass={} datatypeSize={} baseType={}", datatypeClass, datatypeSize, 1228 baseType); 1229 1230 switch (datatypeClass) { 1231 case CLASS_ARRAY: 1232 try { 1233 if (baseType == null) { 1234 log.debug("createNative(): CLASS_ARRAY base type is NULL"); 1235 break; 1236 } 1237 1238 if ((tmptid = baseType.createNative()) < 0) { 1239 log.debug("createNative(): failed to create native datatype for ARRAY base datatype"); 1240 break; 1241 } 1242 1243 tid = H5.H5Tarray_create(tmptid, arrayDims.length, arrayDims); 1244 } 1245 catch (Exception ex) { 1246 log.debug("createNative(): native array datatype creation failed: ", ex); 1247 if (tid >= 0) 1248 close(tid); 1249 tid = HDF5Constants.H5I_INVALID_HID; 1250 } 1251 finally { 1252 close(tmptid); 1253 } 1254 1255 break; 1256 case CLASS_COMPOUND: 1257 try { 1258 tid = H5.H5Tcreate(CLASS_COMPOUND, datatypeSize); 1259 1260 for (int i = 0; i < compoundMemberTypes.size(); i++) { 1261 H5Datatype memberType = null; 1262 String memberName = null; 1263 long memberOffset = -1; 1264 1265 try { 1266 memberType = (H5Datatype)compoundMemberTypes.get(i); 1267 } 1268 catch (Exception ex) { 1269 log.debug("createNative(): get compound member[{}] type failure: ", i, ex); 1270 memberType = null; 1271 } 1272 1273 try { 1274 memberName = compoundMemberNames.get(i); 1275 } 1276 catch (Exception ex) { 1277 log.debug("createNative(): get compound member[{}] name failure: ", i, ex); 1278 memberName = null; 1279 } 1280 1281 try { 1282 memberOffset = compoundMemberOffsets.get(i); 1283 } 1284 catch (Exception ex) { 1285 log.debug("createNative(): get compound member[{}] offset failure: ", i, ex); 1286 memberOffset = -1; 1287 } 1288 1289 long memberID = HDF5Constants.H5I_INVALID_HID; 1290 try { 1291 memberID = memberType.createNative(); 1292 log.trace("createNative(): {} member[{}] with offset={} ID={}: ", memberName, i, 1293 memberOffset, memberID); 1294 1295 H5.H5Tinsert(tid, memberName, memberOffset, memberID); 1296 } 1297 catch (Exception ex) { 1298 log.debug("createNative(): compound type member[{}] insertion failure: ", i, ex); 1299 } 1300 finally { 1301 close(memberID); 1302 } 1303 } 1304 } 1305 catch (Exception ex) { 1306 log.debug("createNative(): native compound datatype creation failed: ", ex); 1307 if (tid >= 0) 1308 close(tid); 1309 tid = HDF5Constants.H5I_INVALID_HID; 1310 } 1311 break; 1312 case CLASS_INTEGER: 1313 log.trace("createNative(): CLASS_INT of size {}", datatypeSize); 1314 1315 try { 1316 switch ((int)datatypeSize) { 1317 case 1: 1318 log.trace("createNative(): CLASS_INT is H5T_NATIVE_INT8"); 1319 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 1320 break; 1321 case 2: 1322 log.trace("createNative(): CLASS_INT is H5T_NATIVE_INT16"); 1323 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16); 1324 break; 1325 case 4: 1326 log.trace("createNative(): CLASS_INT is H5T_NATIVE_INT32"); 1327 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 1328 break; 1329 case 8: 1330 log.trace("createNative(): CLASS_INT is H5T_NATIVE_INT64"); 1331 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64); 1332 break; 1333 default: 1334 if (datatypeSize == NATIVE) { 1335 datatypeNATIVE = true; 1336 log.trace("createNative(): CLASS_INT is H5T_NATIVE_INT"); 1337 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT); 1338 datatypeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1339 } 1340 else { 1341 datatypeNATIVE = false; 1342 /* Custom sized integer */ 1343 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 1344 H5.H5Tset_size(tid, datatypeSize); 1345 H5.H5Tset_precision(tid, 8 * datatypeSize); 1346 } 1347 break; 1348 } 1349 1350 if (datatypeOrder == Datatype.ORDER_BE) { 1351 log.trace("createNative(): CLASS_INT order is H5T_ORDER_BE"); 1352 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1353 } 1354 else if (datatypeOrder == Datatype.ORDER_LE) { 1355 log.trace("createNative(): CLASS_INT order is H5T_ORDER_LE"); 1356 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1357 } 1358 1359 if (datatypeSign == Datatype.SIGN_NONE) { 1360 log.trace("createNative(): CLASS_INT sign is H5T_SGN_NONE"); 1361 H5.H5Tset_sign(tid, HDF5Constants.H5T_SGN_NONE); 1362 } 1363 } 1364 catch (Exception ex) { 1365 log.debug("createNative(): native integer datatype creation failed: ", ex); 1366 if (tid >= 0) 1367 close(tid); 1368 tid = -1; 1369 } 1370 1371 break; 1372 case CLASS_ENUM: 1373 log.trace("createNative(): CLASS_ENUM"); 1374 try { 1375 if (baseType != null) { 1376 if ((tmptid = baseType.createNative()) < 0) { 1377 log.debug("createNative(): failed to create native type for ENUM base datatype"); 1378 break; 1379 } 1380 1381 tid = H5.H5Tenum_create(tmptid); 1382 } 1383 else { 1384 if (datatypeSize == NATIVE) { 1385 datatypeNATIVE = true; 1386 datatypeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1387 } 1388 else 1389 datatypeNATIVE = false; 1390 1391 tid = H5.H5Tcreate(HDF5Constants.H5T_ENUM, datatypeSize); 1392 } 1393 1394 if (datatypeOrder == Datatype.ORDER_BE) { 1395 log.trace("createNative(): CLASS_ENUM order is H5T_ORDER_BE"); 1396 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1397 } 1398 else if (datatypeOrder == Datatype.ORDER_LE) { 1399 log.trace("createNative(): CLASS_ENUM order is H5T_ORDER_LE"); 1400 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1401 } 1402 1403 if (datatypeSign == Datatype.SIGN_NONE) { 1404 log.trace("createNative(): CLASS_ENUM sign is H5T_SGN_NONE"); 1405 H5.H5Tset_sign(tid, HDF5Constants.H5T_SGN_NONE); 1406 } 1407 } 1408 catch (Exception ex) { 1409 log.debug("createNative(): native enum datatype creation failed: ", ex); 1410 if (tid >= 0) 1411 close(tid); 1412 tid = HDF5Constants.H5I_INVALID_HID; 1413 } 1414 finally { 1415 close(tmptid); 1416 } 1417 1418 break; 1419 case CLASS_FLOAT: 1420 try { 1421 if (datatypeSize > 8) 1422 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_LDOUBLE); 1423 else 1424 tid = H5.H5Tcopy((datatypeSize == 8) ? HDF5Constants.H5T_NATIVE_DOUBLE 1425 : HDF5Constants.H5T_NATIVE_FLOAT); 1426 1427 if (datatypeOrder == Datatype.ORDER_BE) { 1428 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1429 } 1430 else if (datatypeOrder == Datatype.ORDER_LE) { 1431 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1432 } 1433 1434 if (nativeFPebias > 0) { 1435 H5.H5Tset_ebias(tid, nativeFPebias); 1436 } 1437 1438 if (nativeFPnorm >= 0) { 1439 H5.H5Tset_norm(tid, nativeFPnorm); 1440 } 1441 1442 if (nativeFPinpad >= 0) { 1443 H5.H5Tset_inpad(tid, nativeFPinpad); 1444 } 1445 1446 if ((nativeFPesize >= 0) && (nativeFPmsize >= 0)) { 1447 H5.H5Tset_fields(tid, nativeFPspos, nativeFPmpos, nativeFPesize, nativeFPmpos, 1448 nativeFPmsize); 1449 } 1450 } 1451 catch (Exception ex) { 1452 log.debug("createNative(): native floating-point datatype creation failed: ", ex); 1453 if (tid >= 0) 1454 close(tid); 1455 tid = HDF5Constants.H5I_INVALID_HID; 1456 } 1457 1458 break; 1459 case CLASS_CHAR: 1460 try { 1461 tid = H5.H5Tcopy((datatypeSign == Datatype.SIGN_NONE) ? HDF5Constants.H5T_NATIVE_UCHAR 1462 : HDF5Constants.H5T_NATIVE_CHAR); 1463 } 1464 catch (Exception ex) { 1465 log.debug("createNative(): native character datatype creation failed: ", ex); 1466 if (tid >= 0) 1467 close(tid); 1468 tid = HDF5Constants.H5I_INVALID_HID; 1469 } 1470 1471 break; 1472 case CLASS_STRING: 1473 try { 1474 tid = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 1475 1476 H5.H5Tset_size(tid, (isVLEN || datatypeSize < 0) ? HDF5Constants.H5T_VARIABLE : datatypeSize); 1477 1478 log.trace("createNative(): isVlenStr={} nativeStrPad={} nativeStrCSET={}", isVLEN, 1479 nativeStrPad, nativeStrCSET); 1480 1481 H5.H5Tset_strpad(tid, (nativeStrPad >= 0) ? nativeStrPad : HDF5Constants.H5T_STR_NULLTERM); 1482 1483 if (nativeStrCSET >= 0) { 1484 H5.H5Tset_cset(tid, nativeStrCSET); 1485 } 1486 } 1487 catch (Exception ex) { 1488 log.debug("createNative(): native string datatype creation failed: ", ex); 1489 if (tid >= 0) 1490 close(tid); 1491 tid = HDF5Constants.H5I_INVALID_HID; 1492 } 1493 1494 break; 1495 case CLASS_REFERENCE: 1496 try { 1497 long objRefTypeSize = H5.H5Tget_size(HDF5Constants.H5T_STD_REF_OBJ); 1498 long dsetRefTypeSize = H5.H5Tget_size(HDF5Constants.H5T_STD_REF_DSETREG); 1499 // use datatypeSize as which type to copy 1500 log.debug("createNative(): datatypeSize:{} ", datatypeSize); 1501 if (datatypeSize < 0 || datatypeSize > dsetRefTypeSize) { 1502 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF); 1503 log.debug("createNative(): HDF5Constants.H5T_STD_REF"); 1504 } 1505 else if (datatypeSize > objRefTypeSize) { 1506 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_DSETREG); 1507 log.debug("createNative(): HDF5Constants.H5T_STD_REF_DSETREG"); 1508 } 1509 else { 1510 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_OBJ); 1511 log.debug("createNative(): HDF5Constants.H5T_STD_REF_OBJ"); 1512 } 1513 } 1514 catch (Exception ex) { 1515 log.debug("createNative(): native reference datatype creation failed: ", ex); 1516 if (tid >= 0) 1517 close(tid); 1518 tid = HDF5Constants.H5I_INVALID_HID; 1519 } 1520 1521 break; 1522 case CLASS_VLEN: 1523 try { 1524 if (baseType == null) { 1525 log.debug("createNative(): CLASS_VLEN base type is NULL"); 1526 break; 1527 } 1528 1529 if ((tmptid = baseType.createNative()) < 0) { 1530 log.debug("createNative(): failed to create native datatype for VLEN base datatype"); 1531 break; 1532 } 1533 1534 tid = H5.H5Tvlen_create(tmptid); 1535 } 1536 catch (Exception ex) { 1537 log.debug("createNative(): native variable-length datatype creation failed: ", ex); 1538 if (tid >= 0) 1539 close(tid); 1540 tid = HDF5Constants.H5I_INVALID_HID; 1541 } 1542 finally { 1543 close(tmptid); 1544 } 1545 1546 break; 1547 case CLASS_BITFIELD: 1548 log.trace("createNative(): CLASS_BITFIELD size is {}", datatypeSize); 1549 1550 try { 1551 switch ((int)datatypeSize) { 1552 case 1: 1553 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B8"); 1554 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B8); 1555 break; 1556 case 2: 1557 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B16"); 1558 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B16); 1559 break; 1560 case 4: 1561 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B32"); 1562 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B32); 1563 break; 1564 case 8: 1565 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B64"); 1566 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B64); 1567 break; 1568 default: 1569 if (datatypeSize == NATIVE) { 1570 datatypeNATIVE = true; 1571 datatypeSize = 1; 1572 } 1573 else 1574 datatypeNATIVE = false; 1575 1576 /* Custom sized bitfield */ 1577 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B8); 1578 H5.H5Tset_size(tid, datatypeSize); 1579 H5.H5Tset_precision(tid, 8 * datatypeSize); 1580 1581 break; 1582 } 1583 1584 if (datatypeOrder == Datatype.ORDER_BE) { 1585 log.trace("createNative(): CLASS_BITFIELD order is H5T_ORDER_BE"); 1586 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1587 } 1588 else if (datatypeOrder == Datatype.ORDER_LE) { 1589 log.trace("createNative(): CLASS_BITFIELD order is H5T_ORDER_LE"); 1590 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1591 } 1592 } 1593 catch (Exception ex) { 1594 log.debug("createNative(): native bitfield datatype creation failed: ", ex); 1595 if (tid >= 0) 1596 close(tid); 1597 tid = HDF5Constants.H5I_INVALID_HID; 1598 } 1599 1600 break; 1601 case CLASS_OPAQUE: 1602 log.trace("createNative(): CLASS_OPAQUE is {}-byte H5T_OPAQUE", datatypeSize); 1603 1604 try { 1605 if (datatypeSize == NATIVE) { 1606 datatypeNATIVE = true; 1607 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_OPAQUE); 1608 datatypeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_OPAQUE); 1609 } 1610 else { 1611 datatypeNATIVE = false; 1612 tid = H5.H5Tcreate(HDF5Constants.H5T_OPAQUE, datatypeSize); 1613 } 1614 1615 if (opaqueTag != null) { 1616 H5.H5Tset_tag(tid, opaqueTag); 1617 } 1618 } 1619 catch (Exception ex) { 1620 log.debug("createNative(): native opaque datatype creation failed: ", ex); 1621 if (tid >= 0) 1622 close(tid); 1623 tid = HDF5Constants.H5I_INVALID_HID; 1624 } 1625 1626 break; 1627 default: 1628 log.debug("createNative(): Unknown class"); 1629 break; 1630 } // (tclass) 1631 1632 // set up enum members 1633 if ((datatypeClass == CLASS_ENUM) && (enumMembers != null)) { 1634 log.trace("createNative(): set up enum members"); 1635 try { 1636 String memstr; 1637 String memname; 1638 byte[] memval = null; 1639 1640 Iterator entries = enumMembers.entrySet().iterator(); 1641 while (entries.hasNext()) { 1642 Entry thisEntry = (Entry)entries.next(); 1643 memstr = (String)thisEntry.getKey(); 1644 memname = (String)thisEntry.getValue(); 1645 1646 if (datatypeSize == 1) { 1647 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT8"); 1648 Byte tval = Byte.parseByte(memstr); 1649 memval = HDFNativeData.byteToByte(tval); 1650 } 1651 else if (datatypeSize == 2) { 1652 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT16"); 1653 Short tval = Short.parseShort(memstr); 1654 memval = HDFNativeData.shortToByte(tval); 1655 } 1656 else if (datatypeSize == 4) { 1657 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT32"); 1658 Integer tval = Integer.parseInt(memstr); 1659 memval = HDFNativeData.intToByte(tval); 1660 } 1661 else if (datatypeSize == 8) { 1662 log.trace("createNative(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 1663 Long tval = Long.parseLong(memstr); 1664 memval = HDFNativeData.longToByte(tval); 1665 } 1666 else { 1667 log.debug("createNative(): enum datatypeSize incorrect"); 1668 } 1669 log.trace("createNative(): H5Tenum_insert {} {}", memname, memval); 1670 H5.H5Tenum_insert(tid, memname, memval); 1671 } 1672 } 1673 catch (Exception ex) { 1674 log.debug("createNative(): set up enum members failure: ", ex); 1675 } 1676 } // (datatypeClass == CLASS_ENUM) 1677 1678 try { 1679 tmptid = tid; 1680 tid = H5.H5Tget_native_type(tmptid); 1681 } 1682 catch (HDF5Exception ex) { 1683 log.debug("createNative(): H5Tget_native_type({}) failure: ", tmptid, ex); 1684 } 1685 finally { 1686 close(tmptid); 1687 } 1688 1689 return tid; 1690 } 1691 1692 /** 1693 * Allocates a one-dimensional array of byte, short, int, long, float, double, or String to store data in 1694 * memory. For example, 1695 * 1696 * <pre> 1697 * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 1698 * int[] data = (int[]) H5Datatype.allocateArray(datatype, 100); 1699 * </pre> 1700 * 1701 * returns a 32-bit integer array of size 100. 1702 * 1703 * @param dtype 1704 * the type. 1705 * @param numPoints 1706 * the total number of data points of the array. 1707 * @return the array object if successful; otherwise, return null. 1708 * @throws OutOfMemoryError 1709 * If there is a failure. 1710 */ 1711 public static final Object allocateArray(final H5Datatype dtype, int numPoints) throws OutOfMemoryError 1712 { 1713 log.trace("allocateArray(): start: numPoints={}", numPoints); 1714 1715 Object data = null; 1716 H5Datatype baseType = (H5Datatype)dtype.getDatatypeBase(); 1717 int typeClass = dtype.getDatatypeClass(); 1718 long typeSize = dtype.getDatatypeSize(); 1719 1720 if (numPoints < 0) { 1721 log.debug("allocateArray(): numPoints < 0"); 1722 return null; 1723 } 1724 1725 // Scalar members have dimensionality zero, i.e. size =0 1726 // what can we do about it, set the size to 1 1727 if (numPoints == 0) 1728 numPoints = 1; 1729 1730 log.trace("allocateArray(): tclass={} : tsize={}", typeClass, typeSize); 1731 1732 if (dtype.isVarStr()) { 1733 log.trace("allocateArray(): is_variable_str={}", dtype.isVarStr()); 1734 1735 data = new String[numPoints]; 1736 for (int i = 0; i < numPoints; i++) 1737 ((String[])data)[i] = ""; 1738 } 1739 else if (typeClass == HDF5Constants.H5T_INTEGER) { 1740 log.trace("allocateArray(): class H5T_INTEGER"); 1741 if (typeSize == NATIVE) 1742 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1743 1744 switch ((int)typeSize) { 1745 case 1: 1746 data = new byte[numPoints]; 1747 break; 1748 case 2: 1749 data = new short[numPoints]; 1750 break; 1751 case 4: 1752 data = new int[numPoints]; 1753 break; 1754 case 8: 1755 data = new long[numPoints]; 1756 break; 1757 default: 1758 break; 1759 } 1760 } 1761 else if (typeClass == HDF5Constants.H5T_ENUM) { 1762 log.trace("allocateArray(): class H5T_ENUM"); 1763 1764 if (baseType != null) 1765 data = H5Datatype.allocateArray(baseType, numPoints); 1766 else { 1767 if (typeSize == NATIVE) 1768 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1769 data = new byte[(int)(numPoints * typeSize)]; 1770 } 1771 } 1772 else if (typeClass == HDF5Constants.H5T_COMPOUND) { 1773 log.trace("allocateArray(): class H5T_COMPOUND"); 1774 1775 data = new ArrayList<>(dtype.getCompoundMemberTypes().size()); 1776 } 1777 else if (typeClass == HDF5Constants.H5T_FLOAT) { 1778 log.trace("allocateArray(): class H5T_FLOAT"); 1779 if (typeSize == NATIVE) 1780 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_FLOAT); 1781 1782 switch ((int)typeSize) { 1783 case 4: 1784 data = new float[numPoints]; 1785 break; 1786 case 8: 1787 data = new double[numPoints]; 1788 break; 1789 case 16: 1790 data = new byte[numPoints * 16]; 1791 break; 1792 default: 1793 break; 1794 } 1795 } 1796 else if ((typeClass == HDF5Constants.H5T_STRING) || (typeClass == HDF5Constants.H5T_REFERENCE)) { 1797 log.trace("allocateArray(): class H5T_STRING || H5T_REFERENCE"); 1798 1799 data = new byte[(int)(numPoints * typeSize)]; 1800 } 1801 else if (dtype.isVLEN()) { 1802 log.trace("allocateArray(): isVLEN"); 1803 1804 data = new ArrayList[numPoints]; 1805 for (int j = 0; j < numPoints; j++) 1806 ((ArrayList[])data)[j] = new ArrayList<byte[]>(); 1807 // if (baseType != null) 1808 // ((ArrayList<>)data).add(H5Datatype.allocateArray(baseType, numPoints)); 1809 } 1810 else if (typeClass == HDF5Constants.H5T_ARRAY) { 1811 log.trace("allocateArray(): class H5T_ARRAY"); 1812 1813 try { 1814 log.trace("allocateArray(): ArrayRank={}", dtype.getArrayDims().length); 1815 1816 // Use the base datatype to define the array 1817 long[] arrayDims = dtype.getArrayDims(); 1818 int asize = numPoints; 1819 for (int j = 0; j < arrayDims.length; j++) { 1820 log.trace("allocateArray(): Array dims[{}]={}", j, arrayDims[j]); 1821 1822 asize *= arrayDims[j]; 1823 } 1824 1825 if (baseType != null) 1826 data = H5Datatype.allocateArray(baseType, asize); 1827 } 1828 catch (Exception ex) { 1829 log.debug("allocateArray(): H5T_ARRAY class failure: ", ex); 1830 } 1831 } 1832 else if ((typeClass == HDF5Constants.H5T_OPAQUE) || (typeClass == HDF5Constants.H5T_BITFIELD)) { 1833 log.trace("allocateArray(): class H5T_OPAQUE || H5T_BITFIELD"); 1834 if (typeSize == NATIVE) 1835 typeSize = H5.H5Tget_size(typeClass); 1836 1837 data = new byte[(int)(numPoints * typeSize)]; 1838 } 1839 else { 1840 log.debug("allocateArray(): class ???? ({})", typeClass); 1841 1842 data = null; 1843 } 1844 1845 return data; 1846 } 1847 1848 /** 1849 * Returns the size (in bytes) of a given datatype identifier. It basically just calls H5Tget_size(tid). 1850 * 1851 * @param tid 1852 * The datatype identifier. 1853 * @return The size of the datatype in bytes. 1854 * @see hdf.hdf5lib.H5#H5Tget_size(long) 1855 */ 1856 public static final long getDatatypeSize(long tid) 1857 { 1858 // data type information 1859 long tsize = -1; 1860 1861 try { 1862 tsize = H5.H5Tget_size(tid); 1863 } 1864 catch (Exception ex) { 1865 tsize = -1; 1866 } 1867 1868 return tsize; 1869 } 1870 1871 /* 1872 * (non-Javadoc) 1873 * @see hdf.object.Datatype#getDescription() 1874 */ 1875 @Override 1876 public String getDescription() 1877 { 1878 log.trace("getDescription(): start - isNamed={}", isNamed()); 1879 1880 if (datatypeDescription != null) 1881 return datatypeDescription; 1882 1883 StringBuilder description = new StringBuilder(); 1884 long tid = HDF5Constants.H5I_INVALID_HID; 1885 1886 switch (datatypeClass) { 1887 case CLASS_CHAR: 1888 log.trace("getDescription(): Char"); 1889 description.append("8-bit ").append(isUnsigned() ? "unsigned " : "").append("integer"); 1890 break; 1891 case CLASS_INTEGER: 1892 log.trace("getDescription(): Int [{}]", datatypeNATIVE); 1893 if (datatypeNATIVE) 1894 description.append("native ").append(isUnsigned() ? "unsigned " : "").append("integer"); 1895 else 1896 description.append(String.valueOf(datatypeSize * 8)) 1897 .append("-bit ") 1898 .append(isUnsigned() ? "unsigned " : "") 1899 .append("integer"); 1900 break; 1901 case CLASS_FLOAT: 1902 log.trace("getDescription(): Float"); 1903 if (datatypeNATIVE) 1904 description.append("native floating-point"); 1905 else 1906 description.append(String.valueOf(datatypeSize * 8)).append("-bit floating-point"); 1907 break; 1908 case CLASS_STRING: 1909 log.trace("getDescription(): String"); 1910 description.append("String, length = ").append(isVarStr() ? "variable" : datatypeSize); 1911 1912 try { 1913 tid = createNative(); 1914 if (tid >= 0) { 1915 String strPadType; 1916 String strCSETType; 1917 int strPad = H5.H5Tget_strpad(tid); 1918 int strCSET = H5.H5Tget_cset(tid); 1919 1920 if (strPad == HDF5Constants.H5T_STR_NULLTERM) 1921 strPadType = "H5T_STR_NULLTERM"; 1922 else if (strPad == HDF5Constants.H5T_STR_NULLPAD) 1923 strPadType = "H5T_STR_NULLPAD"; 1924 else if (strPad == HDF5Constants.H5T_STR_SPACEPAD) 1925 strPadType = "H5T_STR_SPACEPAD"; 1926 else 1927 strPadType = null; 1928 1929 if (strPadType != null) 1930 description.append(", padding = ").append(strPadType); 1931 1932 if (strCSET == HDF5Constants.H5T_CSET_ASCII) 1933 strCSETType = "H5T_CSET_ASCII"; 1934 else if (strCSET == HDF5Constants.H5T_CSET_UTF8) 1935 strCSETType = "H5T_CSET_UTF8"; 1936 else 1937 strCSETType = null; 1938 1939 if (strCSETType != null) 1940 description.append(", cset = ").append(strCSETType); 1941 } 1942 else { 1943 log.debug("createNative() failure"); 1944 } 1945 } 1946 catch (Exception ex) { 1947 log.debug("H5Tget_strpad failure: ", ex); 1948 } 1949 finally { 1950 close(tid); 1951 } 1952 break; 1953 case CLASS_BITFIELD: 1954 log.trace("getDescription(): Bit"); 1955 if (datatypeNATIVE) 1956 description.append("native bitfield"); 1957 else 1958 description.append(String.valueOf(datatypeSize * 8)).append("-bit bitfield"); 1959 break; 1960 case CLASS_OPAQUE: 1961 log.trace("getDescription(): Opaque"); 1962 if (datatypeNATIVE) 1963 description.append("native Opaque"); 1964 else 1965 description.append(String.valueOf(datatypeSize)).append("-byte Opaque"); 1966 1967 if (opaqueTag != null) { 1968 description.append(", tag = ").append(opaqueTag); 1969 } 1970 1971 break; 1972 case CLASS_COMPOUND: 1973 log.trace("getDescription(): Compound"); 1974 description.append("Compound"); 1975 1976 if ((compoundMemberTypes != null) && !compoundMemberTypes.isEmpty()) { 1977 Iterator<String> memberNames = null; 1978 Iterator<Datatype> memberTypes = compoundMemberTypes.iterator(); 1979 1980 if (compoundMemberNames != null) 1981 memberNames = compoundMemberNames.iterator(); 1982 1983 description.append(" {"); 1984 1985 while (memberTypes.hasNext()) { 1986 if (memberNames != null && memberNames.hasNext()) { 1987 description.append(memberNames.next()).append(" = "); 1988 } 1989 1990 description.append(memberTypes.next().getDescription()); 1991 1992 if (memberTypes.hasNext()) 1993 description.append(", "); 1994 } 1995 1996 description.append("}"); 1997 } 1998 1999 break; 2000 case CLASS_REFERENCE: 2001 log.trace("getDescription(): Ref"); 2002 description.append("Reference"); 2003 2004 try { 2005 boolean isRegionType = false; 2006 2007 tid = createNative(); 2008 if (tid >= 0) { 2009 if (!H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF)) { 2010 isRegionType = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 2011 2012 description.setLength(0); 2013 if (isRegionType) { 2014 description.append("Dataset region reference"); 2015 } 2016 else { 2017 description.append("Object reference"); 2018 } 2019 } 2020 } 2021 } 2022 catch (Exception ex) { 2023 log.debug("H5.H5Tequal failure: ", ex); 2024 } 2025 finally { 2026 close(tid); 2027 } 2028 2029 break; 2030 case CLASS_ENUM: 2031 log.trace("getDescription(): Enum"); 2032 if (datatypeNATIVE) 2033 description.append("native enum"); 2034 else 2035 description.append(String.valueOf(datatypeSize * 8)).append("-bit enum"); 2036 2037 String members = getEnumMembersAsString(); 2038 if (members != null) 2039 description.append(" (").append(members).append(")"); 2040 2041 break; 2042 case CLASS_VLEN: 2043 log.trace("getDescription(): Var Len"); 2044 description.append("Variable-length"); 2045 2046 if (baseType != null) 2047 description.append(" of ").append(baseType.getDescription()); 2048 2049 break; 2050 case CLASS_ARRAY: 2051 log.trace("getDescription(): Array"); 2052 description.append("Array"); 2053 2054 if (arrayDims != null) { 2055 description.append(" ["); 2056 for (int i = 0; i < arrayDims.length; i++) { 2057 description.append(arrayDims[i]); 2058 if (i < arrayDims.length - 1) 2059 description.append(" x "); 2060 } 2061 description.append("]"); 2062 } 2063 2064 if (baseType != null) 2065 description.append(" of ").append(baseType.getDescription()); 2066 2067 break; 2068 default: 2069 description.append("Unknown"); 2070 break; 2071 } 2072 if (isNamed()) 2073 description.append("->").append(getFullName()); 2074 2075 return description.toString(); 2076 } 2077 2078 /** 2079 * Checks if a datatype specified by the identifier is an unsigned integer. 2080 * 2081 * @param tid 2082 * the datatype ID to be checked. 2083 * @return true is the datatype is an unsigned integer; otherwise returns false. 2084 */ 2085 public static final boolean isUnsigned(long tid) 2086 { 2087 boolean unsigned = false; 2088 2089 if (tid >= 0) { 2090 try { 2091 int tclass = H5.H5Tget_class(tid); 2092 log.trace("isUnsigned(): tclass = {}", tclass); 2093 if (tclass != HDF5Constants.H5T_FLOAT && tclass != HDF5Constants.H5T_STRING && 2094 tclass != HDF5Constants.H5T_REFERENCE && tclass != HDF5Constants.H5T_BITFIELD && 2095 tclass != HDF5Constants.H5T_OPAQUE && tclass != HDF5Constants.H5T_VLEN && 2096 tclass != HDF5Constants.H5T_COMPOUND && tclass != HDF5Constants.H5T_ARRAY) { 2097 int tsign = H5.H5Tget_sign(tid); 2098 if (tsign == HDF5Constants.H5T_SGN_NONE) 2099 unsigned = true; 2100 else 2101 log.trace("isUnsigned(): not unsigned"); 2102 } 2103 else { 2104 log.trace("isUnsigned(): tclass not integer type"); 2105 } 2106 } 2107 catch (Exception ex) { 2108 log.debug("isUnsigned(): Datatype {} failure", tid, ex); 2109 unsigned = false; 2110 } 2111 } 2112 else { 2113 log.trace("isUnsigned(): not a valid datatype"); 2114 } 2115 2116 return unsigned; 2117 } 2118 2119 /** 2120 * Removes all of the elements from metadata list. The list should be empty after this call returns. 2121 */ 2122 @Override 2123 public void clear() 2124 { 2125 super.clear(); 2126 objMetadata.clear(); 2127 } 2128 2129 /** 2130 * Retrieves the object's metadata, such as attributes, from the file. Metadata, such as attributes, is 2131 * stored in a List. 2132 * 2133 * @return the list of metadata objects. 2134 * @throws HDF5Exception 2135 * if the metadata can not be retrieved 2136 */ 2137 @Override 2138 public List<Attribute> getMetadata() throws HDF5Exception 2139 { 2140 int gmIndexType = 0; 2141 int gmIndexOrder = 0; 2142 2143 try { 2144 gmIndexType = fileFormat.getIndexType(null); 2145 } 2146 catch (Exception ex) { 2147 log.debug("getMetadata(): getIndexType failed: ", ex); 2148 } 2149 try { 2150 gmIndexOrder = fileFormat.getIndexOrder(null); 2151 } 2152 catch (Exception ex) { 2153 log.debug("getMetadata(): getIndexOrder failed: ", ex); 2154 } 2155 return this.getMetadata(gmIndexType, gmIndexOrder); 2156 } 2157 2158 /** 2159 * Retrieves the object's metadata, such as attributes, from the file. Metadata, such as attributes, is 2160 * stored in a List. 2161 * 2162 * @param attrPropList 2163 * the list of properties to get 2164 * @return the list of metadata objects. 2165 * @throws HDF5Exception 2166 * if the metadata can not be retrieved 2167 */ 2168 public List<Attribute> getMetadata(int... attrPropList) throws HDF5Exception 2169 { 2170 try { 2171 this.linkTargetObjName = H5File.getLinkTargetName(this); 2172 } 2173 catch (Exception ex) { 2174 log.debug("getMetadata(): getLinkTargetName failed: ", ex); 2175 } 2176 2177 List<Attribute> attrlist = null; 2178 try { 2179 attrlist = objMetadata.getMetadata(attrPropList); 2180 } 2181 catch (Exception ex) { 2182 log.debug("getMetadata(): getMetadata failed: ", ex); 2183 } 2184 return attrlist; 2185 } 2186 2187 /** 2188 * Writes a specific piece of metadata (such as an attribute) into the file. If an HDF(4&5) attribute 2189 * exists in the file, this method updates its value. If the attribute does not exist in the file, it 2190 * creates the attribute in the file and attaches it to the object. It will fail to write a new attribute 2191 * to the object where an attribute with the same name already exists. To update the value of an existing 2192 * attribute in the file, one needs to get the instance of the attribute by getMetadata(), change its 2193 * values, then use writeMetadata() to write the value. 2194 * 2195 * @param info 2196 * the metadata to write. 2197 * @throws Exception 2198 * if the metadata can not be written 2199 */ 2200 @Override 2201 public void writeMetadata(Object info) throws Exception 2202 { 2203 try { 2204 objMetadata.writeMetadata(info); 2205 } 2206 catch (Exception ex) { 2207 log.debug("writeMetadata(): Object not an Attribute"); 2208 } 2209 } 2210 2211 /** 2212 * Deletes an existing piece of metadata from this object. 2213 * 2214 * @param info 2215 * the metadata to delete. 2216 * @throws HDF5Exception 2217 * if the metadata can not be removed 2218 */ 2219 @Override 2220 public void removeMetadata(Object info) throws HDF5Exception 2221 { 2222 try { 2223 objMetadata.removeMetadata(info); 2224 } 2225 catch (Exception ex) { 2226 log.debug("removeMetadata(): Object not an Attribute"); 2227 return; 2228 } 2229 2230 Attribute attr = (Attribute)info; 2231 log.trace("removeMetadata(): {}", attr.getAttributeName()); 2232 long tid = open(); 2233 if (tid >= 0) { 2234 try { 2235 H5.H5Adelete(tid, attr.getAttributeName()); 2236 } 2237 catch (Exception ex) { 2238 log.debug("removeMetadata(): ", ex); 2239 } 2240 finally { 2241 close(tid); 2242 } 2243 } 2244 else { 2245 log.debug("removeMetadata(): failed to open datatype"); 2246 } 2247 } 2248 2249 /** 2250 * Updates an existing piece of metadata attached to this object. 2251 * 2252 * @param info 2253 * the metadata to update. 2254 * @throws HDF5Exception 2255 * if the metadata can not be updated 2256 */ 2257 @Override 2258 public void updateMetadata(Object info) throws HDF5Exception 2259 { 2260 try { 2261 objMetadata.updateMetadata(info); 2262 } 2263 catch (Exception ex) { 2264 log.debug("updateMetadata(): Object not an Attribute"); 2265 return; 2266 } 2267 } 2268 2269 /* 2270 * (non-Javadoc) 2271 * @see hdf.object.HObject#setName(java.lang.String) 2272 */ 2273 @Override 2274 public void setName(String newName) throws Exception 2275 { 2276 if (newName == null) 2277 throw new IllegalArgumentException("The new name is NULL"); 2278 2279 H5File.renameObject(this, newName); 2280 super.setName(newName); 2281 } 2282 2283 @Override 2284 public void setFullname(String newPath, String newName) throws Exception 2285 { 2286 H5File.renameObject(this, newPath, newName); 2287 super.setFullname(newPath, newName); 2288 } 2289 2290 @Override 2291 public boolean isText() 2292 { 2293 return (datatypeClass == Datatype.CLASS_STRING); 2294 } 2295 2296 /** 2297 * Checks if this datatype is an object reference type. 2298 * 2299 * @return true if the datatype is an object reference; false otherwise 2300 */ 2301 public boolean isRefObj() { return isRefObj; } 2302 2303 /** 2304 * Checks if this datatype is a region reference type. 2305 * 2306 * @return true if the datatype is a region reference; false otherwise 2307 */ 2308 public boolean isRegRef() { return isRegRef; } 2309 2310 /** 2311 * Checks if this datatype is a standard reference type. 2312 * 2313 * @return true if the datatype is a standard reference; false otherwise 2314 */ 2315 public boolean isStdRef() { return isStdRef; } 2316 2317 /* 2318 * (non-Javadoc) 2319 * @see hdf.object.Datatype#getReferenceType() 2320 */ 2321 @Override 2322 public long getReferenceType() throws HDF5Exception 2323 { 2324 if (isRegRef) 2325 return HDF5Constants.H5T_STD_REF_DSETREG; 2326 if (isRefObj) 2327 return HDF5Constants.H5T_STD_REF_OBJ; 2328 if (isStdRef) 2329 return HDF5Constants.H5T_STD_REF; 2330 return -1; 2331 } 2332 2333 /** 2334 * Describes the dataset object description for a 1.10 reference. 2335 * 2336 * @param container 2337 * the dataset/attribute with the reference 2338 * @param refarr 2339 * the reference datatype data to be checked. 2340 * 2341 * @return the dataset reference object description. 2342 */ 2343 public static String descReferenceObject(long container, byte[] refarr) 2344 { 2345 String region_desc = H5.H5Rget_name_string(container, HDF5Constants.H5R_OBJECT, refarr); 2346 region_desc += " H5O_TYPE_OBJ_REF"; 2347 log.trace("descReferenceObject region_desc={}:", region_desc); 2348 return region_desc; 2349 } 2350 2351 /** 2352 * Describes the dataset region description for a 1.10 reference. 2353 * 2354 * @param container 2355 * the dataset/attribute with the reference 2356 * @param refarr 2357 * the reference datatype data to be checked. 2358 * 2359 * @return the dataset region description. 2360 */ 2361 public static String descRegionDataset(long container, byte[] refarr) 2362 { 2363 String region_desc = H5.H5Rget_name_string(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2364 log.trace("descRegionDataset region_desc={}:", region_desc); 2365 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 2366 try { 2367 log.trace("descRegionDataset refarr2={}:", refarr); 2368 new_obj_id = H5.H5Rdereference(container, HDF5Constants.H5P_DEFAULT, 2369 HDF5Constants.H5R_DATASET_REGION, refarr); 2370 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 2371 try { 2372 log.trace("descRegionDataset refarr3={}:", refarr); 2373 new_obj_sid = H5.H5Rget_region(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2374 try { 2375 int region_type = H5.H5Sget_select_type(new_obj_sid); 2376 log.debug("descRegionDataset Reference Region Type {}", region_type); 2377 long reg_ndims = H5.H5Sget_simple_extent_ndims(new_obj_sid); 2378 StringBuilder sb = new StringBuilder(); 2379 if (HDF5Constants.H5S_SEL_POINTS == region_type) { 2380 sb.append(" REGION_TYPE POINT "); 2381 long reg_npoints = H5.H5Sget_select_elem_npoints(new_obj_sid); 2382 long getcoord[] = new long[(int)(reg_ndims * reg_npoints)]; 2383 try { 2384 H5.H5Sget_select_elem_pointlist(new_obj_sid, 0, reg_npoints, getcoord); 2385 } 2386 catch (Exception ex5) { 2387 log.debug("descRegionDataset H5.H5Sget_select_elem_pointlist: ", ex5); 2388 } 2389 sb.append("{ "); 2390 for (int i = 0; i < (int)reg_npoints; i++) { 2391 if (i > 0) 2392 sb.append(" "); 2393 sb.append("("); 2394 for (int j = 0; j < (int)reg_ndims; j++) { 2395 if (j > 0) 2396 sb.append(","); 2397 sb.append(getcoord[i * (int)reg_ndims + j]); 2398 } 2399 sb.append(")"); 2400 } 2401 sb.append(" }"); 2402 region_desc += sb.toString(); 2403 } 2404 else if (HDF5Constants.H5S_SEL_HYPERSLABS == region_type) { 2405 sb.append(" REGION_TYPE BLOCK "); 2406 long reg_nblocks = H5.H5Sget_select_hyper_nblocks(new_obj_sid); 2407 long getblocks[] = new long[(int)(reg_ndims * reg_nblocks) * 2]; 2408 try { 2409 H5.H5Sget_select_hyper_blocklist(new_obj_sid, 0, reg_nblocks, getblocks); 2410 } 2411 catch (Exception ex5) { 2412 log.debug("descRegionDataset H5.H5Sget_select_hyper_blocklist: ", ex5); 2413 } 2414 sb.append("{ "); 2415 for (int i = 0; i < (int)reg_nblocks; i++) { 2416 if (i > 0) 2417 sb.append(" "); 2418 sb.append("("); 2419 for (int j = 0; j < (int)reg_ndims; j++) { 2420 if (j > 0) 2421 sb.append(","); 2422 sb.append(getblocks[i * 2 * (int)reg_ndims + j]); 2423 } 2424 sb.append(")-("); 2425 for (int j = 0; j < (int)reg_ndims; j++) { 2426 if (j > 0) 2427 sb.append(","); 2428 sb.append(getblocks[i * 2 * (int)reg_ndims + (int)reg_ndims + j]); 2429 } 2430 sb.append(")"); 2431 } 2432 sb.append(" }"); 2433 region_desc += sb.toString(); 2434 } 2435 else 2436 region_desc += " REGION_TYPE UNKNOWN"; 2437 } 2438 catch (Exception ex4) { 2439 log.debug("descRegionDataset Region Type", ex4); 2440 } 2441 } 2442 catch (Exception ex3) { 2443 log.debug("descRegionDataset Space Open", ex3); 2444 } 2445 finally { 2446 H5.H5Sclose(new_obj_sid); 2447 } 2448 log.trace("descRegionDataset finish"); 2449 } 2450 catch (Exception ex2) { 2451 log.debug("descRegionDataset ", ex2); 2452 } 2453 finally { 2454 H5.H5Dclose(new_obj_id); 2455 } 2456 return region_desc; 2457 } 2458 2459 /** 2460 * Gets the dataset reference type for a 1.10 reference. 2461 * 2462 * @param container the dataset/attribute with the reference 2463 * @param obj_type the dataset/attribute object type 2464 * @param refarr the reference datatype data to be checked. 2465 * 2466 * @return the dataset reference type. 2467 */ 2468 public static int typeObjectRef(long container, int obj_type, byte[] refarr) 2469 { 2470 int ref_type = -1; 2471 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 2472 try { 2473 log.trace("typeObjectRef refarr2={}:", refarr); 2474 new_obj_id = H5.H5Rdereference(container, HDF5Constants.H5P_DEFAULT, obj_type, refarr); 2475 if (HDF5Constants.H5R_DATASET_REGION == obj_type) { 2476 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 2477 try { 2478 log.trace("typeObjectRef refarr3={}:", refarr); 2479 new_obj_sid = H5.H5Rget_region(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2480 try { 2481 ref_type = H5.H5Sget_select_type(new_obj_sid); 2482 log.debug("typeObjectRef Reference Region Type {}", ref_type); 2483 } 2484 catch (Exception ex4) { 2485 log.debug("typeObjectRef Region Type", ex4); 2486 } 2487 } 2488 catch (Exception ex3) { 2489 log.debug("typeObjectRef Space Open", ex3); 2490 } 2491 finally { 2492 H5.H5Sclose(new_obj_sid); 2493 } 2494 } 2495 else { 2496 H5O_info_t objInfo; 2497 2498 objInfo = H5.H5Oget_info(new_obj_id); 2499 ref_type = objInfo.type; 2500 } 2501 log.trace("typeObjectRef finish"); 2502 } 2503 catch (Exception ex2) { 2504 log.debug("typeObjectRef ", ex2); 2505 } 2506 finally { 2507 H5.H5Dclose(new_obj_id); 2508 } 2509 return ref_type; 2510 } 2511 2512 /** 2513 * Checks if a reference datatype is all zero. 2514 * 2515 * @param refarr 2516 * the reference datatype data to be checked. 2517 * @return true is the reference datatype data is all zero; otherwise returns false. 2518 */ 2519 public static boolean zeroArrayCheck(final byte[] refarr) 2520 { 2521 for (byte b : refarr) { 2522 if (b != 0) 2523 return false; 2524 } 2525 return true; 2526 } 2527 2528 /** 2529 * Gets the string padding. 2530 * 2531 * @return the string padding value 2532 */ 2533 public int getNativeStrPad() { return nativeStrPad; } 2534 2535 /** 2536 * Extracts compound information into flat structure. For example, compound datatype "nest" has {nest1{a, 2537 * b, c}, d, e} then extractCompoundInfo() will put the names of nested compound fields into a flat list 2538 * as 2539 * 2540 * <pre> 2541 * nest.nest1.a 2542 * nest.nest1.b 2543 * nest.nest1.c 2544 * nest.d 2545 * nest.e 2546 * </pre> 2547 * 2548 * @param dtype 2549 * the datatype to extract compound info from 2550 * @param name 2551 * the name of the compound datatype 2552 * @param names 2553 * the list to store the member names of the compound datatype 2554 * @param flatListTypes 2555 * the list to store the nested member names of the compound datatype 2556 */ 2557 public static void extractCompoundInfo(final H5Datatype dtype, String name, List<String> names, 2558 List<Datatype> flatListTypes) 2559 { 2560 log.trace("extractCompoundInfo(): start: name={}", name); 2561 2562 if (dtype.isArray()) { 2563 log.trace("extractCompoundInfo(): array type - extracting compound info from base datatype"); 2564 H5Datatype.extractCompoundInfo((H5Datatype)dtype.getDatatypeBase(), name, names, flatListTypes); 2565 } 2566 else if (dtype.isVLEN() && !dtype.isVarStr()) { 2567 log.trace( 2568 "extractCompoundInfo(): variable-length type - extracting compound info from base datatype"); 2569 H5Datatype.extractCompoundInfo((H5Datatype)dtype.getDatatypeBase(), name, names, flatListTypes); 2570 } 2571 else if (dtype.isCompound()) { 2572 List<String> compoundMemberNames = dtype.getCompoundMemberNames(); 2573 List<Datatype> compoundMemberTypes = dtype.getCompoundMemberTypes(); 2574 Datatype mtype = null; 2575 String mname = null; 2576 2577 if (compoundMemberNames == null) { 2578 log.debug("extractCompoundInfo(): compoundMemberNames is null"); 2579 return; 2580 } 2581 2582 if (compoundMemberNames.isEmpty()) { 2583 log.debug("extractCompoundInfo(): compound datatype has no members"); 2584 return; 2585 } 2586 2587 log.trace("extractCompoundInfo(): nMembers={}", compoundMemberNames.size()); 2588 2589 for (int i = 0; i < compoundMemberNames.size(); i++) { 2590 log.trace("extractCompoundInfo(): member[{}]:", i); 2591 2592 mtype = compoundMemberTypes.get(i); 2593 2594 log.trace("extractCompoundInfo(): type={} with size={}", mtype.getDescription(), 2595 mtype.getDatatypeSize()); 2596 2597 if (names != null) { 2598 mname = name + compoundMemberNames.get(i); 2599 log.trace("extractCompoundInfo(): mname={}, name={}", mname, name); 2600 } 2601 2602 if (mtype.isCompound()) { 2603 H5Datatype.extractCompoundInfo((H5Datatype)mtype, mname + CompoundDS.SEPARATOR, names, 2604 flatListTypes); 2605 log.trace("extractCompoundInfo(): continue after recursive compound"); 2606 continue; 2607 } 2608 2609 if (names != null) { 2610 names.add(mname); 2611 } 2612 2613 flatListTypes.add(mtype); 2614 2615 /* 2616 * For ARRAY of COMPOUND and VLEN of COMPOUND types, we first add the top-level array or vlen 2617 * type to the list of datatypes, and then follow that with a listing of the datatypes inside 2618 * the nested compound. 2619 */ 2620 /* 2621 * TODO: Don't flatten variable-length types until true variable-length support is 2622 * implemented. 2623 */ 2624 if (mtype.isArray() /* || (mtype.isVLEN() && !mtype.isVarStr()) */) { 2625 H5Datatype.extractCompoundInfo((H5Datatype)mtype, mname + CompoundDS.SEPARATOR, names, 2626 flatListTypes); 2627 } 2628 } 2629 } 2630 } 2631 2632 /** 2633 * Creates a datatype of a compound with one field. This function is needed to read/write data field by 2634 * field. 2635 * 2636 * @param memberName 2637 * The name of the datatype 2638 * @return the identifier of the compound datatype. 2639 * @throws HDF5Exception 2640 * If there is an error at the HDF5 library level. 2641 */ 2642 public long createCompoundFieldType(String memberName) throws HDF5Exception 2643 { 2644 log.trace("createCompoundFieldType(): start member_name={}", memberName); 2645 2646 long topTID = HDF5Constants.H5I_INVALID_HID; 2647 long tmpTID1 = HDF5Constants.H5I_INVALID_HID; 2648 2649 try { 2650 if (this.isArray()) { 2651 log.trace("createCompoundFieldType(): array datatype"); 2652 2653 if (baseType != null) { 2654 log.trace("createCompoundFieldType(): creating compound field type from base datatype"); 2655 tmpTID1 = ((H5Datatype)baseType).createCompoundFieldType(memberName); 2656 } 2657 2658 log.trace("createCompoundFieldType(): creating container array datatype"); 2659 topTID = H5.H5Tarray_create(tmpTID1, arrayDims.length, arrayDims); 2660 } 2661 else if (this.isVLEN()) { 2662 log.trace("createCompoundFieldType(): variable-length datatype"); 2663 2664 if (baseType != null) { 2665 log.trace("createCompoundFieldType(): creating compound field type from base datatype"); 2666 tmpTID1 = ((H5Datatype)baseType).createCompoundFieldType(memberName); 2667 } 2668 2669 log.trace("createCompoundFieldType(): creating container variable-length datatype"); 2670 topTID = H5.H5Tvlen_create(tmpTID1); 2671 } 2672 else if (this.isCompound()) { 2673 log.trace("createCompoundFieldType(): compound datatype"); 2674 2675 String insertedName = memberName; 2676 2677 int sep = memberName.indexOf(CompoundDS.SEPARATOR); 2678 if (sep >= 0) { 2679 /* 2680 * If a compound separator character is present in the supplied string, then there is an 2681 * additional level of compound nesting. We will create a compound type to hold the nested 2682 * compound type. 2683 */ 2684 insertedName = memberName.substring(0, sep); 2685 2686 log.trace("createCompoundFieldType(): member with name {} is nested inside compound", 2687 insertedName); 2688 } 2689 2690 /* 2691 * Retrieve the index of the compound member by its name. 2692 */ 2693 int memberIndex = this.compoundMemberNames.indexOf(insertedName); 2694 if (memberIndex >= 0) { 2695 H5Datatype memberType = (H5Datatype)this.compoundMemberTypes.get(memberIndex); 2696 2697 log.trace("createCompoundFieldType(): Member {} is type {} of size={} with baseType={}", 2698 insertedName, memberType.getDescription(), memberType.getDatatypeSize(), 2699 memberType.getDatatypeBase()); 2700 2701 if (sep >= 0) 2702 /* 2703 * Additional compound nesting; create the nested compound type. 2704 */ 2705 tmpTID1 = memberType.createCompoundFieldType(memberName.substring(sep + 1)); 2706 else 2707 tmpTID1 = memberType.createNative(); 2708 2709 log.trace("createCompoundFieldType(): creating container compound datatype"); 2710 topTID = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, datatypeSize); 2711 2712 log.trace("createCompoundFieldType(): inserting member {} into compound datatype", 2713 insertedName); 2714 H5.H5Tinsert(topTID, insertedName, 0, tmpTID1); 2715 2716 /* 2717 * WARNING!!! This step is crucial. Without it, the compound type created might be larger 2718 * than the size of the single datatype field we are inserting. Performing a read with a 2719 * compound datatype of an incorrect size will corrupt JVM memory and cause strange 2720 * behavior and crashes. 2721 */ 2722 H5.H5Tpack(topTID); 2723 } 2724 else { 2725 log.debug( 2726 "createCompoundFieldType(): member name {} not found in compound datatype's member name list", 2727 memberName); 2728 } 2729 } 2730 } 2731 catch (Exception ex) { 2732 log.debug("createCompoundFieldType(): creation of compound field type failed: ", ex); 2733 topTID = HDF5Constants.H5I_INVALID_HID; 2734 } 2735 finally { 2736 close(tmpTID1); 2737 } 2738 2739 return topTID; 2740 } 2741 2742 private boolean datatypeIsComplex(long tid) 2743 { 2744 long tclass = HDF5Constants.H5T_NO_CLASS; 2745 2746 try { 2747 tclass = H5.H5Tget_class(tid); 2748 log.trace("datatypeIsComplex():{}", tclass); 2749 } 2750 catch (Exception ex) { 2751 log.debug("datatypeIsComplex():", ex); 2752 } 2753 2754 boolean retVal = (tclass == HDF5Constants.H5T_COMPOUND); 2755 retVal |= (tclass == HDF5Constants.H5T_ENUM); 2756 retVal |= (tclass == HDF5Constants.H5T_VLEN); 2757 retVal |= (tclass == HDF5Constants.H5T_ARRAY); 2758 2759 return retVal; 2760 } 2761 2762 private boolean datatypeIsReference(long tid) 2763 { 2764 long tclass = HDF5Constants.H5T_NO_CLASS; 2765 2766 try { 2767 tclass = H5.H5Tget_class(tid); 2768 log.trace("datatypeIsReference():{}", tclass); 2769 } 2770 catch (Exception ex) { 2771 log.debug("datatypeIsReference():", ex); 2772 } 2773 2774 return (tclass == HDF5Constants.H5T_REFERENCE); 2775 } 2776 2777 private boolean datatypeIsAtomic(long tid) 2778 { 2779 boolean retVal = !(datatypeIsComplex(tid) | datatypeIsReference(tid) | isRef()); 2780 retVal |= isOpaque(); 2781 retVal |= isBitField(); 2782 2783 return retVal; 2784 } 2785 2786 private boolean datatypeClassIsComplex(long tclass) 2787 { 2788 boolean retVal = (tclass == HDF5Constants.H5T_COMPOUND); 2789 retVal |= (tclass == HDF5Constants.H5T_ENUM); 2790 retVal |= (tclass == HDF5Constants.H5T_VLEN); 2791 retVal |= (tclass == HDF5Constants.H5T_ARRAY); 2792 2793 return retVal; 2794 } 2795 2796 private boolean datatypeClassIsReference(long tclass) { return (tclass == HDF5Constants.H5T_REFERENCE); } 2797 2798 private boolean datatypeClassIsOpaque(long tclass) { return (tclass == Datatype.CLASS_OPAQUE); } 2799 2800 private boolean datatypeClassIsAtomic(long tclass) 2801 { 2802 boolean retVal = !(datatypeClassIsComplex(tclass) | datatypeClassIsReference(tclass)); 2803 retVal |= (tclass == Datatype.CLASS_OPAQUE); 2804 retVal |= (tclass == Datatype.CLASS_BITFIELD); 2805 2806 return retVal; 2807 } 2808}