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