1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 
16 /*------------------------------------------------------------------
17  File:  dfconv.c
18 
19  Purpose:
20     Routines to support conversion to and from HDF format
21 
22  Invokes:
23 
24  PRIVATE conversion functions: All of these are now in seperate files!
25     dfknat.c
26     DFKnb1b -  Native mode for 8 bit integers
27     DFKnb2b -  Native mode for 16 bit integers
28     DFKnb4b -  Native mode for 32 bit integers and floats
29     DFKnb8b -  Native mode for 64 bit floats
30     dfkswap.c
31     DFKsb2b -  Byte swapping for 16 bit integers
32     DFKsb4b -  Byte swapping for 32 bit integers
33     DFKsb8b -  Byte swapping for 64 bit floats
34 
35  Other PUBLIC functions:
36     DFKmachineNTsize - Determine size in machine, given number type
37     DFKhdfNTsize     - Determine size in HDF format, given number type
38     DFKsetNT         - Set number type for future conversion calls
39     DFKsetcustom    - Template for user to setup custom conversion
40                       routines
41     DFKisnative     - Checks whether number type is native mode
42     DFKislitend     - Checks whether number type is little-endian mode
43     DFconvert       - provide compatibility with 3.0 routines
44 
45  Private functions:
46     DFKInoset    - Indicate that DFKsetNT hasn't been called
47 
48  Remarks:
49 
50  *------------------------------------------------------------------*/
51 
52 /*****************************************************************************/
53 /*                                                                           */
54 /*    All the routines in this file marked as PRIVATE have been marked so    */
55 /*  for a reason.  *ANY* of these routines may or may nor be supported in    */
56 /*  the next version of HDF (4.00).  Furthurmore, the names, paramters, or   */
57 /*  functionality is *NOT* guaranteed to remain the same.                    */
58 /*    The *ONLY* guarantee possible is that DFKnumin(), and DFKnumout()      */
59 /*  will not change.  They are *NOT* guaranteed to be implemented in the     */
60 /*  next version of HDF as function pointers.  They are guaranteed to take   */
61 /*  the same arguments and produce the same results.                         */
62 /*    If your programs call any routines in this file except for             */
63 /*  DFKnumin(), DFKnumout, and/or DFKsetntype(), your code may not work      */
64 /*  with future versions of HDF and your code will *NOT* be portable.        */
65 /*                                                                           */
66 /*****************************************************************************/
67 
68 #include <ctype.h>
69 #include "hdf.h"
70 #include "hconv.h"
71 
72 /*
73    **  Static function prototypes
74  */
75 PRIVATE int DFKInoset
76             (VOIDP source, VOIDP dest, uint32 num_elm, uint32 source_stride,
77              uint32 dest_stride);
78 
79 /* Prototypes */
80 extern int32 DFKqueryNT(void);
81 extern int DFKsetcustom(
82   int (*DFKcustin) (VOIDP source, VOIDP dest, uint32 num_elm,
83                            uint32 source_stride, uint32 dest_stride),
84   int  (*DFKcustout) (VOIDP source, VOIDP dest, uint32 num_elm,
85                              uint32 source_stride, uint32 dest_stride));
86 extern int DFconvert(uint8 *source, uint8 *dest, int ntype, int sourcetype,
87                      int desttype, int32 size);
88 
89 /*
90    **  Conversion Routine Pointer Definitions
91  */
92 static int	(*DFKnumin)
93             (VOIDP source, VOIDP dest, uint32 num_elm,
94                     uint32 source_stride, uint32 dest_stride) = DFKInoset;
95 static int	(*DFKnumout)
96             (VOIDP source, VOIDP dest, uint32 num_elm,
97                     uint32 source_stride, uint32 dest_stride) = DFKInoset;
98 
99 /************************************************************
100  * If the programmer forgot to call DFKsetntype, then let
101  * them know about it.
102  ************************************************************/
103 PRIVATE int
DFKInoset(VOIDP source,VOIDP dest,uint32 num_elm,uint32 source_stride,uint32 dest_stride)104 DFKInoset(VOIDP source, VOIDP dest, uint32 num_elm,
105           uint32 source_stride, uint32 dest_stride)
106 {
107     CONSTR(FUNC, "DFKInoset");
108 
109     HEclear();
110 
111     /* shut the compiler up about not using the arguments */
112     source = source;
113     dest = dest;
114     num_elm = num_elm;
115     source_stride = source_stride;
116     dest_stride = dest_stride;
117 
118     /* If this is causing a problem for you, call DFKsetntype */
119     HERROR(DFE_BADCONV);
120     return FAIL;
121 }
122 
123 /*****************************************************************************
124  * Routines that depend on the above information
125  *****************************************************************************/
126 
127 PRIVATE int32 g_ntype = DFNT_NONE;  /* Holds current number type. */
128                     /* Initially not set.         */
129 
130 /************************************************************
131 * DFKqueryNT()
132 *   Determine the current conversion settings
133  ************************************************************/
134 int32
DFKqueryNT(void)135 DFKqueryNT(void)
136 {
137     return g_ntype;
138 }
139 
140 /************************************************************
141  * DFKNTsize()
142  *   Determine the size, given the number type
143  ************************************************************/
144 int
DFKNTsize(int32 number_type)145 DFKNTsize(int32 number_type)
146 {
147 #ifdef LATER
148     CONSTR(FUNC, "DFKNTsize");
149 #endif
150 
151     /* mask off the litend bit since little endian and big endian have */
152     /* the same size.  Only need to distinguish size difference between */
153     /* HDF and native types. */
154     switch (number_type & (~DFNT_LITEND))
155       {
156 	  /* native types */
157           case DFNT_NUCHAR:
158               return (SIZE_NUCHAR);
159           case DFNT_NCHAR:
160               return (SIZE_NCHAR);
161           case DFNT_NINT8:
162               return (SIZE_NINT8);
163           case DFNT_NUINT8:
164               return (SIZE_NUINT8);
165 
166           case DFNT_NINT16:
167               return (SIZE_NINT16);
168           case DFNT_NUINT16:
169               return (SIZE_NUINT16);
170 
171           case DFNT_NINT32:
172               return (SIZE_NINT32);
173           case DFNT_NUINT32:
174               return (SIZE_NUINT32);
175 
176           case DFNT_NFLOAT32:
177               return (SIZE_NFLOAT32);
178 
179           case DFNT_NFLOAT64:
180               return (SIZE_NFLOAT64);
181 
182 	  /* HDF types */
183           case DFNT_UCHAR:
184               return (SIZE_UCHAR);
185           case DFNT_CHAR:
186               return (SIZE_CHAR);
187           case DFNT_INT8:
188               return (SIZE_INT8);
189           case DFNT_UINT8:
190               return (SIZE_UINT8);
191 
192           case DFNT_INT16:
193               return (SIZE_INT16);
194           case DFNT_UINT16:
195               return (SIZE_UINT16);
196 
197           case DFNT_INT32:
198               return (SIZE_INT32);
199           case DFNT_UINT32:
200               return (SIZE_UINT32);
201 
202           case DFNT_FLOAT32:
203               return (SIZE_FLOAT32);
204 
205           case DFNT_FLOAT64:
206               return (SIZE_FLOAT64);
207 
208 	  /* Unknown types */
209           default:
210               break;
211       }     /* switch       */
212     /* hdf default format   */
213     return FAIL;
214 }
215 
216 /************************************************************
217  * DFKsetNT()
218  *   Set the number type for future conversion calls
219  ************************************************************/
220 intn
DFKsetNT(int32 ntype)221 DFKsetNT(int32 ntype)
222 {
223     CONSTR(FUNC, "DFKsetNT");
224 
225     HEclear();
226 
227     g_ntype = ntype;
228 
229     switch (ntype)
230       {
231           case DFNT_CHAR8:
232           case DFNT_UCHAR8:
233           case DFNT_INT8:
234           case DFNT_UINT8:
235               DFKnumin = UI8_IN;
236               DFKnumout = UI8_OUT;
237               break;
238           case DFNT_INT16:
239               DFKnumin = SI16_IN;
240               DFKnumout = SI16_OUT;
241               break;
242           case DFNT_UINT16:
243               DFKnumin = UI16_IN;
244               DFKnumout = UI16_OUT;
245               break;
246           case DFNT_INT32:
247               DFKnumin = SI32_IN;
248               DFKnumout = SI32_OUT;
249               break;
250           case DFNT_UINT32:
251               DFKnumin = UI32_IN;
252               DFKnumout = UI32_OUT;
253               break;
254           case DFNT_FLOAT32:
255               DFKnumin = F32_IN;
256               DFKnumout = F32_OUT;
257               break;
258           case DFNT_FLOAT64:
259               DFKnumin = F64_IN;
260               DFKnumout = F64_OUT;
261               break;
262 
263               /*
264                * NATIVE MODE 'CONVERSIONS'
265                */
266           case DFNT_NCHAR:
267           case DFNT_NINT8:
268           case DFNT_NUCHAR:
269           case DFNT_NUINT8:
270               DFKnumin = NUI8_IN;
271               DFKnumout = NUI8_OUT;
272               break;
273           case DFNT_NINT16:
274               DFKnumin = NSI16_IN;
275               DFKnumout = NSI16_OUT;
276               break;
277           case DFNT_NUINT16:
278               DFKnumin = NUI16_IN;
279               DFKnumout = NUI16_OUT;
280               break;
281           case DFNT_NINT32:
282               DFKnumin = NSI32_IN;
283               DFKnumout = NSI32_OUT;
284               break;
285           case DFNT_NUINT32:
286               DFKnumin = NUI32_IN;
287               DFKnumout = NUI32_OUT;
288               break;
289           case DFNT_NFLOAT32:
290               DFKnumin = NF32_IN;
291               DFKnumout = NF32_OUT;
292               break;
293           case DFNT_NFLOAT64:
294               DFKnumin = NF64_IN;
295               DFKnumout = NF64_OUT;
296               break;
297 
298               /*
299                * Little Endian Conversions
300                */
301           case DFNT_LCHAR:
302           case DFNT_LINT8:
303           case DFNT_LUCHAR:
304           case DFNT_LUINT8:
305               DFKnumin = LUI8_IN;
306               DFKnumout = LUI8_OUT;
307               break;
308           case DFNT_LINT16:
309               DFKnumin = LSI16_IN;
310               DFKnumout = LSI16_OUT;
311               break;
312           case DFNT_LUINT16:
313               DFKnumin = LUI16_IN;
314               DFKnumout = LUI16_OUT;
315               break;
316           case DFNT_LINT32:
317               DFKnumin = LSI32_IN;
318               DFKnumout = LSI32_OUT;
319               break;
320           case DFNT_LUINT32:
321               DFKnumin = LUI32_IN;
322               DFKnumout = LUI32_OUT;
323               break;
324           case DFNT_LFLOAT32:
325               DFKnumin = LF32_IN;
326               DFKnumout = LF32_OUT;
327               break;
328           case DFNT_LFLOAT64:
329               DFKnumin = LF64_IN;
330               DFKnumout = LF64_OUT;
331               break;
332 
333 /* No conversion routines are specified for DFNT_custom.  User must provide. */
334 /* Users should call DFCV_SetCustomIn() and DFCV_SetCustomOut() if they      */
335 /* choose to use DFNT_CUSTOM.  Users should provide their own method to      */
336 /* distinguish between multiple 'custom' conversion routines.  HDF only      */
337 /* knows such routines as type 'DFNT_CUSTOM'.                                */
338 
339           case DFNT_CUSTOM:
340               g_ntype = DFNT_CUSTOM;
341               break;
342           default:
343               HRETURN_ERROR(DFE_BADCONV,FAIL)
344       }
345   return 0;
346 }
347 
348 /*****************************************************************************
349  * The following routine provides an easy method for the user to setup custom
350  * conversion routines....
351  *****************************************************************************/
352 int
DFKsetcustom(int (* DFKcustin)(VOIDP,VOIDP,uint32,uint32,uint32),int (* DFKcustout)(VOIDP,VOIDP,uint32,uint32,uint32))353 DFKsetcustom(
354   int         (*DFKcustin) (VOIDP /* source */, VOIDP /* dest */, uint32 /* num_elm */,
355                                  uint32 /* source_stride */, uint32 /* dest_stride */),
356  int         (*DFKcustout) (VOIDP /* source */, VOIDP /* dest */, uint32 /* num_elm */,
357                                    uint32 /* source_stride */, uint32 /* dest_stride */)
358 )
359 {
360     DFKnumin = DFKcustin;
361     DFKnumout = DFKcustout;
362     DFKsetNT(DFNT_CUSTOM);  /* Keep HDF from getting confused */
363     return 0;
364 }
365 
366 /*------------------------------------------------------------------
367  * Name:    DFKisnativeNT
368  * Purpose: Determine whether number type is native mode
369  * Inputs:  numbertype: number type
370  * Returns: 1 if true, 0 if false
371  * Users:   DFSDgetslice
372  * Method:  Checks to see if the "native mode" bit is set
373  * Remarks:
374  *------------------------------------------------------------------*/
375 
376 int32
DFKisnativeNT(int32 numbertype)377 DFKisnativeNT(int32 numbertype)
378 {
379     return ((DFNT_NATIVE & numbertype) > 0 ? 1 : 0);
380 }
381 
382 /*------------------------------------------------------------------
383  * Name:    DFKislitendNT
384  * Purpose: Determine whether number type is little-endian mode
385  * Inputs:  numbertype: number type
386  * Returns: 1 if true, 0 if false
387  * Users:   DFSDgetslice
388  * Method:  Checks to see if the "native mode" bit is set
389  * Remarks:
390  *------------------------------------------------------------------*/
391 
392 int32
DFKislitendNT(int32 numbertype)393 DFKislitendNT(int32 numbertype)
394 {
395     return ((DFNT_LITEND & numbertype) > 0 ? 1 : 0);
396 }
397 
398 /************************************************************
399  * DFconvert()
400  *
401  * This routine is called by HDF version 3.0 compatibility
402  * routines.  It serves as a jump point to the new version 4.0
403  * comversion functions.  DFconvert() CANNOT be used by Vdata
404  * applications because it assumes a stride of 1 (for
405  * compatibility). Vdata routines should call DFnum_in() and
406  * DFKnumout() (depending on which translation is needed)
407  *
408  * uint8 * source    location where the data is stored
409  * uint8 * dest      location to put the converted data
410  * int  * ntype       the overall number type of the data, ie DFNT_FLOAT...
411  * int  * sourcetype  the specific type of the source data, ie DFNTF_IEEE...
412  * int  * desttype    the specifid type of the converted data, ie DFNTF_VAX...
413  * int  * size        the number (total) of BYTES to convert
414  ************************************************************/
415 int
DFconvert(uint8 * source,uint8 * dest,int ntype,int sourcetype,int desttype,int32 size)416 DFconvert(uint8 *source, uint8 *dest, int ntype, int sourcetype, int desttype,
417           int32 size)
418 {
419     uint32 num_elm;
420     CONSTR(FUNC, "DFconvert");
421 
422     HEclear();
423 
424     if (DFKsetNT(ntype) == FAIL)
425       {
426           HERROR(DFE_BADCONV);
427           return FAIL;
428       }
429 
430     if (sourcetype == desttype)
431       {
432           HDmemcpy(dest, source, size);
433           return 0;
434       }
435 
436     num_elm = (uint32)size / 4;
437 
438 /* Check to see if they want to covert numbers in from the disk */
439     if (sourcetype == DFNTF_IEEE && (desttype == DFNTF_VAX ||
440                                      desttype == DFNTF_CRAY ||
441                                      desttype == DFNTF_PC))
442         return (DFKnumin) ((VOIDP) source, (VOIDP) dest, num_elm, 0, 0);
443 
444 /* Check to see if they want to convert numbers out to disk */
445     if (desttype == DFNTF_IEEE && (sourcetype == DFNTF_VAX ||
446                                    sourcetype == DFNTF_CRAY ||
447                                    sourcetype == DFNTF_PC))
448         return DFKnumout((VOIDP) source, (VOIDP) dest, num_elm, 0, 0);
449 
450 /* Return an error because they did not specify valid translation codes */
451     HERROR(DFE_BADCONV);
452     return FAIL;
453 }
454 
455 /*------------------------------------------------------------------
456  * Name:    DFKgetPNSC
457  * Purpose: Get PlatformNumberSubclass for a given number type
458  * Inputs:  numtype: number type to get subclass for
459  *          machinetype: machine-type code
460  * Returns: PlatformNumberSubclass on success, FAIL on failure with
461  *          error set
462  * Users:   DFSDgetslice
463  * Method:  Checks NT_TYPES to determine whether it is a char, int, or
464  *          float, then looks in corresponding field of machine type
465  *          (DFMT) to get the class.
466  * Remarks:
467  *------------------------------------------------------------------*/
468 
469 int8
DFKgetPNSC(int32 numbertype,int32 machinetype)470 DFKgetPNSC(int32 numbertype, int32 machinetype)
471 {
472     CONSTR(FUNC, "DFKgetPNSC");
473 
474     /* clear error stack and validate args */
475     HEclear();
476 
477     /* Since the information is provided only for the 4 */
478     /* classes of char, int, float, double and is indenpend */
479     /* of whether it is stored native or little-endian in file, */
480     /* we will use only the standard HDF format information */
481     switch (numbertype & DFNT_MASK)
482       {
483           case DFNT_CHAR8:
484           case DFNT_UCHAR8:
485               return (int8) (machinetype & 0x0f);
486 
487           case DFNT_INT8:
488           case DFNT_UINT8:
489           case DFNT_INT16:
490           case DFNT_UINT16:
491           case DFNT_INT32:
492           case DFNT_UINT32:
493               return (int8) ((machinetype >> 4) & 0x0f);
494 
495           case DFNT_FLOAT32:
496               return (int8) ((machinetype >> 8) & 0x0f);
497 
498           case DFNT_FLOAT64:
499               return (int8) ((machinetype >> 12) & 0x0f);
500 
501           default:
502 	      HRETURN_ERROR(DFE_BADNUMTYPE, FAIL);
503       }
504 }
505 
506 /*----------------------------------------------------------------------------
507 * Name: DFKconvert
508 * Purpose: set number type and do the convert
509 * Inputs:  source -- location where the data is stored
510 *      dest -- location to put the converted data
511 *      ntype -- the current number type
512 *      num_elm -- number of elements to be converted
513 *      acc_mode -- DFACC_READ for numin, DFACC_WRITE for numout
514 *      source_stride, dest_stride -- strides in source and destination
515 * Returns: 0 -- succeed; FAIL -- failure
516 * Users:   DFSDgetsdg, DFSDputsdg, DFSDIgetslice, DFSDIgetslice
517 * Method:  Calls DFKsetNT, then call DFnumin or DFnumout
518 *---------------------------------------------------------------------------*/
519 int32
DFKconvert(VOIDP source,VOIDP dest,int32 ntype,int32 num_elm,int16 acc_mode,int32 source_stride,int32 dest_stride)520 DFKconvert(VOIDP source, VOIDP dest, int32 ntype, int32 num_elm,
521            int16 acc_mode, int32 source_stride, int32 dest_stride)
522 {
523     int         ret;
524 
525     /* Check args (minimally) */
526     if (source==NULL || dest==NULL)
527         return(-1);
528 
529     DFKsetNT(ntype);
530     if (acc_mode == DFACC_READ)
531         ret = DFKnumin(source, dest, (uint32)num_elm, (uint32)source_stride, (uint32)dest_stride);
532     else
533         ret = DFKnumout(source, dest, (uint32)num_elm, (uint32)source_stride, (uint32)dest_stride);
534     return (ret);
535 }
536 
537 /*****************************************************************************
538  * Miscellaneous Other Conversion Routines
539  *****************************************************************************/
540