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 https://support.hdfgroup.org/products/licenses.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.h4; 016 017import java.util.List; 018 019import hdf.hdflib.HDFConstants; 020import hdf.object.Datatype; 021 022/** 023 * This class defines HDF4 data type characteristics and APIs for a data type. 024 * 025 * This class provides several methods to convert an HDF4 datatype identifier to a datatype object, 026 * and vice versa. A datatype object is described by four basic fields: datatype class, size, byte 027 * order, and sign, while an HDF5 datatype is presented by a datatype identifier. 028 * 029 * @version 1.1 9/4/2007 030 * @author Peter X. Cao 031 */ 032public class H4Datatype extends Datatype { 033 private static final long serialVersionUID = -1342029403385521874L; 034 035 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4Datatype.class); 036 037 /** 038 * Constructs a H4Datatype with specified class, size, byte order and sign. 039 * 040 * The following is a list of a few examples of H4Datatype: 041 * <ol> 042 * <li>to create unsigned native integer<br> 043 * H4Datatype type = new H4Dataype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE); 044 * <li>to create 16-bit signed integer with big endian<br> 045 * H4Datatype type = new H4Dataype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE); 046 * <li>to create native float<br> 047 * H4Datatype type = new H4Dataype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE); 048 * <li>to create 64-bit double<br> 049 * H4Datatype type = new H4Dataype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 050 * </ol> 051 * 052 * @param tclass 053 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 054 * @param tsize 055 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 056 * Valid values are NATIVE or a positive value. 057 * @param torder 058 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 059 * ORDER_NONE and NATIVE. 060 * @param tsign 061 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 062 * 063 * @throws Exception 064 * if there is an error 065 */ 066 public H4Datatype(int tclass, int tsize, int torder, int tsign) throws Exception { 067 super(tclass, tsize, torder, tsign); 068 datatypeDescription = getDescription(); 069 } 070 071 /** 072 * Constructs a H4Datatype with a given native datatype identifier. 073 * 074 * For example, 075 * 076 * <pre> 077 * Datatype dtype = new H4Datatype(HDFConstants.DFNT_INT32); 078 * </pre> 079 * 080 * will construct a datatype equivalent to 081 * 082 * <pre> 083 * new H4Datatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, Datatype.SIGN_NONE); 084 * </pre> 085 * 086 * @see #fromNative(long nativeID) 087 * 088 * @param nativeID 089 * the native datatype identifier. 090 * 091 * @throws Exception 092 * if there is an error 093 */ 094 public H4Datatype(long nativeID) throws Exception { 095 super(null, nativeID); 096 097 fromNative(nativeID); 098 datatypeDescription = getDescription(); 099 } 100 101 /* 102 * (non-Javadoc) 103 * 104 * @see hdf.object.Datatype#fromNative(long) 105 */ 106 @Override 107 public void fromNative(long tid) { 108 datatypeOrder = NATIVE; 109 datatypeSign = NATIVE; 110 111 switch ((int) tid) { 112 case HDFConstants.DFNT_CHAR: 113 datatypeClass = CLASS_CHAR; 114 datatypeSize = 1; 115 break; 116 case HDFConstants.DFNT_UCHAR8: 117 datatypeClass = CLASS_CHAR; 118 datatypeSize = 1; 119 datatypeSign = SIGN_NONE; 120 break; 121 case HDFConstants.DFNT_INT8: 122 datatypeClass = CLASS_INTEGER; 123 datatypeSize = 1; 124 break; 125 case HDFConstants.DFNT_UINT8: 126 datatypeClass = CLASS_INTEGER; 127 datatypeSize = 1; 128 datatypeSign = SIGN_NONE; 129 break; 130 case HDFConstants.DFNT_INT16: 131 datatypeClass = CLASS_INTEGER; 132 datatypeSize = 2; 133 break; 134 case HDFConstants.DFNT_UINT16: 135 datatypeClass = CLASS_INTEGER; 136 datatypeSize = 2; 137 datatypeSign = SIGN_NONE; 138 break; 139 case HDFConstants.DFNT_INT32: 140 datatypeClass = CLASS_INTEGER; 141 datatypeSize = 4; 142 break; 143 case HDFConstants.DFNT_UINT32: 144 datatypeClass = CLASS_INTEGER; 145 datatypeSize = 4; 146 datatypeSign = SIGN_NONE; 147 break; 148 case HDFConstants.DFNT_INT64: 149 datatypeClass = CLASS_INTEGER; 150 datatypeSize = 8; 151 break; 152 case HDFConstants.DFNT_UINT64: 153 datatypeClass = CLASS_INTEGER; 154 datatypeSize = 8; 155 datatypeSign = SIGN_NONE; 156 break; 157 case HDFConstants.DFNT_FLOAT32: 158 datatypeClass = CLASS_FLOAT; 159 datatypeSize = 4; 160 break; 161 case HDFConstants.DFNT_FLOAT64: 162 datatypeClass = CLASS_FLOAT; 163 datatypeSize = 8; 164 break; 165 default: 166 datatypeClass = CLASS_NO_CLASS; 167 break; 168 } 169 170 log.trace("Datatype class={} size={}", datatypeClass, datatypeSize); 171 } 172 173 /** 174 * Allocate a 1D array large enough to hold a multidimensional array of 'datasize' elements of 175 * 'datatype' numbers. 176 * 177 * @param datatype 178 * the data type 179 * @param datasize 180 * the size of the data array 181 * 182 * @return an array of 'datasize' numbers of datatype. 183 * 184 * @throws OutOfMemoryError 185 * if the array cannot be allocated 186 */ 187 public static final Object allocateArray(long datatype, int datasize) throws OutOfMemoryError { 188 if (datasize <= 0) { 189 log.debug("datasize <= 0"); 190 return null; 191 } 192 193 Object data = null; 194 195 switch ((int) datatype) { 196 case HDFConstants.DFNT_CHAR: 197 case HDFConstants.DFNT_UCHAR8: 198 case HDFConstants.DFNT_UINT8: 199 case HDFConstants.DFNT_INT8: 200 log.trace("allocateArray(): allocating byte array of size {}", datasize); 201 data = new byte[datasize]; 202 break; 203 case HDFConstants.DFNT_INT16: 204 case HDFConstants.DFNT_UINT16: 205 log.trace("allocateArray(): allocating short array of size {}", datasize); 206 data = new short[datasize]; 207 break; 208 case HDFConstants.DFNT_INT32: 209 case HDFConstants.DFNT_UINT32: 210 log.trace("allocateArray(): allocating int array of size {}", datasize); 211 if (datasize == NATIVE) 212 datasize = 4; 213 data = new int[datasize]; 214 break; 215 case HDFConstants.DFNT_INT64: 216 case HDFConstants.DFNT_UINT64: 217 log.trace("allocateArray(): allocating long array of size {}", datasize); 218 data = new long[datasize]; 219 break; 220 case HDFConstants.DFNT_FLOAT32: 221 log.trace("allocateArray(): allocating float array of size {}", datasize); 222 data = new float[datasize]; 223 break; 224 case HDFConstants.DFNT_FLOAT64: 225 log.trace("allocateArray(): allocating double array of size {}", datasize); 226 data = new double[datasize]; 227 break; 228 default: 229 log.debug("allocateArray(): unknown datatype {}", datatype); 230 data = null; 231 break; 232 } 233 234 return data; 235 } 236 237 /* 238 * (non-Javadoc) 239 * 240 * @see hdf.object.Datatype#getDatatypeDescription() 241 */ 242 @Override 243 public String getDescription() { 244 if (datatypeDescription != null) 245 return datatypeDescription; 246 247 String description = null; 248 249 switch (datatypeClass) { 250 case CLASS_CHAR: 251 description = "8-bit " + (isUnsigned() ? "unsigned " : "") + "character"; 252 break; 253 case CLASS_INTEGER: 254 description = String.valueOf(datatypeSize * 8) + "-bit " + (isUnsigned() ? "unsigned " : "") + "integer"; 255 break; 256 case CLASS_FLOAT: 257 description = String.valueOf(datatypeSize * 8) + "-bit floating-point"; 258 break; 259 default: 260 description = "Unknown"; 261 break; 262 } 263 264 return description; 265 } 266 267 /* 268 * (non-Javadoc) 269 * 270 * @see hdf.object.Datatype#isUnsigned() 271 */ 272 @Override 273 public boolean isUnsigned() { 274 return (Datatype.SIGN_NONE == getDatatypeSign()); 275 } 276 277 /** 278 * Checks if the datatype is an unsigned integer. 279 * 280 * @param datatype 281 * the data type. 282 * 283 * @return True is the datatype is an unsigned integer; otherwise returns false. 284 */ 285 public static final boolean isUnsigned(long datatype) { 286 boolean unsigned = false; 287 288 switch((int) datatype) { 289 case HDFConstants.DFNT_UCHAR8: 290 case HDFConstants.DFNT_UINT8: 291 case HDFConstants.DFNT_UINT16: 292 case HDFConstants.DFNT_UINT32: 293 case HDFConstants.DFNT_UINT64: 294 unsigned = true; 295 break; 296 default: 297 log.debug("isUnsigned(): unknown datatype {}", datatype); 298 unsigned = false; 299 break; 300 } 301 302 return unsigned; 303 } 304 305 @Override 306 public boolean isText() { 307 return (Datatype.CLASS_STRING == getDatatypeClass()); 308 } 309 310 /* 311 * (non-Javadoc) 312 * @see hdf.object.Datatype#createNative() 313 */ 314 @Override 315 public long createNative() { 316 long tid = -1; 317 int tclass = getDatatypeClass(); 318 int tsize = (int) getDatatypeSize(); 319 320 // figure the datatype 321 switch (tclass) { 322 case Datatype.CLASS_INTEGER: 323 if (tsize == 1) { 324 if (isUnsigned()) { 325 tid = HDFConstants.DFNT_UINT8; 326 } 327 else { 328 tid = HDFConstants.DFNT_INT8; 329 } 330 } 331 else if (tsize == 2) { 332 if (isUnsigned()) { 333 tid = HDFConstants.DFNT_UINT16; 334 } 335 else { 336 tid = HDFConstants.DFNT_INT16; 337 } 338 } 339 else if ((tsize == 4) || (tsize == NATIVE)) { 340 if (isUnsigned()) { 341 tid = HDFConstants.DFNT_UINT32; 342 } 343 else { 344 tid = HDFConstants.DFNT_INT32; 345 } 346 } 347 else if (tsize == 8) { 348 if (isUnsigned()) { 349 tid = HDFConstants.DFNT_UINT64; 350 } 351 else { 352 tid = HDFConstants.DFNT_INT64; 353 } 354 } 355 break; 356 case Datatype.CLASS_FLOAT: 357 if (tsize == Datatype.NATIVE) { 358 tid = HDFConstants.DFNT_FLOAT; 359 } 360 else if (tsize == 4) { 361 tid = HDFConstants.DFNT_FLOAT32; 362 } 363 else if (tsize == 8) { 364 tid = HDFConstants.DFNT_FLOAT64; 365 } 366 break; 367 case Datatype.CLASS_CHAR: 368 if (isUnsigned()) { 369 tid = HDFConstants.DFNT_UCHAR; 370 } 371 else { 372 tid = HDFConstants.DFNT_CHAR; 373 } 374 break; 375 case Datatype.CLASS_STRING: 376 tid = HDFConstants.DFNT_CHAR; 377 break; 378 default: 379 log.debug("createNative(): unknown datatype class {}", tclass); 380 } 381 382 return tid; 383 } 384 385 /* 386 * (non-Javadoc) 387 * 388 * @see hdf.object.Datatype#close(int) 389 */ 390 @Override 391 public void close(long id) { 392 // No implementation 393 } 394 395 // Implementing MetaDataContainer 396 /** 397 * Retrieves the object's metadata, such as attributes, from the file. 398 * 399 * Metadata, such as attributes, is stored in a List. 400 * 401 * @param attrPropList 402 * the list of properties to get 403 * 404 * @return the list of metadata objects. 405 * 406 * @throws Exception 407 * if the metadata can not be retrieved 408 */ 409 @SuppressWarnings("rawtypes") 410 public List getMetadata(int... attrPropList) throws Exception { 411 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 412 } 413 414 /** 415 * Check if the object has any attributes attached. 416 * 417 * @return true if it has any attributes, false otherwise. 418 */ 419 @Override 420 public boolean hasAttribute() { 421 return false; 422 } 423}