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