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