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