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