    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}