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 if (datatypeSize == 8) 1424 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_DOUBLE); 1425 else 1426 tid = H5.H5Tcopy((datatypeSize == 4) ? HDF5Constants.H5T_NATIVE_FLOAT 1427 : HDF5Constants.H5T_NATIVE_FLOAT16); 1428 1429 if (datatypeOrder == Datatype.ORDER_BE) { 1430 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1431 } 1432 else if (datatypeOrder == Datatype.ORDER_LE) { 1433 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1434 } 1435 1436 if (nativeFPebias > 0) { 1437 H5.H5Tset_ebias(tid, nativeFPebias); 1438 } 1439 1440 if (nativeFPnorm >= 0) { 1441 H5.H5Tset_norm(tid, nativeFPnorm); 1442 } 1443 1444 if (nativeFPinpad >= 0) { 1445 H5.H5Tset_inpad(tid, nativeFPinpad); 1446 } 1447 1448 if ((nativeFPesize >= 0) && (nativeFPmsize >= 0)) { 1449 H5.H5Tset_fields(tid, nativeFPspos, nativeFPmpos, nativeFPesize, nativeFPmpos, 1450 nativeFPmsize); 1451 } 1452 } 1453 catch (Exception ex) { 1454 log.debug("createNative(): native floating-point datatype creation failed: ", ex); 1455 if (tid >= 0) 1456 close(tid); 1457 tid = HDF5Constants.H5I_INVALID_HID; 1458 } 1459 1460 break; 1461 case CLASS_CHAR: 1462 try { 1463 tid = H5.H5Tcopy((datatypeSign == Datatype.SIGN_NONE) ? HDF5Constants.H5T_NATIVE_UCHAR 1464 : HDF5Constants.H5T_NATIVE_CHAR); 1465 } 1466 catch (Exception ex) { 1467 log.debug("createNative(): native character datatype creation failed: ", ex); 1468 if (tid >= 0) 1469 close(tid); 1470 tid = HDF5Constants.H5I_INVALID_HID; 1471 } 1472 1473 break; 1474 case CLASS_STRING: 1475 try { 1476 tid = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 1477 1478 H5.H5Tset_size(tid, (isVLEN || datatypeSize < 0) ? HDF5Constants.H5T_VARIABLE : datatypeSize); 1479 1480 log.trace("createNative(): isVlenStr={} nativeStrPad={} nativeStrCSET={}", isVLEN, 1481 nativeStrPad, nativeStrCSET); 1482 1483 H5.H5Tset_strpad(tid, (nativeStrPad >= 0) ? nativeStrPad : HDF5Constants.H5T_STR_NULLTERM); 1484 1485 if (nativeStrCSET >= 0) { 1486 H5.H5Tset_cset(tid, nativeStrCSET); 1487 } 1488 } 1489 catch (Exception ex) { 1490 log.debug("createNative(): native string datatype creation failed: ", ex); 1491 if (tid >= 0) 1492 close(tid); 1493 tid = HDF5Constants.H5I_INVALID_HID; 1494 } 1495 1496 break; 1497 case CLASS_REFERENCE: 1498 try { 1499 long objRefTypeSize = H5.H5Tget_size(HDF5Constants.H5T_STD_REF_OBJ); 1500 long dsetRefTypeSize = H5.H5Tget_size(HDF5Constants.H5T_STD_REF_DSETREG); 1501 // use datatypeSize as which type to copy 1502 log.debug("createNative(): datatypeSize:{} ", datatypeSize); 1503 if (datatypeSize < 0 || datatypeSize > dsetRefTypeSize) { 1504 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF); 1505 log.debug("createNative(): HDF5Constants.H5T_STD_REF"); 1506 } 1507 else if (datatypeSize > objRefTypeSize) { 1508 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_DSETREG); 1509 log.debug("createNative(): HDF5Constants.H5T_STD_REF_DSETREG"); 1510 } 1511 else { 1512 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_OBJ); 1513 log.debug("createNative(): HDF5Constants.H5T_STD_REF_OBJ"); 1514 } 1515 } 1516 catch (Exception ex) { 1517 log.debug("createNative(): native reference datatype creation failed: ", ex); 1518 if (tid >= 0) 1519 close(tid); 1520 tid = HDF5Constants.H5I_INVALID_HID; 1521 } 1522 1523 break; 1524 case CLASS_VLEN: 1525 try { 1526 if (baseType == null) { 1527 log.debug("createNative(): CLASS_VLEN base type is NULL"); 1528 break; 1529 } 1530 1531 if ((tmptid = baseType.createNative()) < 0) { 1532 log.debug("createNative(): failed to create native datatype for VLEN base datatype"); 1533 break; 1534 } 1535 1536 tid = H5.H5Tvlen_create(tmptid); 1537 } 1538 catch (Exception ex) { 1539 log.debug("createNative(): native variable-length datatype creation failed: ", ex); 1540 if (tid >= 0) 1541 close(tid); 1542 tid = HDF5Constants.H5I_INVALID_HID; 1543 } 1544 finally { 1545 close(tmptid); 1546 } 1547 1548 break; 1549 case CLASS_BITFIELD: 1550 log.trace("createNative(): CLASS_BITFIELD size is {}", datatypeSize); 1551 1552 try { 1553 switch ((int)datatypeSize) { 1554 case 1: 1555 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B8"); 1556 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B8); 1557 break; 1558 case 2: 1559 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B16"); 1560 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B16); 1561 break; 1562 case 4: 1563 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B32"); 1564 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B32); 1565 break; 1566 case 8: 1567 log.trace("createNative(): CLASS_BITFIELD is H5T_NATIVE_B64"); 1568 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B64); 1569 break; 1570 default: 1571 if (datatypeSize == NATIVE) { 1572 datatypeNATIVE = true; 1573 datatypeSize = 1; 1574 } 1575 else 1576 datatypeNATIVE = false; 1577 1578 /* Custom sized bitfield */ 1579 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_B8); 1580 H5.H5Tset_size(tid, datatypeSize); 1581 H5.H5Tset_precision(tid, 8 * datatypeSize); 1582 1583 break; 1584 } 1585 1586 if (datatypeOrder == Datatype.ORDER_BE) { 1587 log.trace("createNative(): CLASS_BITFIELD order is H5T_ORDER_BE"); 1588 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 1589 } 1590 else if (datatypeOrder == Datatype.ORDER_LE) { 1591 log.trace("createNative(): CLASS_BITFIELD order is H5T_ORDER_LE"); 1592 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 1593 } 1594 } 1595 catch (Exception ex) { 1596 log.debug("createNative(): native bitfield datatype creation failed: ", ex); 1597 if (tid >= 0) 1598 close(tid); 1599 tid = HDF5Constants.H5I_INVALID_HID; 1600 } 1601 1602 break; 1603 case CLASS_OPAQUE: 1604 log.trace("createNative(): CLASS_OPAQUE is {}-byte H5T_OPAQUE", datatypeSize); 1605 1606 try { 1607 if (datatypeSize == NATIVE) { 1608 datatypeNATIVE = true; 1609 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_OPAQUE); 1610 datatypeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_OPAQUE); 1611 } 1612 else { 1613 datatypeNATIVE = false; 1614 tid = H5.H5Tcreate(HDF5Constants.H5T_OPAQUE, datatypeSize); 1615 } 1616 1617 if (opaqueTag != null) { 1618 H5.H5Tset_tag(tid, opaqueTag); 1619 } 1620 } 1621 catch (Exception ex) { 1622 log.debug("createNative(): native opaque datatype creation failed: ", ex); 1623 if (tid >= 0) 1624 close(tid); 1625 tid = HDF5Constants.H5I_INVALID_HID; 1626 } 1627 1628 break; 1629 default: 1630 log.debug("createNative(): Unknown class"); 1631 break; 1632 } // (tclass) 1633 1634 // set up enum members 1635 if ((datatypeClass == CLASS_ENUM) && (enumMembers != null)) { 1636 log.trace("createNative(): set up enum members"); 1637 try { 1638 String memstr; 1639 String memname; 1640 byte[] memval = null; 1641 1642 Iterator entries = enumMembers.entrySet().iterator(); 1643 while (entries.hasNext()) { 1644 Entry thisEntry = (Entry)entries.next(); 1645 memstr = (String)thisEntry.getKey(); 1646 memname = (String)thisEntry.getValue(); 1647 1648 if (datatypeSize == 1) { 1649 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT8"); 1650 Byte tval = Byte.parseByte(memstr); 1651 memval = HDFNativeData.byteToByte(tval); 1652 } 1653 else if (datatypeSize == 2) { 1654 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT16"); 1655 Short tval = Short.parseShort(memstr); 1656 memval = HDFNativeData.shortToByte(tval); 1657 } 1658 else if (datatypeSize == 4) { 1659 log.trace("createNative(): CLASS_ENUM is H5T_NATIVE_INT32"); 1660 Integer tval = Integer.parseInt(memstr); 1661 memval = HDFNativeData.intToByte(tval); 1662 } 1663 else if (datatypeSize == 8) { 1664 log.trace("createNative(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 1665 Long tval = Long.parseLong(memstr); 1666 memval = HDFNativeData.longToByte(tval); 1667 } 1668 else { 1669 log.debug("createNative(): enum datatypeSize incorrect"); 1670 } 1671 log.trace("createNative(): H5Tenum_insert {} {}", memname, memval); 1672 H5.H5Tenum_insert(tid, memname, memval); 1673 } 1674 } 1675 catch (Exception ex) { 1676 log.debug("createNative(): set up enum members failure: ", ex); 1677 } 1678 } // (datatypeClass == CLASS_ENUM) 1679 1680 try { 1681 tmptid = tid; 1682 tid = H5.H5Tget_native_type(tmptid); 1683 } 1684 catch (HDF5Exception ex) { 1685 log.debug("createNative(): H5Tget_native_type({}) failure: ", tmptid, ex); 1686 } 1687 finally { 1688 close(tmptid); 1689 } 1690 1691 return tid; 1692 } 1693 1694 /** 1695 * Allocates a one-dimensional array of byte, short, int, long, float, double, or String to store data in 1696 * memory. For example, 1697 * 1698 * <pre> 1699 * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 1700 * int[] data = (int[]) H5Datatype.allocateArray(datatype, 100); 1701 * </pre> 1702 * 1703 * returns a 32-bit integer array of size 100. 1704 * 1705 * @param dtype 1706 * the type. 1707 * @param numPoints 1708 * the total number of data points of the array. 1709 * @return the array object if successful; otherwise, return null. 1710 * @throws OutOfMemoryError 1711 * If there is a failure. 1712 */ 1713 public static final Object allocateArray(final H5Datatype dtype, int numPoints) throws OutOfMemoryError 1714 { 1715 log.trace("allocateArray(): start: numPoints={}", numPoints); 1716 1717 Object data = null; 1718 H5Datatype baseType = (H5Datatype)dtype.getDatatypeBase(); 1719 int typeClass = dtype.getDatatypeClass(); 1720 long typeSize = dtype.getDatatypeSize(); 1721 1722 if (numPoints < 0) { 1723 log.debug("allocateArray(): numPoints < 0"); 1724 return null; 1725 } 1726 1727 // Scalar members have dimensionality zero, i.e. size =0 1728 // what can we do about it, set the size to 1 1729 if (numPoints == 0) 1730 numPoints = 1; 1731 1732 log.trace("allocateArray(): tclass={} : tsize={}", typeClass, typeSize); 1733 1734 if (dtype.isVarStr()) { 1735 log.trace("allocateArray(): is_variable_str={}", dtype.isVarStr()); 1736 1737 data = new String[numPoints]; 1738 for (int i = 0; i < numPoints; i++) 1739 ((String[])data)[i] = ""; 1740 } 1741 else if (typeClass == HDF5Constants.H5T_INTEGER) { 1742 log.trace("allocateArray(): class H5T_INTEGER"); 1743 if (typeSize == NATIVE) 1744 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1745 1746 switch ((int)typeSize) { 1747 case 1: 1748 data = new byte[numPoints]; 1749 break; 1750 case 2: 1751 data = new short[numPoints]; 1752 break; 1753 case 4: 1754 data = new int[numPoints]; 1755 break; 1756 case 8: 1757 data = new long[numPoints]; 1758 break; 1759 default: 1760 break; 1761 } 1762 } 1763 else if (typeClass == HDF5Constants.H5T_ENUM) { 1764 log.trace("allocateArray(): class H5T_ENUM"); 1765 1766 if (baseType != null) 1767 data = H5Datatype.allocateArray(baseType, numPoints); 1768 else { 1769 if (typeSize == NATIVE) 1770 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT); 1771 data = new byte[(int)(numPoints * typeSize)]; 1772 } 1773 } 1774 else if (typeClass == HDF5Constants.H5T_COMPOUND) { 1775 log.trace("allocateArray(): class H5T_COMPOUND"); 1776 1777 data = new ArrayList<>(dtype.getCompoundMemberTypes().size()); 1778 } 1779 else if (typeClass == HDF5Constants.H5T_FLOAT) { 1780 log.trace("allocateArray(): class H5T_FLOAT"); 1781 if (typeSize == NATIVE) 1782 typeSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_FLOAT); 1783 1784 switch ((int)typeSize) { 1785 case 2: 1786 data = new short[numPoints]; 1787 break; 1788 case 4: 1789 data = new float[numPoints]; 1790 break; 1791 case 8: 1792 data = new double[numPoints]; 1793 break; 1794 case 16: 1795 data = new byte[numPoints * 16]; 1796 break; 1797 default: 1798 break; 1799 } 1800 } 1801 else if ((typeClass == HDF5Constants.H5T_STRING) || (typeClass == HDF5Constants.H5T_REFERENCE)) { 1802 log.trace("allocateArray(): class H5T_STRING || H5T_REFERENCE"); 1803 1804 data = new byte[(int)(numPoints * typeSize)]; 1805 } 1806 else if (dtype.isVLEN()) { 1807 log.trace("allocateArray(): isVLEN"); 1808 1809 data = new ArrayList[numPoints]; 1810 for (int j = 0; j < numPoints; j++) 1811 ((ArrayList[])data)[j] = new ArrayList<byte[]>(); 1812 // if (baseType != null) 1813 // ((ArrayList<>)data).add(H5Datatype.allocateArray(baseType, numPoints)); 1814 } 1815 else if (typeClass == HDF5Constants.H5T_ARRAY) { 1816 log.trace("allocateArray(): class H5T_ARRAY"); 1817 1818 try { 1819 log.trace("allocateArray(): ArrayRank={}", dtype.getArrayDims().length); 1820 1821 // Use the base datatype to define the array 1822 long[] arrayDims = dtype.getArrayDims(); 1823 int asize = numPoints; 1824 for (int j = 0; j < arrayDims.length; j++) { 1825 log.trace("allocateArray(): Array dims[{}]={}", j, arrayDims[j]); 1826 1827 asize *= arrayDims[j]; 1828 } 1829 1830 if (baseType != null) 1831 data = H5Datatype.allocateArray(baseType, asize); 1832 } 1833 catch (Exception ex) { 1834 log.debug("allocateArray(): H5T_ARRAY class failure: ", ex); 1835 } 1836 } 1837 else if ((typeClass == HDF5Constants.H5T_OPAQUE) || (typeClass == HDF5Constants.H5T_BITFIELD)) { 1838 log.trace("allocateArray(): class H5T_OPAQUE || H5T_BITFIELD"); 1839 if (typeSize == NATIVE) 1840 typeSize = H5.H5Tget_size(typeClass); 1841 1842 data = new byte[(int)(numPoints * typeSize)]; 1843 } 1844 else { 1845 log.debug("allocateArray(): class ???? ({})", typeClass); 1846 1847 data = null; 1848 } 1849 1850 return data; 1851 } 1852 1853 /** 1854 * Returns the size (in bytes) of a given datatype identifier. It basically just calls H5Tget_size(tid). 1855 * 1856 * @param tid 1857 * The datatype identifier. 1858 * @return The size of the datatype in bytes. 1859 * @see hdf.hdf5lib.H5#H5Tget_size(long) 1860 */ 1861 public static final long getDatatypeSize(long tid) 1862 { 1863 // data type information 1864 long tsize = -1; 1865 1866 try { 1867 tsize = H5.H5Tget_size(tid); 1868 } 1869 catch (Exception ex) { 1870 tsize = -1; 1871 } 1872 1873 return tsize; 1874 } 1875 1876 /* 1877 * (non-Javadoc) 1878 * @see hdf.object.Datatype#getDescription() 1879 */ 1880 @Override 1881 public String getDescription() 1882 { 1883 log.trace("getDescription(): start - isNamed={}", isNamed()); 1884 1885 if (datatypeDescription != null) 1886 return datatypeDescription; 1887 1888 StringBuilder description = new StringBuilder(); 1889 long tid = HDF5Constants.H5I_INVALID_HID; 1890 1891 switch (datatypeClass) { 1892 case CLASS_CHAR: 1893 log.trace("getDescription(): Char"); 1894 description.append("8-bit ").append(isUnsigned() ? "unsigned " : "").append("integer"); 1895 break; 1896 case CLASS_INTEGER: 1897 log.trace("getDescription(): Int [{}]", datatypeNATIVE); 1898 if (datatypeNATIVE) 1899 description.append("native ").append(isUnsigned() ? "unsigned " : "").append("integer"); 1900 else 1901 description.append(String.valueOf(datatypeSize * 8)) 1902 .append("-bit ") 1903 .append(isUnsigned() ? "unsigned " : "") 1904 .append("integer"); 1905 break; 1906 case CLASS_FLOAT: 1907 log.trace("getDescription(): Float"); 1908 if (datatypeNATIVE) 1909 description.append("native floating-point"); 1910 else 1911 description.append(String.valueOf(datatypeSize * 8)).append("-bit floating-point"); 1912 break; 1913 case CLASS_STRING: 1914 log.trace("getDescription(): String"); 1915 description.append("String, length = ").append(isVarStr() ? "variable" : datatypeSize); 1916 1917 try { 1918 tid = createNative(); 1919 if (tid >= 0) { 1920 String strPadType; 1921 String strCSETType; 1922 int strPad = H5.H5Tget_strpad(tid); 1923 int strCSET = H5.H5Tget_cset(tid); 1924 1925 if (strPad == HDF5Constants.H5T_STR_NULLTERM) 1926 strPadType = "H5T_STR_NULLTERM"; 1927 else if (strPad == HDF5Constants.H5T_STR_NULLPAD) 1928 strPadType = "H5T_STR_NULLPAD"; 1929 else if (strPad == HDF5Constants.H5T_STR_SPACEPAD) 1930 strPadType = "H5T_STR_SPACEPAD"; 1931 else 1932 strPadType = null; 1933 1934 if (strPadType != null) 1935 description.append(", padding = ").append(strPadType); 1936 1937 if (strCSET == HDF5Constants.H5T_CSET_ASCII) 1938 strCSETType = "H5T_CSET_ASCII"; 1939 else if (strCSET == HDF5Constants.H5T_CSET_UTF8) 1940 strCSETType = "H5T_CSET_UTF8"; 1941 else 1942 strCSETType = null; 1943 1944 if (strCSETType != null) 1945 description.append(", cset = ").append(strCSETType); 1946 } 1947 else { 1948 log.debug("createNative() failure"); 1949 } 1950 } 1951 catch (Exception ex) { 1952 log.debug("H5Tget_strpad failure: ", ex); 1953 } 1954 finally { 1955 close(tid); 1956 } 1957 break; 1958 case CLASS_BITFIELD: 1959 log.trace("getDescription(): Bit"); 1960 if (datatypeNATIVE) 1961 description.append("native bitfield"); 1962 else 1963 description.append(String.valueOf(datatypeSize * 8)).append("-bit bitfield"); 1964 break; 1965 case CLASS_OPAQUE: 1966 log.trace("getDescription(): Opaque"); 1967 if (datatypeNATIVE) 1968 description.append("native Opaque"); 1969 else 1970 description.append(String.valueOf(datatypeSize)).append("-byte Opaque"); 1971 1972 if (opaqueTag != null) { 1973 description.append(", tag = ").append(opaqueTag); 1974 } 1975 1976 break; 1977 case CLASS_COMPOUND: 1978 log.trace("getDescription(): Compound"); 1979 description.append("Compound"); 1980 1981 if ((compoundMemberTypes != null) && !compoundMemberTypes.isEmpty()) { 1982 Iterator<String> memberNames = null; 1983 Iterator<Datatype> memberTypes = compoundMemberTypes.iterator(); 1984 1985 if (compoundMemberNames != null) 1986 memberNames = compoundMemberNames.iterator(); 1987 1988 description.append(" {"); 1989 1990 while (memberTypes.hasNext()) { 1991 if (memberNames != null && memberNames.hasNext()) { 1992 description.append(memberNames.next()).append(" = "); 1993 } 1994 1995 description.append(memberTypes.next().getDescription()); 1996 1997 if (memberTypes.hasNext()) 1998 description.append(", "); 1999 } 2000 2001 description.append("}"); 2002 } 2003 2004 break; 2005 case CLASS_REFERENCE: 2006 log.trace("getDescription(): Ref"); 2007 description.append("Reference"); 2008 2009 try { 2010 boolean isRegionType = false; 2011 2012 tid = createNative(); 2013 if (tid >= 0) { 2014 if (!H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF)) { 2015 isRegionType = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 2016 2017 description.setLength(0); 2018 if (isRegionType) { 2019 description.append("Dataset region reference"); 2020 } 2021 else { 2022 description.append("Object reference"); 2023 } 2024 } 2025 } 2026 } 2027 catch (Exception ex) { 2028 log.debug("H5.H5Tequal failure: ", ex); 2029 } 2030 finally { 2031 close(tid); 2032 } 2033 2034 break; 2035 case CLASS_ENUM: 2036 log.trace("getDescription(): Enum"); 2037 if (datatypeNATIVE) 2038 description.append("native enum"); 2039 else 2040 description.append(String.valueOf(datatypeSize * 8)).append("-bit enum"); 2041 2042 String members = getEnumMembersAsString(); 2043 if (members != null) 2044 description.append(" (").append(members).append(")"); 2045 2046 break; 2047 case CLASS_VLEN: 2048 log.trace("getDescription(): Var Len"); 2049 description.append("Variable-length"); 2050 2051 if (baseType != null) 2052 description.append(" of ").append(baseType.getDescription()); 2053 2054 break; 2055 case CLASS_ARRAY: 2056 log.trace("getDescription(): Array"); 2057 description.append("Array"); 2058 2059 if (arrayDims != null) { 2060 description.append(" ["); 2061 for (int i = 0; i < arrayDims.length; i++) { 2062 description.append(arrayDims[i]); 2063 if (i < arrayDims.length - 1) 2064 description.append(" x "); 2065 } 2066 description.append("]"); 2067 } 2068 2069 if (baseType != null) 2070 description.append(" of ").append(baseType.getDescription()); 2071 2072 break; 2073 default: 2074 description.append("Unknown"); 2075 break; 2076 } 2077 if (isNamed()) 2078 description.append("->").append(getFullName()); 2079 2080 return description.toString(); 2081 } 2082 2083 /** 2084 * Checks if a datatype specified by the identifier is an unsigned integer. 2085 * 2086 * @param tid 2087 * the datatype ID to be checked. 2088 * @return true is the datatype is an unsigned integer; otherwise returns false. 2089 */ 2090 public static final boolean isUnsigned(long tid) 2091 { 2092 boolean unsigned = false; 2093 2094 if (tid >= 0) { 2095 try { 2096 int tclass = H5.H5Tget_class(tid); 2097 log.trace("isUnsigned(): tclass = {}", tclass); 2098 if (tclass != HDF5Constants.H5T_FLOAT && tclass != HDF5Constants.H5T_STRING && 2099 tclass != HDF5Constants.H5T_REFERENCE && tclass != HDF5Constants.H5T_BITFIELD && 2100 tclass != HDF5Constants.H5T_OPAQUE && tclass != HDF5Constants.H5T_VLEN && 2101 tclass != HDF5Constants.H5T_COMPOUND && tclass != HDF5Constants.H5T_ARRAY) { 2102 int tsign = H5.H5Tget_sign(tid); 2103 if (tsign == HDF5Constants.H5T_SGN_NONE) 2104 unsigned = true; 2105 else 2106 log.trace("isUnsigned(): not unsigned"); 2107 } 2108 else { 2109 log.trace("isUnsigned(): tclass not integer type"); 2110 } 2111 } 2112 catch (Exception ex) { 2113 log.debug("isUnsigned(): Datatype {} failure", tid, ex); 2114 unsigned = false; 2115 } 2116 } 2117 else { 2118 log.trace("isUnsigned(): not a valid datatype"); 2119 } 2120 2121 return unsigned; 2122 } 2123 2124 /** 2125 * Removes all of the elements from metadata list. The list should be empty after this call returns. 2126 */ 2127 @Override 2128 public void clear() 2129 { 2130 super.clear(); 2131 objMetadata.clear(); 2132 } 2133 2134 /** 2135 * Retrieves the object's metadata, such as attributes, from the file. Metadata, such as attributes, is 2136 * stored in a List. 2137 * 2138 * @return the list of metadata objects. 2139 * @throws HDF5Exception 2140 * if the metadata can not be retrieved 2141 */ 2142 @Override 2143 public List<Attribute> getMetadata() throws HDF5Exception 2144 { 2145 int gmIndexType = 0; 2146 int gmIndexOrder = 0; 2147 2148 try { 2149 gmIndexType = fileFormat.getIndexType(null); 2150 } 2151 catch (Exception ex) { 2152 log.debug("getMetadata(): getIndexType failed: ", ex); 2153 } 2154 try { 2155 gmIndexOrder = fileFormat.getIndexOrder(null); 2156 } 2157 catch (Exception ex) { 2158 log.debug("getMetadata(): getIndexOrder failed: ", ex); 2159 } 2160 return this.getMetadata(gmIndexType, gmIndexOrder); 2161 } 2162 2163 /** 2164 * Retrieves the object's metadata, such as attributes, from the file. Metadata, such as attributes, is 2165 * stored in a List. 2166 * 2167 * @param attrPropList 2168 * the list of properties to get 2169 * @return the list of metadata objects. 2170 * @throws HDF5Exception 2171 * if the metadata can not be retrieved 2172 */ 2173 public List<Attribute> getMetadata(int... attrPropList) throws HDF5Exception 2174 { 2175 try { 2176 this.linkTargetObjName = H5File.getLinkTargetName(this); 2177 } 2178 catch (Exception ex) { 2179 log.debug("getMetadata(): getLinkTargetName failed: ", ex); 2180 } 2181 2182 List<Attribute> attrlist = null; 2183 try { 2184 attrlist = objMetadata.getMetadata(attrPropList); 2185 } 2186 catch (Exception ex) { 2187 log.debug("getMetadata(): getMetadata failed: ", ex); 2188 } 2189 return attrlist; 2190 } 2191 2192 /** 2193 * Writes a specific piece of metadata (such as an attribute) into the file. If an HDF(4&5) attribute 2194 * exists in the file, this method updates its value. If the attribute does not exist in the file, it 2195 * creates the attribute in the file and attaches it to the object. It will fail to write a new attribute 2196 * to the object where an attribute with the same name already exists. To update the value of an existing 2197 * attribute in the file, one needs to get the instance of the attribute by getMetadata(), change its 2198 * values, then use writeMetadata() to write the value. 2199 * 2200 * @param info 2201 * the metadata to write. 2202 * @throws Exception 2203 * if the metadata can not be written 2204 */ 2205 @Override 2206 public void writeMetadata(Object info) throws Exception 2207 { 2208 try { 2209 objMetadata.writeMetadata(info); 2210 } 2211 catch (Exception ex) { 2212 log.debug("writeMetadata(): Object not an Attribute"); 2213 } 2214 } 2215 2216 /** 2217 * Deletes an existing piece of metadata from this object. 2218 * 2219 * @param info 2220 * the metadata to delete. 2221 * @throws HDF5Exception 2222 * if the metadata can not be removed 2223 */ 2224 @Override 2225 public void removeMetadata(Object info) throws HDF5Exception 2226 { 2227 try { 2228 objMetadata.removeMetadata(info); 2229 } 2230 catch (Exception ex) { 2231 log.debug("removeMetadata(): Object not an Attribute"); 2232 return; 2233 } 2234 2235 Attribute attr = (Attribute)info; 2236 log.trace("removeMetadata(): {}", attr.getAttributeName()); 2237 long tid = open(); 2238 if (tid >= 0) { 2239 try { 2240 H5.H5Adelete(tid, attr.getAttributeName()); 2241 } 2242 catch (Exception ex) { 2243 log.debug("removeMetadata(): ", ex); 2244 } 2245 finally { 2246 close(tid); 2247 } 2248 } 2249 else { 2250 log.debug("removeMetadata(): failed to open datatype"); 2251 } 2252 } 2253 2254 /** 2255 * Updates an existing piece of metadata attached to this object. 2256 * 2257 * @param info 2258 * the metadata to update. 2259 * @throws HDF5Exception 2260 * if the metadata can not be updated 2261 */ 2262 @Override 2263 public void updateMetadata(Object info) throws HDF5Exception 2264 { 2265 try { 2266 objMetadata.updateMetadata(info); 2267 } 2268 catch (Exception ex) { 2269 log.debug("updateMetadata(): Object not an Attribute"); 2270 return; 2271 } 2272 } 2273 2274 /* 2275 * (non-Javadoc) 2276 * @see hdf.object.HObject#setName(java.lang.String) 2277 */ 2278 @Override 2279 public void setName(String newName) throws Exception 2280 { 2281 if (newName == null) 2282 throw new IllegalArgumentException("The new name is NULL"); 2283 2284 H5File.renameObject(this, newName); 2285 super.setName(newName); 2286 } 2287 2288 @Override 2289 public void setFullname(String newPath, String newName) throws Exception 2290 { 2291 H5File.renameObject(this, newPath, newName); 2292 super.setFullname(newPath, newName); 2293 } 2294 2295 @Override 2296 public boolean isText() 2297 { 2298 return (datatypeClass == Datatype.CLASS_STRING); 2299 } 2300 2301 /** 2302 * Checks if this datatype is an object reference type. 2303 * 2304 * @return true if the datatype is an object reference; false otherwise 2305 */ 2306 public boolean isRefObj() { return isRefObj; } 2307 2308 /** 2309 * Checks if this datatype is a region reference type. 2310 * 2311 * @return true if the datatype is a region reference; false otherwise 2312 */ 2313 public boolean isRegRef() { return isRegRef; } 2314 2315 /** 2316 * Checks if this datatype is a standard reference type. 2317 * 2318 * @return true if the datatype is a standard reference; false otherwise 2319 */ 2320 public boolean isStdRef() { return isStdRef; } 2321 2322 /* 2323 * (non-Javadoc) 2324 * @see hdf.object.Datatype#getReferenceType() 2325 */ 2326 @Override 2327 public long getReferenceType() throws HDF5Exception 2328 { 2329 if (isRegRef) 2330 return HDF5Constants.H5T_STD_REF_DSETREG; 2331 if (isRefObj) 2332 return HDF5Constants.H5T_STD_REF_OBJ; 2333 if (isStdRef) 2334 return HDF5Constants.H5T_STD_REF; 2335 return -1; 2336 } 2337 2338 /** 2339 * Describes the dataset object description for a 1.10 reference. 2340 * 2341 * @param container 2342 * the dataset/attribute with the reference 2343 * @param refarr 2344 * the reference datatype data to be checked. 2345 * 2346 * @return the dataset reference object description. 2347 */ 2348 public static String descReferenceObject(long container, byte[] refarr) 2349 { 2350 String region_desc = H5.H5Rget_name_string(container, HDF5Constants.H5R_OBJECT, refarr); 2351 region_desc += " H5O_TYPE_OBJ_REF"; 2352 log.trace("descReferenceObject region_desc={}:", region_desc); 2353 return region_desc; 2354 } 2355 2356 /** 2357 * Describes the dataset region description for a 1.10 reference. 2358 * 2359 * @param container 2360 * the dataset/attribute with the reference 2361 * @param refarr 2362 * the reference datatype data to be checked. 2363 * 2364 * @return the dataset region description. 2365 */ 2366 public static String descRegionDataset(long container, byte[] refarr) 2367 { 2368 String region_desc = H5.H5Rget_name_string(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2369 log.trace("descRegionDataset region_desc={}:", region_desc); 2370 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 2371 try { 2372 log.trace("descRegionDataset refarr2={}:", refarr); 2373 new_obj_id = H5.H5Rdereference(container, HDF5Constants.H5P_DEFAULT, 2374 HDF5Constants.H5R_DATASET_REGION, refarr); 2375 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 2376 try { 2377 log.trace("descRegionDataset refarr3={}:", refarr); 2378 new_obj_sid = H5.H5Rget_region(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2379 try { 2380 int region_type = H5.H5Sget_select_type(new_obj_sid); 2381 log.debug("descRegionDataset Reference Region Type {}", region_type); 2382 long reg_ndims = H5.H5Sget_simple_extent_ndims(new_obj_sid); 2383 StringBuilder sb = new StringBuilder(); 2384 if (HDF5Constants.H5S_SEL_POINTS == region_type) { 2385 sb.append(" REGION_TYPE POINT "); 2386 long reg_npoints = H5.H5Sget_select_elem_npoints(new_obj_sid); 2387 long getcoord[] = new long[(int)(reg_ndims * reg_npoints)]; 2388 try { 2389 H5.H5Sget_select_elem_pointlist(new_obj_sid, 0, reg_npoints, getcoord); 2390 } 2391 catch (Exception ex5) { 2392 log.debug("descRegionDataset H5.H5Sget_select_elem_pointlist: ", ex5); 2393 } 2394 sb.append("{ "); 2395 for (int i = 0; i < (int)reg_npoints; i++) { 2396 if (i > 0) 2397 sb.append(" "); 2398 sb.append("("); 2399 for (int j = 0; j < (int)reg_ndims; j++) { 2400 if (j > 0) 2401 sb.append(","); 2402 sb.append(getcoord[i * (int)reg_ndims + j]); 2403 } 2404 sb.append(")"); 2405 } 2406 sb.append(" }"); 2407 region_desc += sb.toString(); 2408 } 2409 else if (HDF5Constants.H5S_SEL_HYPERSLABS == region_type) { 2410 sb.append(" REGION_TYPE BLOCK "); 2411 long reg_nblocks = H5.H5Sget_select_hyper_nblocks(new_obj_sid); 2412 long getblocks[] = new long[(int)(reg_ndims * reg_nblocks) * 2]; 2413 try { 2414 H5.H5Sget_select_hyper_blocklist(new_obj_sid, 0, reg_nblocks, getblocks); 2415 } 2416 catch (Exception ex5) { 2417 log.debug("descRegionDataset H5.H5Sget_select_hyper_blocklist: ", ex5); 2418 } 2419 sb.append("{ "); 2420 for (int i = 0; i < (int)reg_nblocks; i++) { 2421 if (i > 0) 2422 sb.append(" "); 2423 sb.append("("); 2424 for (int j = 0; j < (int)reg_ndims; j++) { 2425 if (j > 0) 2426 sb.append(","); 2427 sb.append(getblocks[i * 2 * (int)reg_ndims + j]); 2428 } 2429 sb.append(")-("); 2430 for (int j = 0; j < (int)reg_ndims; j++) { 2431 if (j > 0) 2432 sb.append(","); 2433 sb.append(getblocks[i * 2 * (int)reg_ndims + (int)reg_ndims + j]); 2434 } 2435 sb.append(")"); 2436 } 2437 sb.append(" }"); 2438 region_desc += sb.toString(); 2439 } 2440 else 2441 region_desc += " REGION_TYPE UNKNOWN"; 2442 } 2443 catch (Exception ex4) { 2444 log.debug("descRegionDataset Region Type", ex4); 2445 } 2446 } 2447 catch (Exception ex3) { 2448 log.debug("descRegionDataset Space Open", ex3); 2449 } 2450 finally { 2451 H5.H5Sclose(new_obj_sid); 2452 } 2453 log.trace("descRegionDataset finish"); 2454 } 2455 catch (Exception ex2) { 2456 log.debug("descRegionDataset ", ex2); 2457 } 2458 finally { 2459 H5.H5Dclose(new_obj_id); 2460 } 2461 return region_desc; 2462 } 2463 2464 /** 2465 * Gets the dataset reference type for a 1.10 reference. 2466 * 2467 * @param container the dataset/attribute with the reference 2468 * @param obj_type the dataset/attribute object type 2469 * @param refarr the reference datatype data to be checked. 2470 * 2471 * @return the dataset reference type. 2472 */ 2473 public static int typeObjectRef(long container, int obj_type, byte[] refarr) 2474 { 2475 int ref_type = -1; 2476 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 2477 try { 2478 log.trace("typeObjectRef refarr2={}:", refarr); 2479 new_obj_id = H5.H5Rdereference(container, HDF5Constants.H5P_DEFAULT, obj_type, refarr); 2480 if (HDF5Constants.H5R_DATASET_REGION == obj_type) { 2481 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 2482 try { 2483 log.trace("typeObjectRef refarr3={}:", refarr); 2484 new_obj_sid = H5.H5Rget_region(container, HDF5Constants.H5R_DATASET_REGION, refarr); 2485 try { 2486 ref_type = H5.H5Sget_select_type(new_obj_sid); 2487 log.debug("typeObjectRef Reference Region Type {}", ref_type); 2488 } 2489 catch (Exception ex4) { 2490 log.debug("typeObjectRef Region Type", ex4); 2491 } 2492 } 2493 catch (Exception ex3) { 2494 log.debug("typeObjectRef Space Open", ex3); 2495 } 2496 finally { 2497 H5.H5Sclose(new_obj_sid); 2498 } 2499 } 2500 else { 2501 H5O_info_t objInfo; 2502 2503 objInfo = H5.H5Oget_info(new_obj_id); 2504 ref_type = objInfo.type; 2505 } 2506 log.trace("typeObjectRef finish"); 2507 } 2508 catch (Exception ex2) { 2509 log.debug("typeObjectRef ", ex2); 2510 } 2511 finally { 2512 H5.H5Dclose(new_obj_id); 2513 } 2514 return ref_type; 2515 } 2516 2517 /** 2518 * Checks if a reference datatype is all zero. 2519 * 2520 * @param refarr 2521 * the reference datatype data to be checked. 2522 * @return true is the reference datatype data is all zero; otherwise returns false. 2523 */ 2524 public static boolean zeroArrayCheck(final byte[] refarr) 2525 { 2526 for (byte b : refarr) { 2527 if (b != 0) 2528 return false; 2529 } 2530 return true; 2531 } 2532 2533 /** 2534 * Gets the string padding. 2535 * 2536 * @return the string padding value 2537 */ 2538 public int getNativeStrPad() { return nativeStrPad; } 2539 2540 /** 2541 * Extracts compound information into flat structure. For example, compound datatype "nest" has {nest1{a, 2542 * b, c}, d, e} then extractCompoundInfo() will put the names of nested compound fields into a flat list 2543 * as 2544 * 2545 * <pre> 2546 * nest.nest1.a 2547 * nest.nest1.b 2548 * nest.nest1.c 2549 * nest.d 2550 * nest.e 2551 * </pre> 2552 * 2553 * @param dtype 2554 * the datatype to extract compound info from 2555 * @param name 2556 * the name of the compound datatype 2557 * @param names 2558 * the list to store the member names of the compound datatype 2559 * @param flatListTypes 2560 * the list to store the nested member names of the compound datatype 2561 */ 2562 public static void extractCompoundInfo(final H5Datatype dtype, String name, List<String> names, 2563 List<Datatype> flatListTypes) 2564 { 2565 log.trace("extractCompoundInfo(): start: name={}", name); 2566 2567 if (dtype.isArray()) { 2568 log.trace("extractCompoundInfo(): array type - extracting compound info from base datatype"); 2569 H5Datatype.extractCompoundInfo((H5Datatype)dtype.getDatatypeBase(), name, names, flatListTypes); 2570 } 2571 else if (dtype.isVLEN() && !dtype.isVarStr()) { 2572 log.trace( 2573 "extractCompoundInfo(): variable-length type - extracting compound info from base datatype"); 2574 H5Datatype.extractCompoundInfo((H5Datatype)dtype.getDatatypeBase(), name, names, flatListTypes); 2575 } 2576 else if (dtype.isCompound()) { 2577 List<String> compoundMemberNames = dtype.getCompoundMemberNames(); 2578 List<Datatype> compoundMemberTypes = dtype.getCompoundMemberTypes(); 2579 Datatype mtype = null; 2580 String mname = null; 2581 2582 if (compoundMemberNames == null) { 2583 log.debug("extractCompoundInfo(): compoundMemberNames is null"); 2584 return; 2585 } 2586 2587 if (compoundMemberNames.isEmpty()) { 2588 log.debug("extractCompoundInfo(): compound datatype has no members"); 2589 return; 2590 } 2591 2592 log.trace("extractCompoundInfo(): nMembers={}", compoundMemberNames.size()); 2593 2594 for (int i = 0; i < compoundMemberNames.size(); i++) { 2595 log.trace("extractCompoundInfo(): member[{}]:", i); 2596 2597 mtype = compoundMemberTypes.get(i); 2598 2599 log.trace("extractCompoundInfo(): type={} with size={}", mtype.getDescription(), 2600 mtype.getDatatypeSize()); 2601 2602 if (names != null) { 2603 mname = name + compoundMemberNames.get(i); 2604 log.trace("extractCompoundInfo(): mname={}, name={}", mname, name); 2605 } 2606 2607 if (mtype.isCompound()) { 2608 H5Datatype.extractCompoundInfo((H5Datatype)mtype, mname + CompoundDS.SEPARATOR, names, 2609 flatListTypes); 2610 log.trace("extractCompoundInfo(): continue after recursive compound"); 2611 continue; 2612 } 2613 2614 if (names != null) { 2615 names.add(mname); 2616 } 2617 2618 flatListTypes.add(mtype); 2619 2620 /* 2621 * For ARRAY of COMPOUND and VLEN of COMPOUND types, we first add the top-level array or vlen 2622 * type to the list of datatypes, and then follow that with a listing of the datatypes inside 2623 * the nested compound. 2624 */ 2625 /* 2626 * TODO: Don't flatten variable-length types until true variable-length support is 2627 * implemented. 2628 */ 2629 if (mtype.isArray() /* || (mtype.isVLEN() && !mtype.isVarStr()) */) { 2630 H5Datatype.extractCompoundInfo((H5Datatype)mtype, mname + CompoundDS.SEPARATOR, names, 2631 flatListTypes); 2632 } 2633 } 2634 } 2635 } 2636 2637 /** 2638 * Creates a datatype of a compound with one field. This function is needed to read/write data field by 2639 * field. 2640 * 2641 * @param memberName 2642 * The name of the datatype 2643 * @return the identifier of the compound datatype. 2644 * @throws HDF5Exception 2645 * If there is an error at the HDF5 library level. 2646 */ 2647 public long createCompoundFieldType(String memberName) throws HDF5Exception 2648 { 2649 log.trace("createCompoundFieldType(): start member_name={}", memberName); 2650 2651 long topTID = HDF5Constants.H5I_INVALID_HID; 2652 long tmpTID1 = HDF5Constants.H5I_INVALID_HID; 2653 2654 try { 2655 if (this.isArray()) { 2656 log.trace("createCompoundFieldType(): array datatype"); 2657 2658 if (baseType != null) { 2659 log.trace("createCompoundFieldType(): creating compound field type from base datatype"); 2660 tmpTID1 = ((H5Datatype)baseType).createCompoundFieldType(memberName); 2661 } 2662 2663 log.trace("createCompoundFieldType(): creating container array datatype"); 2664 topTID = H5.H5Tarray_create(tmpTID1, arrayDims.length, arrayDims); 2665 } 2666 else if (this.isVLEN()) { 2667 log.trace("createCompoundFieldType(): variable-length datatype"); 2668 2669 if (baseType != null) { 2670 log.trace("createCompoundFieldType(): creating compound field type from base datatype"); 2671 tmpTID1 = ((H5Datatype)baseType).createCompoundFieldType(memberName); 2672 } 2673 2674 log.trace("createCompoundFieldType(): creating container variable-length datatype"); 2675 topTID = H5.H5Tvlen_create(tmpTID1); 2676 } 2677 else if (this.isCompound()) { 2678 log.trace("createCompoundFieldType(): compound datatype"); 2679 2680 String insertedName = memberName; 2681 2682 int sep = memberName.indexOf(CompoundDS.SEPARATOR); 2683 if (sep >= 0) { 2684 /* 2685 * If a compound separator character is present in the supplied string, then there is an 2686 * additional level of compound nesting. We will create a compound type to hold the nested 2687 * compound type. 2688 */ 2689 insertedName = memberName.substring(0, sep); 2690 2691 log.trace("createCompoundFieldType(): member with name {} is nested inside compound", 2692 insertedName); 2693 } 2694 2695 /* 2696 * Retrieve the index of the compound member by its name. 2697 */ 2698 int memberIndex = this.compoundMemberNames.indexOf(insertedName); 2699 if (memberIndex >= 0) { 2700 H5Datatype memberType = (H5Datatype)this.compoundMemberTypes.get(memberIndex); 2701 2702 log.trace("createCompoundFieldType(): Member {} is type {} of size={} with baseType={}", 2703 insertedName, memberType.getDescription(), memberType.getDatatypeSize(), 2704 memberType.getDatatypeBase()); 2705 2706 if (sep >= 0) 2707 /* 2708 * Additional compound nesting; create the nested compound type. 2709 */ 2710 tmpTID1 = memberType.createCompoundFieldType(memberName.substring(sep + 1)); 2711 else 2712 tmpTID1 = memberType.createNative(); 2713 2714 log.trace("createCompoundFieldType(): creating container compound datatype"); 2715 topTID = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, datatypeSize); 2716 2717 log.trace("createCompoundFieldType(): inserting member {} into compound datatype", 2718 insertedName); 2719 H5.H5Tinsert(topTID, insertedName, 0, tmpTID1); 2720 2721 /* 2722 * WARNING!!! This step is crucial. Without it, the compound type created might be larger 2723 * than the size of the single datatype field we are inserting. Performing a read with a 2724 * compound datatype of an incorrect size will corrupt JVM memory and cause strange 2725 * behavior and crashes. 2726 */ 2727 H5.H5Tpack(topTID); 2728 } 2729 else { 2730 log.debug( 2731 "createCompoundFieldType(): member name {} not found in compound datatype's member name list", 2732 memberName); 2733 } 2734 } 2735 } 2736 catch (Exception ex) { 2737 log.debug("createCompoundFieldType(): creation of compound field type failed: ", ex); 2738 topTID = HDF5Constants.H5I_INVALID_HID; 2739 } 2740 finally { 2741 close(tmpTID1); 2742 } 2743 2744 return topTID; 2745 } 2746 2747 private boolean datatypeIsComplex(long tid) 2748 { 2749 long tclass = HDF5Constants.H5T_NO_CLASS; 2750 2751 try { 2752 tclass = H5.H5Tget_class(tid); 2753 log.trace("datatypeIsComplex():{}", tclass); 2754 } 2755 catch (Exception ex) { 2756 log.debug("datatypeIsComplex():", ex); 2757 } 2758 2759 boolean retVal = (tclass == HDF5Constants.H5T_COMPOUND); 2760 retVal |= (tclass == HDF5Constants.H5T_ENUM); 2761 retVal |= (tclass == HDF5Constants.H5T_VLEN); 2762 retVal |= (tclass == HDF5Constants.H5T_ARRAY); 2763 2764 return retVal; 2765 } 2766 2767 private boolean datatypeIsReference(long tid) 2768 { 2769 long tclass = HDF5Constants.H5T_NO_CLASS; 2770 2771 try { 2772 tclass = H5.H5Tget_class(tid); 2773 log.trace("datatypeIsReference():{}", tclass); 2774 } 2775 catch (Exception ex) { 2776 log.debug("datatypeIsReference():", ex); 2777 } 2778 2779 return (tclass == HDF5Constants.H5T_REFERENCE); 2780 } 2781 2782 private boolean datatypeIsAtomic(long tid) 2783 { 2784 boolean retVal = !(datatypeIsComplex(tid) | datatypeIsReference(tid) | isRef()); 2785 retVal |= isOpaque(); 2786 retVal |= isBitField(); 2787 2788 return retVal; 2789 } 2790 2791 private boolean datatypeClassIsComplex(long tclass) 2792 { 2793 boolean retVal = (tclass == HDF5Constants.H5T_COMPOUND); 2794 retVal |= (tclass == HDF5Constants.H5T_ENUM); 2795 retVal |= (tclass == HDF5Constants.H5T_VLEN); 2796 retVal |= (tclass == HDF5Constants.H5T_ARRAY); 2797 2798 return retVal; 2799 } 2800 2801 private boolean datatypeClassIsReference(long tclass) { return (tclass == HDF5Constants.H5T_REFERENCE); } 2802 2803 private boolean datatypeClassIsOpaque(long tclass) { return (tclass == Datatype.CLASS_OPAQUE); } 2804 2805 private boolean datatypeClassIsAtomic(long tclass) 2806 { 2807 boolean retVal = !(datatypeClassIsComplex(tclass) | datatypeClassIsReference(tclass)); 2808 retVal |= (tclass == Datatype.CLASS_OPAQUE); 2809 retVal |= (tclass == Datatype.CLASS_BITFIELD); 2810 2811 return retVal; 2812 } 2813}