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 file COPYING. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * If you do not have access to this file, you may request a copy from * 011 * help@hdfgroup.org. * 012 ****************************************************************************/ 013 014package hdf.object.h5; 015 016import java.lang.reflect.Array; 017import java.util.List; 018import java.util.StringTokenizer; 019import java.util.Vector; 020 021import hdf.hdf5lib.H5; 022import hdf.hdf5lib.HDF5Constants; 023import hdf.hdf5lib.HDFNativeData; 024import hdf.hdf5lib.exceptions.HDF5Exception; 025import hdf.hdf5lib.exceptions.HDF5LibraryException; 026import hdf.hdf5lib.structs.H5O_info_t; 027import hdf.object.Attribute; 028import hdf.object.Datatype; 029import hdf.object.FileFormat; 030 031/** 032 * This class defines HDF5 datatype characteristics and APIs for a data type. 033 * <p> 034 * This class provides several methods to convert an HDF5 datatype identifier to a datatype object, and vice versa. A 035 * datatype object is described by four basic fields: datatype class, size, byte order, and sign, while an HDF5 datatype 036 * is presented by a datatype identifier. 037 * 038 * @version 1.1 9/4/2007 039 * @author Peter X. Cao 040 */ 041public class H5Datatype extends Datatype { 042 private static final long serialVersionUID = -750546422258749792L; 043 044 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H5Datatype.class); 045 046 /** 047 * The list of attributes of this data object. 048 */ 049 private List<Attribute> attributeList; 050 051 /** Flag to indicate if this datatype is a named datatype */ 052 private boolean isNamed = false; 053 054 private int nAttributes = -1; 055 056 private H5O_info_t obj_info; 057 058 private boolean isVLEN = false; 059 060 private String description = null; 061 062 /** 063 * Constructs an named HDF5 data type object for a given file, dataset name and group path. 064 * <p> 065 * The datatype object represents an existing named datatype in file. For example, new H5Datatype(file, "dtype1", 066 * "/g0") constructs a datatype object that corresponds to the dataset,"dset1", at group "/g0". 067 * 068 * @param theFile 069 * the file that contains the dataset. 070 * @param name 071 * the name of the dataset such as "dset1". 072 * @param path 073 * the group path to the dataset such as "/g0/". 074 */ 075 public H5Datatype(FileFormat theFile, String name, String path) { 076 this(theFile, name, path, null); 077 } 078 079 /** 080 * @deprecated Not for public use in the future. <br> 081 * Using {@link #H5Datatype(FileFormat, String, String)} 082 * 083 * @param theFile 084 * the file that contains the dataset. 085 * @param name 086 * the name of the dataset such as "dset1". 087 * @param path 088 * the group path to the dataset such as "/g0/". 089 * @param oid 090 * the oid of the dataset. 091 */ 092 @Deprecated 093 public H5Datatype(FileFormat theFile, String name, String path, long[] oid) { 094 super(theFile, name, path, oid); 095 obj_info = new H5O_info_t(-1L, -1L, 0, 0, -1L, 0L, 0L, 0L, 0L, null, null, null); 096 097 if ((oid == null) && (theFile != null)) { 098 // retrieve the object ID 099 try { 100 byte[] ref_buf = H5.H5Rcreate(theFile.getFID(), this.getFullName(), HDF5Constants.H5R_OBJECT, -1); 101 this.oid = new long[1]; 102 this.oid[0] = HDFNativeData.byteToLong(ref_buf, 0); 103 } 104 catch (Exception ex) { 105 log.debug("constructor ID {} for {} failed H5Rcreate", theFile.getFID(), this.getFullName()); 106 } 107 } 108 } 109 110 /** 111 * Constructs a Datatype with specified class, size, byte order and sign. 112 * <p> 113 * The following is a list of a few example of H5Datatype. 114 * <ol> 115 * <li>to create unsigned native integer<br> 116 * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE); 117 * <li>to create 16-bit signed integer with big endian<br> 118 * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE); 119 * <li>to create native float<br> 120 * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1); 121 * <li>to create 64-bit double<br> 122 * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1); 123 * </ol> 124 * 125 * @param tclass 126 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 127 * @param tsize 128 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 129 * @param torder 130 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and ORDER_NONE 131 * @param tsign 132 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN 133 */ 134 public H5Datatype(int tclass, int tsize, int torder, int tsign) { 135 super(tclass, tsize, torder, tsign); 136 } 137 138 /** 139 * Constructs a Datatype with specified class, size, byte order and sign. 140 * <p> 141 * The following is a list of a few example of H5Datatype. 142 * <ol> 143 * <li>to create unsigned native integer<br> 144 * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE); 145 * <li>to create 16-bit signed integer with big endian<br> 146 * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE); 147 * <li>to create native float<br> 148 * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1); 149 * <li>to create 64-bit double<br> 150 * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1); 151 * </ol> 152 * 153 * @param tclass 154 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 155 * @param tsize 156 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 157 * @param torder 158 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and ORDER_NONE 159 * @param tsign 160 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN 161 * @param tbase 162 * the base datatype of the new datatype 163 */ 164 public H5Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) { 165 super(tclass, tsize, torder, tsign, tbase); 166 } 167 168 /** 169 * Constructs a Datatype with a given native datatype identifier. 170 * <p> 171 * For example, if the datatype identifier is a 32-bit unsigned integer created from HDF5, 172 * 173 * <pre> 174 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 175 * Datatype dtype = new Datatype(tid); 176 * </pre> 177 * 178 * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 179 * 180 * @see #fromNative(int nativeID) 181 * 182 * @param nativeID 183 * the native datatype identifier. 184 */ 185 public H5Datatype(int nativeID) { 186 super(nativeID); 187 188 description = getDatatypeDescription(nativeID); 189 log.trace("H5Datatype(int nativeID) description={}", description); 190 fromNative(nativeID); 191 } 192 193 /* 194 * (non-Javadoc) 195 * 196 * @see hdf.object.DataFormat#hasAttribute() 197 */ 198 public boolean hasAttribute() { 199 obj_info.num_attrs = nAttributes; 200 201 if (obj_info.num_attrs < 0) { 202 int tid = -1; 203 try { 204 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 205 fromNative(tid); 206 obj_info = H5.H5Oget_info(tid); 207 isNamed = true; 208 } 209 catch (Exception ex) { 210 obj_info.num_attrs = 0; 211 } 212 finally { 213 try { 214 H5.H5Tclose(tid); 215 } 216 catch (Exception ex) { 217 log.debug("hasAttribute(): H5Tclose(tid {}) failure:", tid, ex); 218 } 219 } 220 } 221 222 log.trace("hasAttribute(): nAttributes={}", obj_info.num_attrs); 223 224 return (obj_info.num_attrs > 0); 225 } 226 227 /** 228 * Converts values in an Enumeration Datatype to names. 229 * <p> 230 * This method searches the identified enumeration datatype for the values appearing in <code>inValues</code> and 231 * returns the names corresponding to those values. If a given value is not found in the enumeration datatype, the 232 * name corresponding to that value will be set to <code>null</code> in the string array that is returned. 233 * <p> 234 * If the method fails in general, null will be returned instead of a String array. An empty <code>inValues</code> 235 * parameter, an <code>outNames</code> array with a different number of entries than the <code>inValues</code> 236 * array, or an invalid <code>tid</code> would all cause general failure. 237 * 238 * @param tid 239 * The identifier of the enumeration datatype. 240 * @param inValues 241 * The array of enumerations values to be converted. 242 * @param outNames 243 * The array of names to be populated. If null, the array will be created. If <code>outNames</code> is 244 * not null, the number of entries must be the same as the number of values in <code>inValues</code>. 245 * 246 * @return The string array of names if successful; otherwise return null. 247 * 248 * @throws HDF5Exception 249 * If there is an error at the HDF5 library level. 250 * 251 */ 252 public static final String[] convertEnumValueToName(int tid, Object inValues, String[] outNames) 253 throws HDF5Exception { 254 log.trace("convertEnumValueToName start"); 255 int inSize = 0; 256 257 String cName = inValues.getClass().getName(); 258 boolean isArray = cName.lastIndexOf("[") >= 0; 259 if (isArray) { 260 inSize = Array.getLength(inValues); 261 } 262 else { 263 inSize = 1; 264 } 265 266 if ((inValues == null) || (inSize <= 0) 267 || ((outNames != null) && (inSize != Array.getLength(outNames)))) { 268 log.debug("convertEnumValueToName() failure: in/out values null or inSize not equal to outNames length"); 269 log.debug("convertEnumValueToName(): inValues={} inSize={} outNames length={}", inValues, inSize, outNames.length); 270 log.trace("convertEnumValueToName(): finish"); 271 return null; 272 } 273 274 int nMembers = H5.H5Tget_nmembers(tid); 275 if (nMembers <= 0) { 276 log.debug("convertEnumValueToName(): no members"); 277 log.trace("convertEnumValueToName(): finish"); 278 return null; 279 } 280 281 log.trace("convertEnumValueToName(): inSize={} nMembers={}", inSize, nMembers); 282 if (outNames == null) { 283 outNames = new String[inSize]; 284 } 285 else { 286 // set values in existing array to null in case no match found 287 for (int i = 0; i < inSize; i++) { 288 outNames[i] = null; 289 } 290 } 291 292 String[] names = new String[nMembers]; 293 int[] values = new int[nMembers]; 294 int[] theValue = { 0 }; 295 296 // Loop through the enumeration datatype and extract the names and 297 // values. 298 for (int i = 0; i < nMembers; i++) { 299 names[i] = H5.H5Tget_member_name(tid, i); 300 H5.H5Tget_member_value(tid, i, theValue); 301 values[i] = theValue[0]; 302 log.trace("convertEnumValueToName(): extract member[{}] names[i]={} values[i]={}", i, names[i], values[i]); 303 } 304 305 int val = -1; 306 307 // Look for matches 308 for (int i = 0; i < inSize; i++) { 309 if (isArray) { 310 val = (Integer) Array.get(inValues, i); 311 } 312 else { 313 val = (Integer) inValues; 314 } 315 boolean notfound = true; 316 for (int j = 0; j < nMembers; j++) { 317 if (val == values[j]) { 318 outNames[i] = names[j]; 319 notfound = false; 320 break; 321 } 322 } 323 if(notfound) { 324 log.debug("convertEnumValueToName(): default name"); 325 outNames[i] = "**ENUM ERR "+String.valueOf(val)+"**"; 326 } 327 } 328 329 log.trace("convertEnumValueToName(): finish"); 330 return outNames; 331 } 332 333 /** 334 * Converts names in an Enumeration Datatype to values. 335 * <p> 336 * This method searches the identified enumeration datatype for the names appearing in <code>inValues</code> and 337 * returns the values corresponding to those names. 338 * 339 * @param tid 340 * The identifier of the enumeration datatype. 341 * @param in 342 * The array of enumerations names to be converted. 343 * @param out 344 * The array of values to be populated. 345 * 346 * @return The int array of values if successful; otherwise return null. 347 * 348 * @throws HDF5Exception 349 * If there is an error at the HDF5 library level. 350 * 351 */ 352 public static final int[] convertEnumNameToValue(int tid, String[] in, int[] out) throws HDF5Exception { 353 log.trace("convertEnumNameToValue start"); 354 int size = 0; 355 356 if ((in == null) || ((size = Array.getLength(in)) <= 0) || ((out != null) && (size != Array.getLength(out)))) { 357 log.debug("convertEnumNameToValue() failure: in/out values null or in size not equal to out size"); 358 log.debug("convertEnumNameToValue(): in={} inSize={} out={} outSize={}", in.toString(), in.length, out.toString(), out.length); 359 log.trace("convertEnumValueToName(): finish"); 360 return null; 361 } 362 363 int nMembers = H5.H5Tget_nmembers(tid); 364 if (nMembers <= 0) { 365 log.debug("convertEnumNameToValue(): no members"); 366 log.trace("convertEnumNameToValue(): finish"); 367 return null; 368 } 369 370 if (out == null) { 371 out = new int[size]; 372 } 373 else { 374 // set values in existing array to -1 in case no match found 375 for (int i = 0; i < size; i++) { 376 out[i] = -1; 377 } 378 } 379 380 String[] names = new String[nMembers]; 381 int[] values = new int[nMembers]; 382 int[] theValue = { 0 }; 383 384 // Loop through the enumeration datatype and extract the names and 385 // values. 386 for (int i = 0; i < nMembers; i++) { 387 names[i] = H5.H5Tget_member_name(tid, i); 388 H5.H5Tget_member_value(tid, i, theValue); 389 values[i] = theValue[0]; 390 } 391 392 for (int i = 0; i < size; i++) { 393 if (in[i] == null || in[i].length() <= 0) 394 continue; 395 396 for (int j = 0; j < nMembers; j++) { 397 if (in[i].equalsIgnoreCase(names[j])) { 398 out[i] = values[j]; 399 break; 400 } 401 } 402 } 403 404 log.trace("convertEnumNameToValue(): finish"); 405 return out; 406 } 407 408 /* 409 * (non-Javadoc) 410 * 411 * @see hdf.object.Datatype#fromNative(int) 412 */ 413 @Override 414 public void fromNative(int tid) { 415 log.trace("fromNative(): start: tid={}", tid); 416 int tclass = -1; 417 int tsize = -1; 418 int torder = -1; 419 boolean isChar = false, isUchar = false; 420 421 if (tid < 0) { 422 datatypeClass = CLASS_NO_CLASS; 423 } 424 else { 425 try { 426 tclass = H5.H5Tget_class(tid); 427 tsize = H5.H5Tget_size(tid); 428 torder = H5.H5Tget_order(tid); 429 isVLEN = (tclass == HDF5Constants.H5T_VLEN) || H5.H5Tis_variable_str(tid); 430 log.trace("fromNative(): tclass={}, tsize={}, torder={}, isVLEN={}", tclass, tsize, torder, isVLEN); 431 } 432 catch (Exception ex) { 433 log.debug("fromNative(): failure: ", ex); 434 datatypeClass = CLASS_NO_CLASS; 435 } 436 437 if (torder == HDF5Constants.H5T_ORDER_BE) 438 datatypeOrder = ORDER_BE; 439 else 440 datatypeOrder = ORDER_LE; 441 442 try { 443 isUchar = H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_UCHAR); 444 isChar = (H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_CHAR) || isUchar); 445 } 446 catch (Exception ex) { 447 log.debug("fromNative(): native char type failure: ", ex); 448 } 449 450 if (tclass == HDF5Constants.H5T_ARRAY) { 451 int tmptid = -1; 452 datatypeClass = CLASS_ARRAY; 453 try { 454 int ndims = H5.H5Tget_array_ndims(tid); 455 dims = new long[ndims]; 456 H5.H5Tget_array_dims(tid, dims); 457 tmptid = H5.H5Tget_super(tid); 458 baseType = new H5Datatype(tmptid); 459 isVLEN = (baseType.getDatatypeClass() == HDF5Constants.H5T_VLEN) || H5.H5Tis_variable_str(tmptid); 460 log.trace("fromNative:baseType={} tclass={}, isVLEN={}", tmptid, tclass, isVLEN); 461 } 462 catch (Exception ex) { 463 log.debug("fromNative(): array type failure: ", ex); 464 } 465 finally { 466 try { 467 H5.H5Tclose(tmptid); 468 } 469 catch (Exception ex) { 470 log.debug("fromNative(): array H5Tclose(tmptid {}) failure: ", tmptid, ex); 471 } 472 } 473 } 474 else if (tclass == HDF5Constants.H5T_COMPOUND) { 475 datatypeClass = CLASS_COMPOUND; 476 477 try { 478 int nMembers = H5.H5Tget_nmembers(tid); 479 compoundMemberNames = new Vector<String>(nMembers); 480 compoundMemberTypes = new Vector<Datatype>(nMembers); 481 compoundMemberOffsets = new Vector<Long>(nMembers); 482 compoundMemberFieldIDs = new Vector<Integer>(nMembers); 483 484 for (int i = 0; i < nMembers; i++) { 485 String memberName = H5.H5Tget_member_name(tid, i); 486 long memberOffset = H5.H5Tget_member_offset(tid, i); 487 int memberID = -1; 488 H5Datatype t = null; 489 try { 490 memberID = H5.H5Tget_member_type(tid, i); 491 t = new H5Datatype(memberID); 492 } 493 catch (Exception ex1) { 494 log.debug("fromNative(): compound type failure: ", ex1); 495 } 496 finally { 497 try { 498 H5.H5Tclose(memberID); 499 } 500 catch (Exception ex2) { 501 log.debug("fromNative(): compound H5Tclose(memberID {}) failure: ", memberID, ex2); 502 } 503 } 504 505 compoundMemberNames.add(i, memberName); 506 compoundMemberOffsets.add(i, memberOffset); 507 compoundMemberFieldIDs.add(i, memberID); 508 compoundMemberTypes.add(i, t); 509 } 510 } 511 catch (HDF5LibraryException ex) { 512 log.debug("fromNative(): compound type failure: ", ex); 513 } 514 } 515 else if (isChar) { 516 datatypeClass = CLASS_CHAR; 517 if (isUchar) 518 datatypeSign = SIGN_NONE; 519 else 520 datatypeSign = SIGN_2; 521 } 522 else if (tclass == HDF5Constants.H5T_INTEGER) { 523 datatypeClass = CLASS_INTEGER; 524 try { 525 int tsign = H5.H5Tget_sign(tid); 526 if (tsign == HDF5Constants.H5T_SGN_NONE) { 527 datatypeSign = SIGN_NONE; 528 } 529 else 530 datatypeSign = SIGN_2; 531 532 } 533 catch (Exception ex) { 534 log.debug("fromNative(): int type failure: ", ex); 535 } 536 } 537 else if (tclass == HDF5Constants.H5T_FLOAT) { 538 datatypeClass = CLASS_FLOAT; 539 } 540 else if (tclass == HDF5Constants.H5T_STRING) { 541 try { 542 isVLEN = H5.H5Tis_variable_str(tid); 543 } 544 catch (Exception ex) { 545 log.debug("fromNative(): var str type failure: ", ex); 546 } 547 548 datatypeClass = CLASS_STRING; 549 } 550 else if (tclass == HDF5Constants.H5T_REFERENCE) { 551 datatypeClass = CLASS_REFERENCE; 552 } 553 else if (tclass == HDF5Constants.H5T_ENUM) { 554 datatypeClass = CLASS_ENUM; 555 try { 556 int nMember = H5.H5Tget_nmembers(tid); 557 String name = null; 558 byte[] val = new byte[tsize]; 559 String enumStr = ""; 560 for (int i = 0; i < nMember; i++) { 561 name = H5.H5Tget_member_name(tid, i); 562 H5.H5Tget_member_value(tid, i, val); 563 enumStr += name + "="; 564 switch (H5.H5Tget_size(tid)) { 565 case 1: 566 enumStr += (HDFNativeData.byteToByte(val[0]))[0]; 567 break; 568 case 2: 569 enumStr += (HDFNativeData.byteToShort(val))[0]; 570 break; 571 case 4: 572 enumStr += (HDFNativeData.byteToInt(val))[0]; 573 break; 574 case 8: 575 enumStr += (HDFNativeData.byteToLong(val))[0]; 576 break; 577 default: 578 enumStr += "?"; 579 break; 580 } 581 if(i < nMember-1) 582 enumStr += ","; 583 } 584 enumMembers = enumStr; 585 } 586 catch (Exception ex) { 587 log.debug("fromNative(): enum type failure: ", ex); 588 } 589 } 590 else if (tclass == HDF5Constants.H5T_VLEN) { 591 int tmptid = -1; 592 datatypeClass = CLASS_VLEN; 593 try { 594 tmptid = H5.H5Tget_super(tid); 595 baseType = new H5Datatype(tmptid); 596 } 597 catch (Exception ex) { 598 } 599 finally { 600 try { 601 H5.H5Tclose(tmptid); 602 } 603 catch (Exception ex) { 604 log.debug("fromNative(): vlen H5Tclose(tmptid {}) failure: ", tmptid, ex); 605 } 606 } 607 } 608 else if (tclass == HDF5Constants.H5T_BITFIELD) { 609 datatypeClass = CLASS_BITFIELD; 610 } 611 else if (tclass == HDF5Constants.H5T_OPAQUE) { 612 datatypeClass = CLASS_OPAQUE; 613 } 614 else { 615 log.debug("fromNative(): datatypeClass is unknown"); 616 } 617 618 if (isVLEN) 619 datatypeSize = -1; 620 else 621 datatypeSize = tsize; 622 } 623 log.trace("fromNative(): datatypeClass={} baseType={} datatypeSize={}", datatypeClass, baseType, datatypeSize); 624 log.trace("fromNative(): finish"); 625 } 626 627 /** 628 * @deprecated Not for public use in the future.<br> 629 * Using {@link hdf.hdf5lib.H5#H5Tget_native_type(int)} 630 * <p> 631 * Return the HDF5 memory datatype identifier based on the HDF5 datatype identifier on disk 632 * <p> 633 * @param tid 634 * the datatype identification disk. 635 * 636 * @return the memory datatype identifier if successful, and negative otherwise. 637 */ 638 @Deprecated 639 public static int toNative(int tid) { 640 // data type information 641 int native_type = -1; 642 643 try { 644 native_type = H5.H5Tget_native_type(tid); 645 } 646 catch (Exception ex) { 647 log.debug("toNative(): H5Tget_native_type(tid {}) failure: ", tid, ex); 648 } 649 650 try { 651 if (H5.H5Tis_variable_str(tid)) 652 H5.H5Tset_size(native_type, HDF5Constants.H5T_VARIABLE); 653 } 654 catch (Exception ex) { 655 log.debug("toNative(): var str type size failure: ", ex); 656 } 657 658 return native_type; 659 } 660 661 /* 662 * (non-Javadoc) 663 * 664 * @see hdf.object.Datatype#toNative() 665 */ 666 @Override 667 public int toNative() { 668 log.trace("toNative(): start"); 669 670 int tid = -1; 671 int tmptid = -1; 672 673 if (isNamed) { 674 try { 675 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 676 } 677 catch (Exception ex) { 678 log.debug("toNative(): name {} H5Topen failure: ", getPath() + getName(), ex); 679 } 680 } 681 682 if (tid >= 0) { 683 log.trace("toNative(): tid >= 0"); 684 log.trace("toNative(): finish"); 685 return tid; 686 } 687 688 // figure the datatype 689 try { 690 log.trace("toNative(): datatypeClass={} baseType={} datatypeSize={}", datatypeClass, baseType, datatypeSize); 691 switch (datatypeClass) { 692 case CLASS_ARRAY: 693 if (baseType != null) { 694 if ((tmptid = baseType.toNative()) >= 0) { 695 try { 696 tid = H5.H5Tarray_create(tmptid, dims.length, dims); 697 } 698 finally { 699 close(tmptid); 700 } 701 } 702 } 703 else { 704 log.debug("toNative(): CLASS_ARRAY base type is NULL"); 705 } 706 break; 707 case CLASS_COMPOUND: 708 try { 709 tid = H5.H5Tcreate(CLASS_COMPOUND, datatypeSize); 710 711 for (int i = 0; i < compoundMemberNames.size(); i++) { 712 String memberName = compoundMemberNames.get(i); 713 long memberOffset = compoundMemberOffsets.get(i); 714 int memberID = compoundMemberFieldIDs.get(i); 715 716 H5.H5Tinsert(tid, memberName, memberOffset, memberID); 717 } 718 } 719 catch (Exception ex) { 720 log.trace("toNative(): failure: ", ex); 721 } 722 break; 723 case CLASS_INTEGER: 724 case CLASS_ENUM: 725 if (datatypeSize == 1) { 726 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT8"); 727 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 728 } 729 else if (datatypeSize == 2) { 730 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT16"); 731 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16); 732 } 733 else if (datatypeSize == 4) { 734 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT32"); 735 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 736 } 737 else if (datatypeSize == 8) { 738 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 739 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64); 740 } 741 else { 742 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT"); 743 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT); 744 } 745 746 if (datatypeOrder == Datatype.ORDER_BE) { 747 log.trace("toNative(): CLASS_INT-ENUM is H5T_ORDER_BE"); 748 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 749 } 750 else if (datatypeOrder == Datatype.ORDER_LE) { 751 log.trace("toNative(): CLASS_INT-ENUM is H5T_ORDER_LE"); 752 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 753 } 754 755 if (datatypeSign == Datatype.SIGN_NONE) { 756 log.trace("toNative(): CLASS_INT-ENUM is H5T_SGN_NONE"); 757 H5.H5Tset_sign(tid, HDF5Constants.H5T_SGN_NONE); 758 } 759 break; 760 case CLASS_FLOAT: 761 if (datatypeSize == 8) { 762 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_DOUBLE); 763 } 764 else { 765 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_FLOAT); 766 } 767 768 if (datatypeOrder == Datatype.ORDER_BE) { 769 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 770 } 771 else if (datatypeOrder == Datatype.ORDER_LE) { 772 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 773 } 774 break; 775 case CLASS_CHAR: 776 if (datatypeSign == Datatype.SIGN_NONE) { 777 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UCHAR); 778 } 779 else { 780 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_CHAR); 781 } 782 break; 783 case CLASS_STRING: 784 tid = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 785 if (isVLEN || datatypeSize < 0) 786 H5.H5Tset_size(tid, HDF5Constants.H5T_VARIABLE); 787 else 788 H5.H5Tset_size(tid, datatypeSize); 789 790 log.trace("toNative(): isVlenStr={}", isVLEN); 791 // H5.H5Tset_strpad(tid, HDF5Constants.H5T_STR_NULLPAD); 792 break; 793 case CLASS_REFERENCE: 794 if (datatypeSize > H5.H5Tget_size(HDF5Constants.H5T_STD_REF_OBJ)) { 795 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_DSETREG); 796 } 797 else { 798 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_OBJ); 799 } 800 break; 801 case CLASS_VLEN: 802 if (baseType != null) { 803 if ((tmptid = baseType.toNative()) >= 0) { 804 try { 805 tid = H5.H5Tvlen_create(tmptid); 806 } 807 finally { 808 close(tmptid); 809 } 810 } 811 } 812 else { 813 log.debug("toNative(): CLASS_VLEN base type is NULL"); 814 } 815 break; 816 case CLASS_BITFIELD: 817 case CLASS_OPAQUE: 818 if (datatypeSize == 1) { 819 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT8"); 820 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 821 } 822 else if (datatypeSize == 2) { 823 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT16"); 824 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16); 825 } 826 else if (datatypeSize == 4) { 827 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT32"); 828 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 829 } 830 else if (datatypeSize == 8) { 831 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT64"); 832 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64); 833 } 834 else { 835 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT"); 836 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT); 837 } 838 839 if (datatypeOrder == Datatype.ORDER_BE) { 840 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_ORDER_BE"); 841 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 842 } 843 else if (datatypeOrder == Datatype.ORDER_LE) { 844 log.trace("toNative(): CLASS_BITFIELD-OPAQUE is H5T_ORDER_LE"); 845 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 846 } 847 break; 848 default: 849 log.debug("toNative(): Unknown class"); 850 break; 851 } // switch (tclass) 852 } 853 catch (Exception ex) { 854 log.debug("toNative(): Error figuring the datatype: ", ex); 855 tid = -1; 856 } 857 858 // set up enum members 859 if (datatypeClass == CLASS_ENUM) { 860 int ptid = tid; 861 try { 862 tid = H5.H5Tenum_create(ptid); 863 datatypeSize = H5.H5Tget_size(tid); 864 } 865 catch (Exception ex) { 866 log.debug("toNative(): create members failure: ", ex); 867 tid = -1; 868 } 869 870 try { 871 String memstr, memname; 872 int idx; 873 byte[] memval = null; 874 if (datatypeSize == 1) { 875 memval = HDFNativeData.byteToByte(new Byte((byte) 0)); 876 } 877 else if (datatypeSize == 2) { 878 memval = HDFNativeData.shortToByte(new Short((short) 0)); 879 } 880 else if (datatypeSize == 4) { 881 memval = HDFNativeData.intToByte(new Integer((int) 0)); 882 } 883 else if (datatypeSize == 8) { 884 memval = HDFNativeData.longToByte(new Long((long) 0)); 885 } 886 StringTokenizer token; 887 888 // using "0" and "1" as default 889 if (enumMembers == null) { 890 token = new StringTokenizer("0,1", ","); 891 log.trace("toNative(): default string"); 892 } 893 else { 894 token = new StringTokenizer(enumMembers, ","); 895 log.trace("toNative(): string {}", enumMembers); 896 } 897 898 while (token.hasMoreTokens()) { 899 memstr = token.nextToken(); 900 901 if (memstr != null) { 902 memstr = memstr.trim(); 903 } 904 905 if ((memstr == null) || (memstr.length() < 1)) { 906 continue; 907 } 908 909 idx = memstr.indexOf('='); 910 if (idx > 0) { 911 memname = memstr.substring(0, idx); 912 if (datatypeSize == 1) { 913 log.trace("toNative(): ENUM is H5T_NATIVE_INT8"); 914 Byte tval = Byte.parseByte(memstr.substring(idx + 1)); 915 memval = HDFNativeData.byteToByte(tval); 916 } 917 else if (datatypeSize == 2) { 918 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT16"); 919 Short tval = Short.parseShort(memstr.substring(idx + 1)); 920 memval = HDFNativeData.shortToByte(tval); 921 } 922 else if (datatypeSize == 4) { 923 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT32"); 924 Integer tval = Integer.parseInt(memstr.substring(idx + 1)); 925 memval = HDFNativeData.intToByte(tval); 926 } 927 else if (datatypeSize == 8) { 928 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 929 Long tval = Long.parseLong(memstr.substring(idx + 1)); 930 memval = HDFNativeData.longToByte(tval); 931 } 932 else { 933 log.debug("toNative(): enum datatypeSize incorrect"); 934 } 935 } 936 else { 937 memname = memstr; 938 if (datatypeSize == 1) { 939 log.trace("toNative(): ENUM is H5T_NATIVE_INT8"); 940 Byte tval = new Byte(memval[0]); 941 tval++; 942 memval = HDFNativeData.byteToByte(tval); 943 } 944 else if (datatypeSize == 2) { 945 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT16"); 946 Short tval = (HDFNativeData.byteToShort(memval))[0]; 947 tval++; 948 memval = HDFNativeData.shortToByte(tval); 949 } 950 else if (datatypeSize == 4) { 951 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT32"); 952 Integer tval = (HDFNativeData.byteToInt(memval))[0]; 953 tval++; 954 memval = HDFNativeData.intToByte(tval); 955 } 956 else if (datatypeSize == 8) { 957 log.trace("toNative(): CLASS_INT-ENUM is H5T_NATIVE_INT64"); 958 Long tval = (HDFNativeData.byteToLong(memval))[0]; 959 tval++; 960 memval = HDFNativeData.longToByte(tval); 961 } 962 else { 963 log.debug("toNative(): enum datatypeSize incorrect"); 964 } 965 } 966 log.trace("toNative(): H5Tenum_insert {} {}", memname, memval); 967 H5.H5Tenum_insert(tid, memname, memval); 968 } 969 } 970 catch (Exception ex) { 971 log.debug("toNative(): set up enum members failure: ", ex); 972 } 973 974 try { 975 H5.H5Tclose(ptid); 976 } 977 catch (Exception ex) { 978 log.debug("toNative(): H5Tclose(ptid {}) failure: ", ptid, ex); 979 } 980 } // if (datatypeClass == CLASS_ENUM) { 981 982 return tid; 983 } 984 985 /** 986 * Allocates a one-dimensional array of byte, short, int, long, float, double, or String to store data in memory. 987 * 988 * For example, 989 * 990 * <pre> 991 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 992 * int[] data = (int[]) allocateArray(tid, 100); 993 * </pre> 994 * 995 * returns a 32-bit integer array of size 100. 996 * 997 * @param tid 998 * the datatype id. 999 * @param size 1000 * the total number of data points of the array. 1001 * 1002 * @return the array object if successful; otherwise, return null. 1003 * 1004 * @throws OutOfMemoryError 1005 * If there is a failure. 1006 */ 1007 public static Object allocateArray(int tid, int size) throws OutOfMemoryError { 1008 log.trace("allocateArray(): start: tid={} size={}", tid, size); 1009 Object data = null; 1010 boolean isVL = false; 1011 boolean is_variable_str = false; 1012 boolean is_reg_ref = false; 1013 1014 if (size < 0) { 1015 log.debug("allocateArray(): size < 0"); 1016 log.trace("allocateArray(): finish"); 1017 return null; 1018 } 1019 1020 // Scalar members have dimensionality zero, i.e. size =0 1021 // what can we do about it, set the size to 1 1022 if (size == 0) { 1023 size = 1; 1024 } 1025 1026 // data type information 1027 int tclass = -1; 1028 int tsize = -1; 1029 1030 try { 1031 tclass = H5.H5Tget_class(tid); 1032 tsize = H5.H5Tget_size(tid); 1033 log.trace("allocateArray(): tclass={} : tsize={}", tclass, tsize); 1034 } 1035 catch (Exception ex) { 1036 log.debug("allocateArray(): H5Tget_xxxx data type information failure: ", ex); 1037 } 1038 1039 try { 1040 is_variable_str = H5.H5Tis_variable_str(tid); 1041 } 1042 catch (Exception ex) { 1043 log.debug("allocateArray(): H5Tis_variable_str(tid {}) failure: ", tid, ex); 1044 } 1045 isVL = (tclass == HDF5Constants.H5T_VLEN); 1046 1047 try { 1048 is_reg_ref = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 1049 } 1050 catch (Exception ex) { 1051 log.debug("allocateArray(): H5Tequal(tid {}, HDF5Constants.H5T_STD_REF_DSETREG) failure: ", tid, ex); 1052 } 1053 1054 if (is_variable_str || isVL || is_reg_ref) { 1055 log.trace("allocateArray(): is_variable_str={} || isVL={} || is_reg_ref={}", is_variable_str, isVL, is_reg_ref); 1056 data = new String[size]; 1057 for (int i = 0; i < size; i++) { 1058 ((String[]) data)[i] = ""; 1059 } 1060 } 1061 else if (tclass == HDF5Constants.H5T_INTEGER) { 1062 log.trace("allocateArray(): class.H5T_INTEGER={}", tclass); 1063 if (tsize == 1) { 1064 data = new byte[size]; 1065 } 1066 else if (tsize == 2) { 1067 data = new short[size]; 1068 } 1069 else if (tsize == 4) { 1070 data = new int[size]; 1071 } 1072 else if (tsize == 8) { 1073 data = new long[size]; 1074 } 1075 } 1076 else if (tclass == HDF5Constants.H5T_ENUM) { 1077 log.trace("allocateArray(): class.H5T_ENUM={}", tclass); 1078 int superTid = -1; 1079 try { 1080 superTid = H5.H5Tget_super(tid); 1081 data = allocateArray(superTid, size); 1082 } 1083 catch (Exception ex) { 1084 log.debug("allocateArray(): H5T_ENUM class enum data type information failure: ", ex); 1085 } 1086 finally { 1087 try { 1088 H5.H5Tclose(superTid); 1089 } 1090 catch (Exception ex) { 1091 log.debug("allocateArray(): H5T_ENUM H5Tclose(superTid {}) failure: ", superTid, ex); 1092 } 1093 } 1094 } 1095 else if (tclass == HDF5Constants.H5T_COMPOUND) { 1096 log.trace("allocateArray(): class.H5T_COMPOUND={}", tclass); 1097 return new byte[size]; 1098 } 1099 else if (tclass == HDF5Constants.H5T_FLOAT) { 1100 log.trace("allocateArray(): class.H5T_FLOAT={}", tclass); 1101 if (tsize == 4) { 1102 data = new float[size]; 1103 } 1104 else if (tsize == 8) { 1105 data = new double[size]; 1106 } 1107 } 1108 else if ((tclass == HDF5Constants.H5T_STRING) || (tclass == HDF5Constants.H5T_REFERENCE)) { 1109 log.trace("allocateArray(): class.H5T_STRING || H5T_REFERENCE={}", tclass); 1110 data = new byte[size * tsize]; 1111 } 1112 else if (tclass == HDF5Constants.H5T_ARRAY) { 1113 // use the base datatype to define the array 1114 int superTid = -1; 1115 try { 1116 int mn = H5.H5Tget_array_ndims(tid); 1117 long[] marray = new long[mn]; 1118 H5.H5Tget_array_dims(tid, marray); 1119 int asize = 1; 1120 for (int j = 0; j < mn; j++) { 1121 asize *= marray[j]; 1122 } 1123 log.trace("allocateArray(): class.H5T_ARRAY={} : members={} : asize={}", tclass, mn, asize); 1124 1125 superTid = H5.H5Tget_super(tid); 1126 data = allocateArray(superTid, size * asize); 1127 } 1128 catch (Exception ex) { 1129 log.debug("allocateArray(): H5T_ARRAY class failure: ", ex); 1130 } 1131 finally { 1132 try { 1133 H5.H5Tclose(superTid); 1134 } 1135 catch (Exception ex) { 1136 log.debug("allocateArray(): H5T_ARRAY H5Tclose(superTid {}) failure: ", superTid, ex); 1137 } 1138 } 1139 } 1140 else if ((tclass == HDF5Constants.H5T_OPAQUE) || (tclass == HDF5Constants.H5T_BITFIELD)) { 1141 log.trace("allocateArray(): class.H5T_OPAQUE || H5T_BITFIELD={}", tclass); 1142 data = new byte[size * tsize]; 1143 } 1144 else { 1145 log.debug("allocateArray(): class.????={}", tclass); 1146 data = null; 1147 } 1148 1149 return data; 1150 } 1151 1152 /** 1153 * Returns the size (in bytes) of a given datatype identifier. 1154 * <p> 1155 * It basically just calls H5Tget_size(tid). 1156 * 1157 * @param tid 1158 * The datatype identifier. 1159 * 1160 * @return The size of the datatype in bytes. 1161 * 1162 * @see hdf.hdf5lib.H5#H5Tget_size(int) 1163 */ 1164 public static final int getDatatypeSize(int tid) { 1165 // data type information 1166 int tsize = -1; 1167 1168 try { 1169 tsize = H5.H5Tget_size(tid); 1170 } 1171 catch (Exception ex) { 1172 tsize = -1; 1173 } 1174 1175 return tsize; 1176 } 1177 1178 /* 1179 * (non-Javadoc) 1180 * 1181 * @see hdf.object.Datatype#getDatatypeDescription() 1182 */ 1183 @Override 1184 public String getDatatypeDescription() { 1185 if (description == null) { 1186 int tid = toNative(); 1187 if (tid >= 0) { 1188 description = getDatatypeDescription(tid); 1189 close(tid); 1190 } 1191 else { 1192 description = "Unknown"; 1193 } 1194 } 1195 1196 return description; 1197 } 1198 1199 /** 1200 * Returns a short description of a given datatype ID. 1201 * 1202 * @param tid 1203 * the HDF5 datatype identifier 1204 * 1205 * @return a string describing the data type. 1206 */ 1207 public static final String getDatatypeDescription(int tid) { 1208 log.trace("getDatatypeDescription(): start"); 1209 String description = "Unknown"; 1210 1211 // data type information 1212 int tclass = -1; 1213 int tsize = -1; 1214 int tsign = -1; 1215 1216 try { 1217 tclass = H5.H5Tget_class(tid); 1218 tsize = H5.H5Tget_size(tid); 1219 } 1220 catch (Exception ex) { 1221 log.debug("getDatatypeDescription(): Unknown: ", ex); 1222 } 1223 1224 if (tclass == HDF5Constants.H5T_INTEGER) { 1225 log.trace("getDatatypeDescription(): class H5T_INTEGER"); 1226 try { 1227 tsign = H5.H5Tget_sign(tid); 1228 } 1229 catch (Exception ex) { 1230 log.debug("getDatatypeDescription(): H5Tget_sign(tid {}) failure:", tid, ex); 1231 } 1232 if (tsize == 1) { 1233 try { 1234 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1235 description = "8-bit unsigned integer"; 1236 } 1237 else { 1238 description = "8-bit integer"; 1239 } 1240 } 1241 catch (Exception ex) { 1242 description = "Unknown"; 1243 } 1244 } 1245 else if (tsize == 2) { 1246 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1247 description = "16-bit unsigned integer"; 1248 } 1249 else { 1250 description = "16-bit integer"; 1251 } 1252 } 1253 else if (tsize == 4) { 1254 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1255 description = "32-bit unsigned integer"; 1256 } 1257 else { 1258 description = "32-bit integer"; 1259 } 1260 } 1261 else if (tsize == 8) { 1262 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1263 description = "64-bit unsigned integer"; 1264 } 1265 else { 1266 description = "64-bit integer"; 1267 } 1268 } 1269 } 1270 else if (tclass == HDF5Constants.H5T_FLOAT) { 1271 log.trace("getDatatypeDescription(): class H5T_FLOAT"); 1272 if (tsize == 4) { 1273 description = "32-bit floating-point"; 1274 } 1275 else if (tsize == 8) { 1276 description = "64-bit floating-point"; 1277 } 1278 } 1279 else if (tclass == HDF5Constants.H5T_STRING) { 1280 log.trace("getDatatypeDescription(): class H5T_STRING"); 1281 try { 1282 if (H5.H5Tis_variable_str(tid)) { 1283 description = "String, length = variable"; 1284 } 1285 else { 1286 description = "String, length = " + H5.H5Tget_size(tid); 1287 } 1288 } 1289 catch (Exception ex) { 1290 description = "String"; 1291 } 1292 } 1293 else if (tclass == HDF5Constants.H5T_REFERENCE) { 1294 log.trace("getDatatypeDescription(): class H5T_REFERENCE"); 1295 boolean is_reg_ref = false; 1296 try { 1297 is_reg_ref = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 1298 } 1299 catch (Exception ex) { 1300 log.debug("getDatatypeDescription(): H5T_STD_REF_DSETREG: ", ex); 1301 } 1302 1303 if (is_reg_ref) { 1304 description = "Dataset region reference"; 1305 } 1306 else { 1307 description = "Object reference"; 1308 } 1309 } 1310 else if (tclass == HDF5Constants.H5T_BITFIELD) { 1311 log.trace("getDatatypeDescription(): class H5T_BITFIELD"); 1312 description = "Bitfield"; 1313 } 1314 else if (tclass == HDF5Constants.H5T_ENUM) { 1315 log.trace("getDatatypeDescription(): class H5T_ENUM"); 1316 byte[] evalue = new byte[tsize]; 1317 String enames = " ( "; 1318 try { 1319 int n = H5.H5Tget_nmembers(tid); 1320 for (int i = 0; i < n; i++) { 1321 H5.H5Tget_member_value(tid, i, evalue); 1322 enames += H5.H5Tget_member_name(tid, i); 1323 enames += "="; 1324 if (tsize == 1) { 1325 description = "8-bit enum"; 1326 enames += (HDFNativeData.byteToByte(evalue[0]))[0]; 1327 } 1328 else if (tsize == 2) { 1329 description = "16-bit enum"; 1330 enames += (HDFNativeData.byteToShort(evalue))[0]; 1331 } 1332 else if (tsize == 4) { 1333 description = "32-bit enum"; 1334 enames += (HDFNativeData.byteToInt(evalue))[0]; 1335 } 1336 else if (tsize == 8) { 1337 description = "64-bit enum"; 1338 enames += (HDFNativeData.byteToLong(evalue))[0]; 1339 } 1340 if(i < n-1) 1341 enames += " "; 1342 } 1343 enames += ")"; 1344 description += enames; 1345 } 1346 catch (Exception ex) { 1347 log.debug("getDatatypeDescription(): H5T_ENUM: ", ex); 1348 } 1349 } 1350 else if (tclass == HDF5Constants.H5T_ARRAY) { 1351 log.trace("getDatatypeDescription(): class H5T_ARRAY"); 1352 description = "Array of "; 1353 // use the base datatype to define the array 1354 int tmptid = -1; 1355 try { 1356 tmptid = H5.H5Tget_super(tid); 1357 description += getDatatypeDescription(tmptid); 1358 int ndims = H5.H5Tget_array_ndims(tid); 1359 long adims[] = new long[ndims]; 1360 try { 1361 H5.H5Tget_array_dims(tid, adims); 1362 } 1363 catch (Exception ex) { 1364 log.debug("getDatatypeDescription(): H5T_ARRAY dims: ", ex); 1365 } 1366 1367 description += " (" + adims[0]; 1368 for (int j = 1; j < ndims; j++) 1369 description += "x" + adims[j]; 1370 description += ")"; 1371 } 1372 catch (Exception ex) { 1373 log.debug("getDatatypeDescription(): H5T_ARRAY: ", ex); 1374 } 1375 finally { 1376 try { 1377 H5.H5Tclose(tmptid); 1378 } 1379 catch (Exception ex) { 1380 log.debug("getDatatypeDescription(): H5T_ARRAY H5Tclose(tmptid {}) failure: ", tmptid, ex); 1381 } 1382 } 1383 } 1384 else if (tclass == HDF5Constants.H5T_COMPOUND) { 1385 log.trace("getDatatypeDescription(): class H5T_COMPOUND"); 1386 description = "Compound "; 1387 try { 1388 description += "{"; 1389 int n = H5.H5Tget_nmembers(tid); 1390 int mtid = -1; 1391 1392 for (int i = 0; i < n; i++) { 1393 mtid = H5.H5Tget_member_type(tid, i); 1394 description += getDatatypeDescription(mtid) + ", "; 1395 try { 1396 H5.H5Tclose(mtid); 1397 } 1398 catch (Exception ex2) { 1399 log.debug("getDatatypeDescription(): H5T_COMPOUND H5Tclose(mtid {}) failure: ", mtid, ex2); 1400 } 1401 mtid = -1; 1402 } 1403 description += "}"; 1404 } 1405 catch (Exception ex) { 1406 log.debug("getDatatypeDescription(): H5T_COMPOUND: ", ex); 1407 } 1408 } 1409 else if (tclass == HDF5Constants.H5T_VLEN) { 1410 log.trace("getDatatypeDescription(): class H5T_VLEN"); 1411 int tmptid = -1; 1412 try { 1413 tmptid = H5.H5Tget_super(tid); 1414 description = "Variable-length of " + getDatatypeDescription(tmptid); 1415 } 1416 catch (Exception ex) { 1417 description = "Variable-length"; 1418 } 1419 finally { 1420 try { 1421 H5.H5Tclose(tmptid); 1422 } 1423 catch (Exception ex) { 1424 log.debug("getDatatypeDescription(): H5T_VLEN H5Tclose(tmptid {}) failure: ", tmptid, ex); 1425 } 1426 } 1427 } 1428 else if (tclass == HDF5Constants.H5T_OPAQUE) { 1429 log.trace("getDatatypeDescription(): class H5T_OPAQUE"); 1430 description = "Opaque"; 1431 } 1432 else { 1433 description = "Unknown"; 1434 } 1435 1436 log.trace("getDatatypeDescription(): finish"); 1437 return description; 1438 } 1439 1440 /* 1441 * (non-Javadoc) 1442 * 1443 * @see hdf.object.Datatype#isUnsigned() 1444 */ 1445 @Override 1446 public boolean isUnsigned() { 1447 boolean unsigned = false; 1448 int tid = -1; 1449 1450 if (datatypeClass == Datatype.CLASS_COMPOUND) return false; 1451 1452 tid = toNative(); 1453 1454 if (tid >= 0) { 1455 unsigned = isUnsigned(tid); 1456 try { 1457 H5.H5Tclose(tid); 1458 } 1459 catch (final Exception ex) { 1460 } 1461 } 1462 1463 return unsigned; 1464 } 1465 1466 /** 1467 * Checks if a datatype specified by the identifier is an unsigned integer. 1468 * 1469 * @param tid 1470 * the datatype ID to be checked. 1471 * 1472 * @return true is the datatype is an unsigned integer; otherwise returns false. 1473 */ 1474 public static final boolean isUnsigned(int tid) { 1475 boolean unsigned = false; 1476 1477 if (tid >= 0) { 1478 try { 1479 int tclass = H5.H5Tget_class(tid); 1480 log.trace("isUnsigned(): tclass = {}", tclass); 1481 if (tclass != HDF5Constants.H5T_FLOAT && tclass != HDF5Constants.H5T_STRING 1482 && tclass != HDF5Constants.H5T_REFERENCE && tclass != HDF5Constants.H5T_BITFIELD 1483 && tclass != HDF5Constants.H5T_OPAQUE 1484 && tclass != HDF5Constants.H5T_COMPOUND) { 1485 int tsign = H5.H5Tget_sign(tid); 1486 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1487 unsigned = true; 1488 } 1489 else { 1490 log.trace("isUnsigned(): not unsigned"); 1491 } 1492 } 1493 else { 1494 log.trace("isUnsigned(): tclass not integer type"); 1495 } 1496 } 1497 catch (Exception ex) { 1498 log.debug("isUnsigned(): {} Datatype {} failure", getDatatypeDescription(tid), tid, ex); 1499 unsigned = false; 1500 } 1501 } 1502 else { 1503 log.trace("isUnsigned(): not a valid datatype"); 1504 } 1505 1506 return unsigned; 1507 } 1508 1509 /** 1510 * Checks if a datatype is variable-length. 1511 * 1512 * @return if the datatype is variable-length. 1513 */ 1514 public boolean isVLEN() { 1515 return isVLEN; 1516 } 1517 1518 /** 1519 * Opens access to a named datatype. 1520 * <p> 1521 * It calls H5.H5Topen(loc, name). 1522 * 1523 * @return the datatype identifier if successful; otherwise returns negative value. 1524 * 1525 * @see hdf.hdf5lib.H5#H5Topen(int, String) 1526 */ 1527 @Override 1528 public int open() { 1529 log.trace("open(): start"); 1530 int tid = -1; 1531 1532 try { 1533 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 1534 } 1535 catch (HDF5Exception ex) { 1536 tid = -1; 1537 } 1538 1539 log.trace("open(): finish"); 1540 return tid; 1541 } 1542 1543 /** 1544 * Closes a datatype identifier. 1545 * <p> 1546 * It calls H5.H5close(tid). 1547 * 1548 * @param tid 1549 * the datatype ID to close 1550 */ 1551 @Override 1552 public void close(int tid) { 1553 try { 1554 H5.H5Tclose(tid); 1555 } 1556 catch (HDF5Exception ex) { 1557 log.debug("close(): H5Tclose(tid {}) failure: ", tid, ex); 1558 } 1559 } 1560 1561 /* 1562 * (non-Javadoc) 1563 * 1564 * @see hdf.object.Datatype#getMetadata() 1565 */ 1566 @Override 1567 public List<Attribute> getMetadata() throws HDF5Exception { 1568 return this.getMetadata(fileFormat.getIndexType(null), fileFormat.getIndexOrder(null)); 1569 } 1570 1571 /* 1572 * (non-Javadoc) 1573 * 1574 * @see hdf.object.DataFormat#getMetadata(int...) 1575 */ 1576 public List<Attribute> getMetadata(int... attrPropList) throws HDF5Exception { 1577 log.trace("getMetadata(): start"); 1578 // load attributes first 1579 if (attributeList == null) { 1580 int tid = open(); 1581 int indxType = fileFormat.getIndexType(null); 1582 int order = fileFormat.getIndexOrder(null); 1583 1584 if (attrPropList.length > 0) { 1585 indxType = attrPropList[0]; 1586 if (attrPropList.length > 1) { 1587 order = attrPropList[1]; 1588 } 1589 } 1590 1591 try { 1592 attributeList = H5File.getAttribute(tid, indxType, order); 1593 } 1594 catch (Exception ex) { 1595 log.debug("getMetadata(): H5File.getAttribute failure: ", ex); 1596 } 1597 finally { 1598 close(tid); 1599 } 1600 } // if (attributeList == null) 1601 1602 try { 1603 this.linkTargetObjName = H5File.getLinkTargetName(this); 1604 } 1605 catch (Exception ex) { 1606 log.debug("getMetadata(): H5File.linkTargetObjName failure: ", ex); 1607 } 1608 1609 log.trace("getMetadata(): finish"); 1610 return attributeList; 1611 } 1612 1613 /* 1614 * (non-Javadoc) 1615 * 1616 * @see hdf.object.Datatype#writeMetadata(java.lang.Object) 1617 */ 1618 @Override 1619 public void writeMetadata(Object info) throws Exception { 1620 log.trace("writeMetadata(): start"); 1621 1622 // only attribute metadata is supported. 1623 if (!(info instanceof Attribute)) { 1624 log.debug("writeMetadata(): Object not an Attribute"); 1625 log.trace("writeMetadata(): finish"); 1626 return; 1627 } 1628 1629 boolean attrExisted = false; 1630 Attribute attr = (Attribute) info; 1631 1632 if (attributeList == null) { 1633 this.getMetadata(); 1634 } 1635 1636 if (attributeList != null) 1637 attrExisted = attributeList.contains(attr); 1638 1639 getFileFormat().writeAttribute(this, attr, attrExisted); 1640 1641 // add the new attribute into attribute list 1642 if (!attrExisted) { 1643 attributeList.add(attr); 1644 nAttributes = attributeList.size(); 1645 } 1646 log.trace("writeMetadata(): finish"); 1647 } 1648 1649 /* 1650 * (non-Javadoc) 1651 * 1652 * @see hdf.object.Datatype#removeMetadata(java.lang.Object) 1653 */ 1654 @Override 1655 public void removeMetadata(Object info) throws HDF5Exception { 1656 log.trace("removeMetadata(): start"); 1657 1658 // only attribute metadata is supported. 1659 if (!(info instanceof Attribute)) { 1660 log.debug("removeMetadata(): Object not an attribute"); 1661 log.trace("removeMetadata(): finish"); 1662 return; 1663 } 1664 1665 Attribute attr = (Attribute) info; 1666 int tid = open(); 1667 try { 1668 H5.H5Adelete(tid, attr.getName()); 1669 List<Attribute> attrList = getMetadata(); 1670 attrList.remove(attr); 1671 nAttributes = attributeList.size(); 1672 } 1673 catch (Exception ex) { 1674 log.debug("removeMetadata(): ", ex); 1675 } 1676 finally { 1677 close(tid); 1678 } 1679 log.trace("removeMetadata(): finish"); 1680 } 1681 1682 public void setName(String newName) throws Exception { 1683 H5File.renameObject(this, newName); 1684 super.setName(newName); 1685 } 1686}