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 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 * <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(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 * <p> 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.DataFormat#hasAttribute() 105 */ 106 @Override 107 public boolean hasAttribute() { 108 return false; 109 } 110 111 /* 112 * (non-Javadoc) 113 * 114 * @see hdf.object.Datatype#fromNative(long) 115 */ 116 @Override 117 public void fromNative(long tid) 118 { 119 datatypeOrder = NATIVE; 120 datatypeSign = NATIVE; 121 122 switch ((int) tid) { 123 case HDFConstants.DFNT_CHAR: 124 datatypeClass = CLASS_CHAR; 125 datatypeSize = 1; 126 break; 127 case HDFConstants.DFNT_UCHAR8: 128 datatypeClass = CLASS_CHAR; 129 datatypeSize = 1; 130 datatypeSign = SIGN_NONE; 131 break; 132 case HDFConstants.DFNT_INT8: 133 datatypeClass = CLASS_INTEGER; 134 datatypeSize = 1; 135 break; 136 case HDFConstants.DFNT_UINT8: 137 datatypeClass = CLASS_INTEGER; 138 datatypeSize = 1; 139 datatypeSign = SIGN_NONE; 140 break; 141 case HDFConstants.DFNT_INT16: 142 datatypeClass = CLASS_INTEGER; 143 datatypeSize = 2; 144 break; 145 case HDFConstants.DFNT_UINT16: 146 datatypeClass = CLASS_INTEGER; 147 datatypeSize = 2; 148 datatypeSign = SIGN_NONE; 149 break; 150 case HDFConstants.DFNT_INT32: 151 datatypeClass = CLASS_INTEGER; 152 datatypeSize = 4; 153 break; 154 case HDFConstants.DFNT_UINT32: 155 datatypeClass = CLASS_INTEGER; 156 datatypeSize = 4; 157 datatypeSign = SIGN_NONE; 158 break; 159 case HDFConstants.DFNT_INT64: 160 datatypeClass = CLASS_INTEGER; 161 datatypeSize = 8; 162 break; 163 case HDFConstants.DFNT_UINT64: 164 datatypeClass = CLASS_INTEGER; 165 datatypeSize = 8; 166 datatypeSign = SIGN_NONE; 167 break; 168 case HDFConstants.DFNT_FLOAT32: 169 datatypeClass = CLASS_FLOAT; 170 datatypeSize = 4; 171 break; 172 case HDFConstants.DFNT_FLOAT64: 173 datatypeClass = CLASS_FLOAT; 174 datatypeSize = 8; 175 break; 176 default: 177 datatypeClass = CLASS_NO_CLASS; 178 break; 179 } 180 181 log.trace("Datatype class={} size={}", datatypeClass, datatypeSize); 182 } 183 184 /** 185 * Allocate a 1D array large enough to hold a multidimensional array of 'datasize' elements of 186 * 'datatype' numbers. 187 * 188 * @param datatype 189 * the data type 190 * @param datasize 191 * the size of the data array 192 * 193 * @return an array of 'datasize' numbers of datatype. 194 * 195 * @throws OutOfMemoryError 196 * if the array cannot be allocated 197 */ 198 public static final Object allocateArray(long datatype, int datasize) 199 throws OutOfMemoryError { 200 if (datasize <= 0) { 201 log.debug("datasize <= 0"); 202 return null; 203 } 204 205 Object data = null; 206 207 switch ((int) datatype) { 208 case HDFConstants.DFNT_CHAR: 209 case HDFConstants.DFNT_UCHAR8: 210 case HDFConstants.DFNT_UINT8: 211 case HDFConstants.DFNT_INT8: 212 log.trace("allocateArray(): allocating byte array of size {}", datasize); 213 data = new byte[datasize]; 214 break; 215 case HDFConstants.DFNT_INT16: 216 case HDFConstants.DFNT_UINT16: 217 log.trace("allocateArray(): allocating short array of size {}", datasize); 218 data = new short[datasize]; 219 break; 220 case HDFConstants.DFNT_INT32: 221 case HDFConstants.DFNT_UINT32: 222 log.trace("allocateArray(): allocating int array of size {}", datasize); 223 data = new int[datasize]; 224 break; 225 case HDFConstants.DFNT_INT64: 226 case HDFConstants.DFNT_UINT64: 227 log.trace("allocateArray(): allocating long array of size {}", datasize); 228 data = new long[datasize]; 229 break; 230 case HDFConstants.DFNT_FLOAT32: 231 log.trace("allocateArray(): allocating float array of size {}", datasize); 232 data = new float[datasize]; 233 break; 234 case HDFConstants.DFNT_FLOAT64: 235 log.trace("allocateArray(): allocating double array of size {}", datasize); 236 data = new double[datasize]; 237 break; 238 default: 239 log.debug("allocateArray(): unknown datatype {}", datatype); 240 data = null; 241 break; 242 } 243 244 return data; 245 } 246 247 /* 248 * (non-Javadoc) 249 * 250 * @see hdf.object.Datatype#getDatatypeDescription() 251 */ 252 @Override 253 public String getDescription() { 254 255 if (datatypeDescription != null) { 256 return datatypeDescription; 257 } 258 259 String description = null; 260 261 switch (datatypeClass) { 262 case CLASS_CHAR: 263 description = "8-bit " + (isUnsigned() ? "unsigned " : "") + "character"; 264 break; 265 case CLASS_INTEGER: 266 description = String.valueOf(datatypeSize * 8) + "-bit " + (isUnsigned() ? "unsigned " : "") + "integer"; 267 break; 268 case CLASS_FLOAT: 269 description = String.valueOf(datatypeSize * 8) + "-bit floating-point"; 270 break; 271 default: 272 description = "Unknown"; 273 break; 274 } 275 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 boolean unsigned = false; 299 300 switch((int) datatype) { 301 case HDFConstants.DFNT_UCHAR8: 302 case HDFConstants.DFNT_UINT8: 303 case HDFConstants.DFNT_UINT16: 304 case HDFConstants.DFNT_UINT32: 305 case HDFConstants.DFNT_UINT64: 306 unsigned = true; 307 break; 308 default: 309 log.debug("isUnsigned(): unknown datatype {}", datatype); 310 unsigned = false; 311 break; 312 } 313 314 return unsigned; 315 } 316 317 @Override 318 public boolean isText() { 319 return (Datatype.CLASS_STRING == getDatatypeClass()); 320 } 321 322 /* 323 * (non-Javadoc) 324 * @see hdf.object.Datatype#createNative() 325 */ 326 @Override 327 public long createNative() 328 { 329 long tid = -1; 330 int tclass = getDatatypeClass(); 331 int tsize = (int) getDatatypeSize(); 332 333 // figure the datatype 334 switch (tclass) { 335 case Datatype.CLASS_INTEGER: 336 if (tsize == 1) { 337 if (isUnsigned()) { 338 tid = HDFConstants.DFNT_UINT8; 339 } 340 else { 341 tid = HDFConstants.DFNT_INT8; 342 } 343 } 344 else if (tsize == 2) { 345 if (isUnsigned()) { 346 tid = HDFConstants.DFNT_UINT16; 347 } 348 else { 349 tid = HDFConstants.DFNT_INT16; 350 } 351 } 352 else if ((tsize == 4) || (tsize == NATIVE)) { 353 if (isUnsigned()) { 354 tid = HDFConstants.DFNT_UINT32; 355 } 356 else { 357 tid = HDFConstants.DFNT_INT32; 358 } 359 } 360 else if (tsize == 8) { 361 if (isUnsigned()) { 362 tid = HDFConstants.DFNT_UINT64; 363 } 364 else { 365 tid = HDFConstants.DFNT_INT64; 366 } 367 } 368 break; 369 case Datatype.CLASS_FLOAT: 370 if (tsize == Datatype.NATIVE) { 371 tid = HDFConstants.DFNT_FLOAT; 372 } 373 else if (tsize == 4) { 374 tid = HDFConstants.DFNT_FLOAT32; 375 } 376 else if (tsize == 8) { 377 tid = HDFConstants.DFNT_FLOAT64; 378 } 379 break; 380 case Datatype.CLASS_CHAR: 381 if (isUnsigned()) { 382 tid = HDFConstants.DFNT_UCHAR; 383 } 384 else { 385 tid = HDFConstants.DFNT_CHAR; 386 } 387 break; 388 case Datatype.CLASS_STRING: 389 tid = HDFConstants.DFNT_CHAR; 390 break; 391 default: 392 log.debug("createNative(): unknown datatype class {}", tclass); 393 } 394 395 return tid; 396 } 397 398 /* 399 * (non-Javadoc) 400 * 401 * @see hdf.object.Datatype#close(int) 402 */ 403 @Override 404 public void close(long id) { 405 // No implementation 406 } 407 408 // Implementing DataFormat 409 @SuppressWarnings("rawtypes") 410 public List getMetadata(int... attrPropList) throws Exception { 411 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 412 } 413}