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