001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object; 016 017import java.util.ArrayList; 018import java.util.HashMap; 019import java.util.Iterator; 020import java.util.List; 021import java.util.Map; 022import java.util.Map.Entry; 023 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027/** 028 * Datatype is an abstract class that defines datatype characteristics and APIs for a data type. 029 * 030 * A datatype has four basic characteristics: class, size, byte order and sign. These characteristics are 031 * defined in the See <a 032 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 033 * Datatypes in HDF5 User Guide</a> 034 * 035 * These characteristics apply to all the sub-classes. The sub-classes may have different ways to describe a 036 * datatype. We here define the <strong> native datatype</strong> to the datatype used by the sub-class. For 037 * example, H5Datatype uses a datatype identifier (hid_t) to specify a datatype. NC2Datatype uses 038 * ucar.nc2.DataType object to describe its datatype. "Native" here is different from the "native" definition 039 * in the HDF5 library. 040 * 041 * Two functions, createNative() and fromNative(), are defined to convert the general characteristics to/from 042 * the native datatype. Sub-classes must implement these functions so that the conversion will be done 043 * correctly. The values of the CLASS member are not identical to HDF5 values for a datatype class. 044 * 045 * @version 1.1 9/4/2007 046 * @author Peter X. Cao 047 */ 048public abstract class Datatype extends HObject implements MetaDataContainer { 049 private static final long serialVersionUID = -581324710549963177L; 050 051 private static final Logger log = LoggerFactory.getLogger(Datatype.class); 052 053 /** 054 * The default definition for datatype size, order, and sign. 055 */ 056 public static final int NATIVE = -1; 057 058 /** 059 * See <a 060 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 061 * Datatypes in HDF5 User Guide</a> 062 */ 063 public static final int CLASS_NO_CLASS = -1; 064 065 /** 066 * See <a 067 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 068 * Datatypes in HDF5 User Guide</a> 069 */ 070 public static final int CLASS_INTEGER = 0; 071 072 /** 073 * See <a 074 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 075 * Datatypes in HDF5 User Guide</a> 076 */ 077 public static final int CLASS_FLOAT = 1; 078 079 /** 080 * See <a 081 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 082 * Datatypes in HDF5 User Guide</a> 083 */ 084 public static final int CLASS_CHAR = 2; 085 086 /** 087 * See <a 088 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 089 * Datatypes in HDF5 User Guide</a> 090 */ 091 public static final int CLASS_STRING = 3; 092 093 /** 094 * See <a 095 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 096 * Datatypes in HDF5 User Guide</a> 097 */ 098 public static final int CLASS_BITFIELD = 4; 099 100 /** 101 * See <a 102 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 103 * Datatypes in HDF5 User Guide</a> 104 */ 105 public static final int CLASS_OPAQUE = 5; 106 107 /** 108 * See <a 109 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 110 * Datatypes in HDF5 User Guide</a> 111 */ 112 public static final int CLASS_COMPOUND = 6; 113 114 /** 115 * See <a 116 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 117 * Datatypes in HDF5 User Guide</a> 118 */ 119 public static final int CLASS_REFERENCE = 7; 120 121 /** 122 * See <a 123 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 124 * Datatypes in HDF5 User Guide</a> 125 */ 126 public static final int CLASS_ENUM = 8; 127 128 /** 129 * See <a 130 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 131 * Datatypes in HDF5 User Guide</a> 132 */ 133 public static final int CLASS_VLEN = 9; 134 135 /** 136 * See <a 137 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 138 * Datatypes in HDF5 User Guide</a> 139 */ 140 public static final int CLASS_ARRAY = 10; 141 142 /** 143 * See <a 144 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 145 * Datatypes in HDF5 User Guide</a> 146 */ 147 public static final int CLASS_TIME = 11; 148 149 /** 150 * See <a 151 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 152 * Datatypes in HDF5 User Guide</a> 153 */ 154 public static final int ORDER_LE = 0; 155 156 /** 157 * See <a 158 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 159 * Datatypes in HDF5 User Guide</a> 160 */ 161 public static final int ORDER_BE = 1; 162 163 /** 164 * See <a 165 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 166 * Datatypes in HDF5 User Guide</a> 167 */ 168 public static final int ORDER_VAX = 2; 169 170 /** 171 * See <a 172 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 173 * Datatypes in HDF5 User Guide</a> 174 */ 175 public static final int ORDER_NONE = 3; 176 177 /** 178 * See <a 179 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 180 * Datatypes in HDF5 User Guide</a> 181 */ 182 public static final int SIGN_NONE = 0; 183 184 /** 185 * See <a 186 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 187 * Datatypes in HDF5 User Guide</a> 188 */ 189 public static final int SIGN_2 = 1; 190 191 /** 192 * See <a 193 * href="https://support.hdfgroup.org/releases/hdf5/v1_14/v1_14_5/documentation/doxygen/_h5_t__u_g.html#sec_datatype">HDF5 194 * Datatypes in HDF5 User Guide</a> 195 */ 196 public static final int NSGN = 2; 197 198 /** 199 * The description of the datatype. 200 */ 201 protected String datatypeDescription = null; 202 203 /** 204 * The description of the datatype. 205 */ 206 protected boolean datatypeNATIVE = false; 207 208 /** 209 * The class of the datatype. 210 */ 211 protected int datatypeClass; 212 213 /** 214 * The size (in bytes) of the datatype. 215 */ 216 protected long datatypeSize; 217 218 /** 219 * The byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, and 220 * ORDER_VAX. 221 */ 222 protected int datatypeOrder; 223 224 /** 225 * The sign of the datatype. 226 */ 227 protected int datatypeSign; 228 229 /** 230 * The base datatype of this datatype (null if this datatype is atomic). 231 */ 232 protected Datatype baseType; 233 234 /** 235 * Determines whether this datatype is a named datatype 236 */ 237 protected boolean isNamed = false; 238 239 /** 240 * The dimensions of the ARRAY element of an ARRAY datatype. 241 */ 242 protected long[] arrayDims; 243 244 /** 245 * Determines whether this datatype is a variable-length type. 246 */ 247 protected boolean isVLEN = false; 248 249 /** 250 * Determines whether this datatype is a variable-length string type. 251 */ 252 protected boolean isVariableStr = false; 253 254 /** 255 * The (name, value) pairs of enum members. 256 */ 257 protected Map<String, String> enumMembers; 258 259 /** 260 * The list of names of members of a compound Datatype. 261 */ 262 protected List<String> compoundMemberNames; 263 264 /** 265 * The list of types of members of a compound Datatype. 266 */ 267 protected List<Datatype> compoundMemberTypes; 268 269 /** 270 * The list of offsets of members of a compound Datatype. 271 */ 272 protected List<Long> compoundMemberOffsets; 273 274 /** 275 * Constructs a named datatype with a given file, name and path. 276 * 277 * @param theFile 278 * the HDF file. 279 * @param typeName 280 * the name of the datatype, e.g "12-bit Integer". 281 * @param typePath 282 * the full group path of the datatype, e.g. "/datatypes/". 283 */ 284 public Datatype(FileFormat theFile, String typeName, String typePath) 285 { 286 this(theFile, typeName, typePath, null); 287 } 288 289 /** 290 * @deprecated Not for public use in the future.<br> 291 * Using {@link #Datatype(FileFormat, String, String)} 292 * 293 * @param theFile 294 * the HDF file. 295 * @param typeName 296 * the name of the datatype, e.g "12-bit Integer". 297 * @param typePath 298 * the full group path of the datatype, e.g. "/datatypes/". 299 * @param oid 300 * the oidof the datatype. 301 */ 302 @Deprecated 303 public Datatype(FileFormat theFile, String typeName, String typePath, long[] oid) 304 { 305 super(theFile, typeName, typePath, oid); 306 } 307 308 /** 309 * Constructs a Datatype with specified class, size, byte order and sign. 310 * 311 * The following is a list of a few examples of Datatype. 312 * <ol> 313 * <li>to create unsigned native integer<br> 314 * Datatype type = new Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, 315 * Datatype.SIGN_NONE); <li>to create 16-bit signed integer with big endian<br> Datatype type = new 316 * Dataype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> 317 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); 318 * <li>to create 64-bit double<br> 319 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 320 * </ol> 321 * 322 * @param tclass 323 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 324 * @param tsize 325 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 326 * Valid values are NATIVE or a positive value. 327 * @param torder 328 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 329 * ORDER_NONE and NATIVE. 330 * @param tsign 331 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 332 * 333 * @throws Exception 334 * if there is an error 335 */ 336 public Datatype(int tclass, int tsize, int torder, int tsign) throws Exception 337 { 338 this(tclass, tsize, torder, tsign, null); 339 } 340 341 /** 342 * Constructs a Datatype with specified class, size, byte order and sign. 343 * 344 * The following is a list of a few examples of Datatype. 345 * <ol> 346 * <li>to create unsigned native integer<br> 347 * Datatype type = new Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, 348 * Datatype.SIGN_NONE); <li>to create 16-bit signed integer with big endian<br> Datatype type = new 349 * Dataype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> 350 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); 351 * <li>to create 64-bit double<br> 352 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 353 * </ol> 354 * 355 * @param tclass 356 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and 357 * etc. 358 * @param tsize 359 * the size of the datatype in bytes, e.g. for a 32-bit integer, 360 * the size is 4. 361 * Valid values are NATIVE or a positive value. 362 * @param torder 363 * the byte order of the datatype. Valid values are ORDER_LE, 364 * ORDER_BE, ORDER_VAX, ORDER_NONE and NATIVE. 365 * @param tsign 366 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 367 * @param tbase 368 * the base datatype of the new datatype 369 * 370 * @throws Exception 371 * if there is an error 372 */ 373 public Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) throws Exception 374 { 375 this(null, tclass, tsize, torder, tsign, tbase, null); 376 } 377 378 /** 379 * Constructs a Datatype with specified class, size, byte order and sign. 380 * 381 * The following is a list of a few examples of Datatype. 382 * <ol> 383 * <li>to create unsigned native integer<br> 384 * Datatype type = new Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, 385 * Datatype.SIGN_NONE); <li>to create 16-bit signed integer with big endian<br> Datatype type = new 386 * Dataype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> 387 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); 388 * <li>to create 64-bit double<br> 389 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 390 * </ol> 391 * 392 * @param theFile 393 * the HDF file. 394 * @param tclass 395 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 396 * @param tsize 397 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 398 * Valid values are NATIVE or a positive value. 399 * @param torder 400 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 401 * ORDER_NONE and NATIVE. 402 * @param tsign 403 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 404 * @param tbase 405 * the base datatype of the new datatype 406 * @param pbase 407 * the parent datatype of the new datatype 408 * 409 * @throws Exception 410 * if there is an error 411 */ 412 public Datatype(FileFormat theFile, int tclass, int tsize, int torder, int tsign, Datatype tbase, 413 Datatype pbase) throws Exception 414 { 415 super(theFile, null, null, null); 416 if ((tsize == 0) || (tsize < 0 && tsize != Datatype.NATIVE)) 417 throw new Exception("invalid datatype size - " + tsize); 418 if ((torder != Datatype.ORDER_LE) && (torder != Datatype.ORDER_BE) && 419 (torder != Datatype.ORDER_VAX) && (torder != Datatype.ORDER_NONE) && (torder != Datatype.NATIVE)) 420 throw new Exception("invalid datatype order - " + torder); 421 if ((tsign != Datatype.SIGN_NONE) && (tsign != Datatype.SIGN_2) && (tsign != Datatype.NATIVE)) 422 throw new Exception("invalid datatype sign - " + tsign); 423 424 datatypeClass = tclass; 425 datatypeSize = tsize; 426 if (datatypeSize == NATIVE) 427 datatypeNATIVE = true; 428 else 429 datatypeNATIVE = false; 430 datatypeOrder = torder; 431 datatypeSign = tsign; 432 enumMembers = null; 433 baseType = tbase; 434 arrayDims = null; 435 isVariableStr = (datatypeClass == Datatype.CLASS_STRING) && (tsize < 0); 436 isVLEN = (datatypeClass == Datatype.CLASS_VLEN) || isVariableStr; 437 438 compoundMemberNames = new ArrayList<>(); 439 compoundMemberTypes = new ArrayList<>(); 440 compoundMemberOffsets = new ArrayList<>(); 441 442 log.trace("datatypeClass={} datatypeSize={} datatypeOrder={} datatypeSign={} baseType={}", 443 datatypeClass, datatypeSize, datatypeOrder, datatypeSign, baseType); 444 } 445 446 /** 447 * Constructs a Datatype with specified class, size, byte order and sign. 448 * 449 * The following is a list of a few examples of Datatype. 450 * <ol> 451 * <li>to create unsigned native integer<br> 452 * Datatype type = new Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, 453 * Datatype.SIGN_NONE); <li>to create 16-bit signed integer with big endian<br> Datatype type = new 454 * Dataype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE); <li>to create native float<br> 455 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); 456 * <li>to create 64-bit double<br> 457 * Datatype type = new Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 458 * </ol> 459 * 460 * @param tclass 461 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 462 * @param tsize 463 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 464 * Valid values are NATIVE or a positive value. 465 * @param torder 466 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 467 * ORDER_NONE and NATIVE. 468 * @param tsign 469 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 470 * @param tbase 471 * the base datatype of the new datatype 472 * @param pbase 473 * the parent datatype of the new datatype 474 * 475 * @throws Exception 476 * if there is an error 477 */ 478 public Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase, Datatype pbase) 479 throws Exception 480 { 481 this(null, tclass, tsize, torder, tsign, tbase, pbase); 482 } 483 484 /** 485 * Constructs a Datatype with a given native datatype identifier. 486 * 487 * For example, if the datatype identifier is a 32-bit unsigned integer created from HDF5, 488 * 489 * <pre> 490 * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 491 * Datatype dtype = new Datatype(tid); 492 * </pre> 493 * 494 * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 495 * 496 * @see #fromNative(long tid) 497 * @param theFile 498 * the HDF file. 499 * @param tid 500 * the native datatype identifier. 501 * 502 * @throws Exception 503 * if there is an error 504 */ 505 public Datatype(FileFormat theFile, long tid) throws Exception { this(theFile, tid, null); } 506 507 /** 508 * Constructs a Datatype with a given native datatype identifier. 509 * 510 * For example, if the datatype identifier is a 32-bit unsigned integer created from HDF5, 511 * 512 * <pre> 513 * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 514 * Datatype dtype = new Datatype(tid); 515 * </pre> 516 * 517 * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 518 * 519 * @see #fromNative(long tid) 520 * @param theFile 521 * the HDF file. 522 * @param tid 523 * the native datatype identifier. 524 * @param pbase 525 * the parent datatype of the new datatype 526 * 527 * @throws Exception 528 * if there is an error 529 */ 530 public Datatype(FileFormat theFile, long tid, Datatype pbase) throws Exception 531 { 532 this(theFile, CLASS_NO_CLASS, NATIVE, NATIVE, NATIVE, null, pbase); 533 } 534 535 /** 536 * Opens access to this named datatype. Sub-classes must replace this default implementation. For 537 * example, in H5Datatype, open() function H5.H5Topen(loc_id, name) to get the datatype identifier. 538 * 539 * @return the datatype identifier if successful; otherwise returns negative value. 540 */ 541 @Override 542 public long open() 543 { 544 return -1; 545 } 546 547 /** 548 * Closes a datatype identifier. 549 * 550 * Sub-classes must replace this default implementation. 551 * 552 * @param id 553 * the datatype identifier to close. 554 */ 555 @Override 556 public abstract void close(long id); 557 558 /** 559 * Returns the class of the datatype. Valid values are: 560 * <ul> 561 * <li>CLASS_NO_CLASS 562 * <li>CLASS_INTEGER 563 * <li>CLASS_FLOAT 564 * <li>CLASS_CHAR 565 * <li>CLASS_STRING 566 * <li>CLASS_BITFIELD 567 * <li>CLASS_OPAQUE 568 * <li>CLASS_COMPOUND 569 * <li>CLASS_REFERENCE 570 * <li>CLASS_ENUM 571 * <li>CLASS_VLEN 572 * <li>CLASS_ARRAY 573 * </ul> 574 * 575 * @return the class of the datatype. 576 */ 577 public int getDatatypeClass() { return datatypeClass; } 578 579 /** 580 * Returns the size of the datatype in bytes. For example, for a 32-bit 581 * integer, the size is 4 (bytes). 582 * 583 * @return the size of the datatype. 584 */ 585 public long getDatatypeSize() { return datatypeSize; } 586 587 /** 588 * Returns the byte order of the datatype. Valid values are 589 * <ul> 590 * <li>ORDER_LE 591 * <li>ORDER_BE 592 * <li>ORDER_VAX 593 * <li>ORDER_NONE 594 * </ul> 595 * 596 * @return the byte order of the datatype. 597 */ 598 public int getDatatypeOrder() { return datatypeOrder; } 599 600 /** 601 * Returns the sign (SIGN_NONE, SIGN_2) of an integer datatype. 602 * 603 * @return the sign of the datatype. 604 */ 605 public int getDatatypeSign() { return datatypeSign; } 606 607 /** 608 * Returns the base datatype for this datatype. 609 * 610 * For example, in a dataset of type ARRAY of integer, the datatype of the dataset is ARRAY. The 611 * datatype of the base type is integer. 612 * 613 * @return the datatype of the contained basetype. 614 */ 615 public Datatype getDatatypeBase() { return baseType; } 616 617 /** 618 * Sets the (key, value) pairs of enum members for enum datatype. 619 * 620 * For Example, 621 * <dl> 622 * <dt>setEnumMembers("-40=lowTemp, 90=highTemp")</dt> 623 * <dd>sets the key of enum member lowTemp to -40 and highTemp to 90.</dd> 624 * <dt>setEnumMembers("lowTemp, highTemp")</dt> 625 * <dd>sets enum members to defaults, i.e. 0=lowTemp and 1=highTemp</dd> 626 * <dt>setEnumMembers("10=lowTemp, highTemp")</dt> 627 * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd> 628 * </dl> 629 * 630 * @param enumStr 631 * the (key, value) pairs of enum members 632 */ 633 public final void setEnumMembers(String enumStr) 634 { 635 log.trace("setEnumMembers: start enum_members={}", enumStr); 636 if (enumStr != null) { 637 enumMembers = new HashMap<>(); 638 String[] entries = enumStr.split(","); 639 for (String entry : entries) { 640 String[] keyValue = entry.split("="); 641 enumMembers.put(keyValue[0].trim(), keyValue[1].trim()); 642 if (log.isTraceEnabled()) 643 log.trace("setEnumMembers: value={} name={}", keyValue[0].trim(), keyValue[1].trim()); 644 } 645 } 646 datatypeDescription = null; // reset description 647 log.trace("setEnumMembers: finish enum size={}", enumMembers.size()); 648 } 649 650 /** 651 * Returns the Map<String,String> pairs of enum members for enum datatype. 652 * 653 * @return enumStr Map<String,String%gt; pairs of enum members 654 */ 655 public final Map<String, String> getEnumMembers() 656 { 657 if (enumMembers == null) { 658 log.trace("getEnumMembers: null"); 659 enumMembers = new HashMap<>(); 660 } 661 662 return enumMembers; 663 } 664 665 /** 666 * Returns the HashMap pairs of enum members for enum datatype. 667 * 668 * For Example, 669 * <dl> 670 * <dt>getEnumMembersAsString()</dt> 671 * <dd>returns "10=lowTemp, 40=highTemp"</dd> 672 * </dl> 673 * 674 * @return enumStr the (key, value) pairs of enum members 675 */ 676 @SuppressWarnings("rawtypes") 677 public final String getEnumMembersAsString() 678 { 679 StringBuilder enumStr = new StringBuilder(); 680 if (getEnumMembers() != null) { 681 Iterator<Entry<String, String>> entries = enumMembers.entrySet().iterator(); 682 int i = enumMembers.size(); 683 log.trace("getEnumMembersAsString: enum size={}", i); 684 while (entries.hasNext()) { 685 Entry thisEntry = entries.next(); 686 enumStr.append((String)thisEntry.getKey()).append("=").append((String)thisEntry.getValue()); 687 688 i--; 689 if (i > 0) 690 enumStr.append(", "); 691 } 692 } 693 log.trace("getEnumMembersAsString: finish {}", enumStr); 694 return enumStr.toString(); 695 } 696 697 /** 698 * Returns the dimensions of an Array Datatype. 699 * 700 * @return dims the dimensions of the Array Datatype 701 */ 702 public final long[] getArrayDims() { return arrayDims; } 703 704 /** 705 * Returns the member names of a Compound Datatype. 706 * 707 * @return member names of a Compound Datatype 708 */ 709 public final List<String> getCompoundMemberNames() { return compoundMemberNames; } 710 711 /** 712 * Returns member types of a Compound Datatype. 713 * 714 * @return member types of a Compound Datatype 715 */ 716 public final List<Datatype> getCompoundMemberTypes() { return compoundMemberTypes; } 717 718 /** 719 * Returns the member offsets of a Compound Datatype. 720 * 721 * @return member offsets of a Compound Datatype 722 */ 723 public final List<Long> getCompoundMemberOffsets() { return compoundMemberOffsets; } 724 725 /** 726 * Converts the datatype object to a native datatype. 727 * 728 * Subclasses must implement it so that this datatype will be converted accordingly. Use close() to 729 * close the native identifier; otherwise, the datatype will be left open. 730 * 731 * For example, a HDF5 datatype created from<br> 732 * 733 * <pre> 734 * H5Dataype dtype = new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 735 * int tid = dtype.createNative(); 736 * </pre> 737 * 738 * The "tid" will be the HDF5 datatype id of a 64-bit unsigned integer, which is equivalent to 739 * 740 * <pre> 741 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 742 * </pre> 743 * 744 * @return the identifier of the native datatype. 745 */ 746 public abstract long createNative(); 747 748 /** 749 * Set datatype characteristics (class, size, byte order and sign) from a given datatype identifier. 750 * 751 * Sub-classes must implement it so that this datatype will be converted accordingly. 752 * 753 * For example, if the type identifier is a 64-bit unsigned integer created from HDF5, 754 * 755 * <pre> 756 * H5Datatype dtype = new H5Datatype(); 757 * dtype.fromNative(HDF5Constants.H5T_NATIVE_UNINT32); 758 * </pre> 759 * 760 * Where dtype is equivalent to <br> 761 * new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 762 * 763 * @param nativeID 764 * the datatype identifier. 765 */ 766 public abstract void fromNative(long nativeID); 767 768 /** 769 * If the datatype is a reference, then return the type. 770 * 771 * @return the datatype reference type if successful; otherwise returns negative value. 772 */ 773 public long getReferenceType() { return -1; } 774 775 /** 776 * Returns a short text description of this datatype. 777 * 778 * @return a short text description of this datatype 779 */ 780 public String getDescription() 781 { 782 if (datatypeDescription != null) 783 return datatypeDescription; 784 785 StringBuilder description = new StringBuilder(); 786 787 switch (datatypeClass) { 788 case CLASS_CHAR: 789 description.append("8-bit ").append((isUnsigned() ? "unsigned " : "")).append("integer"); 790 break; 791 case CLASS_INTEGER: 792 log.trace("getDescription(): Int [{}]", datatypeNATIVE); 793 if (datatypeNATIVE) 794 description.append("native ").append((isUnsigned() ? "unsigned " : "")).append("integer"); 795 else 796 description.append(String.valueOf(datatypeSize * 8)) 797 .append("-bit ") 798 .append((isUnsigned() ? "unsigned " : "")) 799 .append("integer"); 800 break; 801 case CLASS_FLOAT: 802 if (datatypeNATIVE) 803 description.append("native floating-point"); 804 else 805 description.append(String.valueOf(datatypeSize * 8)).append("-bit floating-point"); 806 break; 807 case CLASS_STRING: 808 description.append("String"); 809 break; 810 case CLASS_REFERENCE: 811 description.append("Object reference"); 812 break; 813 case CLASS_OPAQUE: 814 if (datatypeNATIVE) 815 description.append("native opaque"); 816 else 817 description.append(String.valueOf(datatypeSize * 8)).append("-bit opaque"); 818 break; 819 case CLASS_BITFIELD: 820 if (datatypeNATIVE) 821 description.append("native bitfield"); 822 else 823 description.append(String.valueOf(datatypeSize * 8)).append("-bit bitfield"); 824 break; 825 case CLASS_ENUM: 826 if (datatypeNATIVE) 827 description.append("native enum"); 828 else 829 description.append(String.valueOf(datatypeSize * 8)).append("-bit enum"); 830 break; 831 case CLASS_ARRAY: 832 description.append("Array"); 833 834 if (arrayDims != null) { 835 description.append(" ["); 836 for (int i = 0; i < arrayDims.length; i++) { 837 description.append(arrayDims[i]); 838 if (i < arrayDims.length - 1) 839 description.append(" x "); 840 } 841 description.append("]"); 842 } 843 844 break; 845 case CLASS_COMPOUND: 846 description.append("Compound"); 847 break; 848 case CLASS_VLEN: 849 description.append("Variable-length"); 850 break; 851 default: 852 description.append("Unknown"); 853 break; 854 } 855 856 if (baseType != null) 857 description.append(" of " + baseType.getDescription()); 858 859 return description.toString(); 860 } 861 862 /** 863 * Checks if this datatype is unsigned. 864 * 865 * @return true if the datatype is unsigned; 866 * otherwise, returns false. 867 */ 868 public boolean isUnsigned() 869 { 870 if (baseType != null) 871 return baseType.isUnsigned(); 872 else { 873 if (isCompound()) { 874 if ((compoundMemberTypes != null) && !compoundMemberTypes.isEmpty()) { 875 boolean allMembersUnsigned = true; 876 877 Iterator<Datatype> cmpdTypeListIT = compoundMemberTypes.iterator(); 878 while (cmpdTypeListIT.hasNext()) { 879 Datatype next = cmpdTypeListIT.next(); 880 881 allMembersUnsigned = allMembersUnsigned && next.isUnsigned(); 882 } 883 884 return allMembersUnsigned; 885 } 886 else { 887 log.debug("isUnsigned(): compoundMemberTypes is null"); 888 return false; 889 } 890 } 891 else { 892 return (datatypeSign == Datatype.SIGN_NONE); 893 } 894 } 895 } 896 897 /** 898 * Checks if this datatype is a boolean type. 899 * 900 * @return true if the datatype is boolean; false otherwise 901 */ 902 public abstract boolean isText(); 903 904 /** 905 * Checks if this datatype is an integer type. 906 * 907 * @return true if the datatype is integer; false otherwise 908 */ 909 public boolean isInteger() { return (datatypeClass == Datatype.CLASS_INTEGER); } 910 911 /** 912 * Checks if this datatype is a floating-point type. 913 * 914 * @return true if the datatype is floating-point; false otherwise 915 */ 916 public boolean isFloat() { return (datatypeClass == Datatype.CLASS_FLOAT); } 917 918 /** 919 * Checks if this datatype is a named type. 920 * 921 * @return true if the datatype is named; false otherwise 922 */ 923 public boolean isNamed() { return isNamed; } 924 925 /** 926 * Checks if this datatype is a variable-length string type. 927 * 928 * @return true if the datatype is variable-length string; false otherwise 929 */ 930 public boolean isVarStr() { return isVariableStr; } 931 932 /** 933 * Checks if this datatype is a variable-length type. 934 * 935 * @return true if the datatype is variable-length; false otherwise 936 */ 937 public boolean isVLEN() { return isVLEN; } 938 939 /** 940 * Checks if this datatype is an compound type. 941 * 942 * @return true if the datatype is compound; false otherwise 943 */ 944 public boolean isCompound() { return (datatypeClass == Datatype.CLASS_COMPOUND); } 945 946 /** 947 * Checks if this datatype is an array type. 948 * 949 * @return true if the datatype is array; false otherwise 950 */ 951 public boolean isArray() { return (datatypeClass == Datatype.CLASS_ARRAY); } 952 953 /** 954 * Checks if this datatype is a string type. 955 * 956 * @return true if the datatype is string; false otherwise 957 */ 958 public boolean isString() { return (datatypeClass == Datatype.CLASS_STRING); } 959 960 /** 961 * Checks if this datatype is a character type. 962 * 963 * @return true if the datatype is character; false otherwise 964 */ 965 public boolean isChar() { return (datatypeClass == Datatype.CLASS_CHAR); } 966 967 /** 968 * Checks if this datatype is a reference type. 969 * 970 * @return true if the datatype is reference; false otherwise 971 */ 972 public boolean isRef() { return (datatypeClass == Datatype.CLASS_REFERENCE); } 973 974 /** 975 * Checks if this datatype is a enum type. 976 * 977 * @return true if the datatype is enum; false otherwise 978 */ 979 public boolean isEnum() { return (datatypeClass == Datatype.CLASS_ENUM); } 980 981 /** 982 * Checks if this datatype is a opaque type. 983 * 984 * @return true if the datatype is opaque; false otherwise 985 */ 986 public boolean isOpaque() { return (datatypeClass == Datatype.CLASS_OPAQUE); } 987 988 /** 989 * Checks if this datatype is a bitfield type. 990 * 991 * @return true if the datatype is bitfield; false otherwise 992 */ 993 public boolean isBitField() { return (datatypeClass == Datatype.CLASS_BITFIELD); } 994 995 /* Implement interface MetaDataContainer */ 996 997 /** 998 * Removes all of the elements from metadata list. 999 * The list should be empty after this call returns. 1000 */ 1001 @Override 1002 public void clear() 1003 { 1004 } 1005 1006 /** 1007 * Retrieves the object's metadata, such as attributes, from the file. 1008 * 1009 * Metadata, such as attributes, is stored in a List. 1010 * 1011 * @return the list of metadata objects. 1012 * 1013 * @throws Exception 1014 * if the metadata can not be retrieved 1015 */ 1016 @Override 1017 @SuppressWarnings("rawtypes") 1018 public List getMetadata() throws Exception 1019 { 1020 return null; 1021 } 1022 1023 /** 1024 * Writes a specific piece of metadata (such as an attribute) into the file. 1025 * 1026 * If an HDF(4&5) attribute exists in the file, this method updates its 1027 * value. If the attribute does not exist in the file, it creates the 1028 * attribute in the file and attaches it to the object. It will fail to 1029 * write a new attribute to the object where an attribute with the same name 1030 * already exists. To update the value of an existing attribute in the file, 1031 * one needs to get the instance of the attribute by getMetadata(), change 1032 * its values, then use writeMetadata() to write the value. 1033 * 1034 * @param info 1035 * the metadata to write. 1036 * 1037 * @throws Exception 1038 * if the metadata can not be written 1039 */ 1040 @Override 1041 public void writeMetadata(Object info) throws Exception 1042 { 1043 throw new UnsupportedOperationException( 1044 "Unsupported operation. Subclasses must implement Datatype:writeMetadata."); 1045 } 1046 1047 /** 1048 * Deletes an existing piece of metadata from this object. 1049 * 1050 * @param info 1051 * the metadata to delete. 1052 * 1053 * @throws Exception 1054 * if the metadata can not be removed 1055 */ 1056 @Override 1057 public void removeMetadata(Object info) throws Exception 1058 { 1059 throw new UnsupportedOperationException( 1060 "Unsupported operation. Subclasses must implement Datatype:removeMetadata."); 1061 } 1062 1063 /** 1064 * Updates an existing piece of metadata attached to this object. 1065 * 1066 * @param info 1067 * the metadata to update. 1068 * 1069 * @throws Exception 1070 * if the metadata can not be updated 1071 */ 1072 @Override 1073 public void updateMetadata(Object info) throws Exception 1074 { 1075 throw new UnsupportedOperationException( 1076 "Unsupported operation. Subclasses must implement Datatype:updateMetadata."); 1077 } 1078 1079 @Override 1080 public String toString() 1081 { 1082 return getDescription(); 1083 } 1084}