Made UAE buildable again.
[AROS-Contrib.git] / regina / gci / gci_convert.c
blob983b870162b8fd097bb08a741e489fea2d5f1f91
1 /*
2 * Generic Call Interface for Rexx
3 * Copyright © 2003-2004, Florian Große-Coosmann
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * ----------------------------------------------------------------------------
21 * This file converts numerical string values to binary values and vice versa.
23 * Supported datatypes must be configured from outside in the file
24 * gci_convert.h. We need functions for parsing and printing floating points
25 * and integers.
27 * We support integers with a size of a power of 2 only, typically
28 * 1, 2, 4, 8 and probably 16; every type with a smaller value will be
29 * accepted automatically.
31 * This is expected by the include file to be defined:
32 * GCI_I_x signed integer data type with x bytes.
33 * GCI_I_xm minimum value for GCI_I_x.
34 * GCI_I_xM maximum value for GCI_I_x.
35 * GCI_Ir function for converting GCI_I_x, x largest of all x, which
36 * converts a string into a binary representation. The function
37 * must behave as strtol with the fitting data type.
38 * GCI_Iw function for converting GCI_I_x, x largest of all x, which
39 * converts a binary representation of a number into a zero
40 * terminated string. The prototype must fit "GCI_Iw(string,GCI_I)".
41 * No error throwing is allowed. The maximum number of characters to
42 * write is 127. The function must return the length of string
43 * without the terminating '\0'.
46 * GCI_U_x
47 * GCI_U_xm
48 * GCI_U_xM
49 * GCI_Ur
50 * GCI_Uw same as above but for unsigned datatypes.
52 * GCI_F_x
53 * GCI_F_xm
54 * GCI_F_xM
55 * GCI_Fr
56 * GCI_Fw same as above but for floating point data types. GCI_Fw may
57 * write a maximum of 127 characters and may use "NaN", etc to
58 * present anomal numbers.
61 * One can take advantage of strtobigl and strtobigul for GCI_Ir and GCI_Ur
62 * is NEED_STRTOBIGL or NEED_STRTOBIGUL are defined. They are slow but work.
64 * strtobigf can be used for GCI_Fr if NEED_STRTOBIGF is defined. In this case,
65 * F_SCAN must be defined and should be the scanf() compatible mask for parsing
66 * a GCI_F_x value. Most systems need a '#define F_SCAN "%Lf"' in this case.
69 #include "gci_convert.h"
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <assert.h>
74 #include <errno.h>
75 #include <ctype.h>
77 #undef GCI_I
78 #undef GCI_Imax
79 #undef GCI_U
80 #undef GCI_Umax
81 #undef GCI_F
82 #undef GCI_Fmax
83 #undef GCI_max
86 * Determine the maximum size for each family.
88 #if defined(GCI_I_16)
89 # define GCI_I GCI_I_16
90 # define GCI_Imax 16
91 # define GCI_Im GCI_I_16m
92 # define GCI_IM GCI_I_16M
93 #elif defined(GCI_I_8)
94 # define GCI_I GCI_I_8
95 # define GCI_Imax 8
96 # define GCI_Im GCI_I_8m
97 # define GCI_IM GCI_I_8M
98 #else
99 # define GCI_I GCI_I_4
100 # define GCI_Imax 4
101 # define GCI_Im GCI_I_4m
102 # define GCI_IM GCI_I_4M
103 #endif
105 #if defined(GCI_U_16)
106 # define GCI_U GCI_U_16
107 # define GCI_Umax 16
108 # define GCI_UM GCI_U_16M
109 #elif defined(GCI_U_8)
110 # define GCI_U GCI_U_8
111 # define GCI_Umax 8
112 # define GCI_UM GCI_U_8M
113 #else
114 # define GCI_U GCI_U_4
115 # define GCI_Umax 4
116 # define GCI_UM GCI_U_4M
117 #endif
119 #if defined(GCI_F_16)
120 # define GCI_F GCI_F_16
121 # define GCI_Fmax 16
122 #elif defined(GCI_F_12)
123 # define GCI_F GCI_F_12
124 # define GCI_Fmax 12
125 #elif defined(GCI_F_10)
126 # define GCI_F GCI_F_10
127 # define GCI_Fmax 10
128 #elif defined(GCI_F_8)
129 # define GCI_F GCI_F_8
130 # define GCI_Fmax 8
131 #elif defined(GCI_F_4)
132 # define GCI_F GCI_F_4
133 # define GCI_Fmax 4
134 #else
135 # define GCI_Fmax 0
136 #endif
138 #if ( GCI_Imax >= GCI_Umax ) && ( GCI_Imax >= GCI_Fmax )
139 # define GCI_max GCI_Imax
140 #elif ( GCI_Umax >= GCI_Imax ) && ( GCI_Umax >= GCI_Fmax )
141 # define GCI_max GCI_Umax
142 #else
143 # define GCI_max GCI_Fmax
144 #endif
147 * Create a table for conversion functions. We know the maximum entry
148 * count now.
150 static struct {
151 GCI_result (*s2ifunc)( void *hidden, const char *str, int strsize,
152 void *target );
153 GCI_result (*s2ufunc)( void *hidden, const char *str, int strsize,
154 void *target );
155 GCI_result (*s2ffunc)( void *hidden, const char *str, int strsize,
156 void *target );
157 GCI_result (*i2sfunc)( void *hidden, const void *data, char *str,
158 int *strsize );
159 GCI_result (*u2sfunc)( void *hidden, const void *data, char *str,
160 int *strsize );
161 GCI_result (*f2sfunc)( void *hidden, const void *data, char *str,
162 int *strsize );
163 } functable[GCI_max+1] = {
164 {NULL, },
166 static int functable_assigned = 0;
168 #ifdef NEED_STRTOBIGL
169 static GCI_I strtobigl( void *hidden, const char *nptr, char **end, int base )
171 int neg = 0;
172 char *run = (char *) nptr;
173 GCI_I retval = 0;
175 (hidden = hidden);
177 assert( base == 10 );
179 while ( GCI_isspace( *run ) )
180 run++;
182 if ( *run == '-' )
184 neg = 1;
185 run++;
187 if ( !GCI_isdigit( *run ) )
189 *end = (char *) nptr;
190 return 0;
193 while ( GCI_isdigit( *run ) )
195 if ( neg )
197 if ( retval <= GCI_Im / 10 )
199 if ( retval == GCI_Im / 10 )
201 if ( (char ) -( GCI_Im - 10 * retval ) < ( *run - '0' ) )
203 retval = GCI_Im;
204 errno = ERANGE;
206 else
208 retval *= 10;
209 retval -= ( GCI_I ) ( *run - '0' );
212 else
214 retval = GCI_Im;
215 errno = ERANGE;
218 else
220 retval *= 10;
221 retval -= ( GCI_I ) ( *run - '0' );
224 else
226 if ( retval >= GCI_IM / 10 )
228 if ( retval == GCI_IM / 10 )
230 if ( (char ) ( GCI_IM - 10 * retval ) < ( *run - '0' ) )
232 retval = GCI_IM;
233 errno = ERANGE;
235 else
237 retval *= 10;
238 retval += ( GCI_I ) ( *run - '0' );
241 else
243 retval = GCI_IM;
244 errno = ERANGE;
247 else
249 retval *= 10;
250 retval += ( GCI_I ) ( *run - '0' );
253 run++;
256 *end = run;
258 return retval;
260 #endif
262 #ifdef NEED_STRTOBIGUL
263 static GCI_U strtobigul( void *hidden, const char *nptr, char **end, int base )
265 char *run = (char *) nptr;
266 GCI_U retval = 0;
268 (hidden = hidden);
270 assert( base == 10 );
272 while ( GCI_isspace( *run ) )
273 run++;
275 if ( !GCI_isdigit( *run ) )
277 *end = (char *) nptr;
278 return 0;
281 while ( GCI_isdigit( *run ) )
283 if ( retval >= GCI_UM / 10 )
285 if ( retval == GCI_UM / 10 )
287 if ( (char ) ( GCI_UM - 10 * retval ) < ( *run - '0' ) )
289 retval = GCI_UM;
290 errno = ERANGE;
292 else
294 retval *= 10;
295 retval += ( GCI_U ) ( *run - '0' );
298 else
300 retval = GCI_UM;
301 errno = ERANGE;
304 else
306 retval *= 10;
307 retval += ( GCI_U ) ( *run - '0' );
309 run++;
312 *end = run;
314 return retval;
316 #endif
318 #ifdef NEED_STRTOBIGF
319 static GCI_F strtobigf( const char *nptr, char **end )
321 char c;
322 GCI_F f;
323 int rc;
325 errno = 0;
326 rc = sscanf( nptr, F_SCAN " %c", &f, &c );
327 if ( rc <= 0 )
329 *end = (char *) nptr;
330 if ( !errno )
331 errno = ERANGE;
332 return f; /* pro forma */
335 if ( rc == 2 )
337 if ( ( *end = strrchr( nptr, c ) ) == NULL )
338 *end = (char *) nptr;
340 else
341 *end = (char *) nptr + strlen( nptr );
343 return f;
345 #endif
348 * preparenum chops off leading and trailing whitespaces from *str with the
349 * initial length of *size. Leading zeros will be cut off, too.
350 * *str and *size represent the final string after the stripping.
351 * A resulting length of 0 may occur only if the complete string contain
352 * whitespaces, only.
354 static void preparenum( void *hidden,
355 const char **str,
356 int *size )
358 const char *s = *str;
359 int len = *size;
361 (hidden = hidden);
364 * We prepare the number by hand and strip away blanks and useless zeros.
366 while ( len && GCI_isspace( *s ) )
368 s++;
369 len--;
371 if ( !len )
373 *size = 0;
374 return;
378 * We know from the previous test that at least one non-space exists.
380 while ( GCI_isspace( s[len - 1] ) )
382 len--;
386 * At least one non-space exist. Strip leading zeros; if no character
387 * remains, we have cut off one or more zeros. Undo one step then.
389 while ( len && ( *s == '0' ) )
391 s++;
392 len--;
394 if ( !len )
396 s--;
397 len = 1;
400 *str = s;
401 *size = len;
405 * iswhole returns 1 exactly if all characters in str are decimal digits,
406 * 0 otherwise.
408 static int iswhole( void *hidden,
409 const char *str,
410 int size )
412 (hidden = hidden);
414 while ( size && GCI_isdigit( *str ) )
416 str++;
417 size--;
419 return !size;
423 * string2int is the basic routine which implements GCI_Ir. size characters
424 * of str (not strongly 0-terminated) are converted and the number is placed
425 * in *retval.
427 * The string may contain garbage whitespace.
429 * The return code may be GCI_OK, GCI_WrongInput, GCI_NumberRange.
431 static GCI_result string2int( void *hidden,
432 const char *str,
433 int size,
434 GCI_I *retval )
436 char buf[80]; /* enough even for 256 bit numbers */
437 char *p;
438 int rc;
440 preparenum( hidden, &str, &size );
441 if ( !size || ( size > (int) sizeof( buf ) - 1 ) )
442 return GCI_WrongInput;
444 if ( ( *str == '-' ) || ( *str == '+' ) )
445 rc = iswhole( hidden, str + 1, size - 1 );
446 else
447 rc = iswhole( hidden, str, size );
448 if ( !rc )
449 return GCI_WrongInput;
451 memcpy( buf, str, size );
452 buf[size] = '\0';
455 * Carefully try to detect an overflow. We have to set errno for that
456 * cases where MAX_??? is given in str.
458 errno = 0;
459 *retval = GCI_Ir( buf, &p, 10 );
460 if ( ( *p != '\0' ) || errno )
461 return GCI_NumberRange;
463 return GCI_OK;
467 * int2string is the basic routine which implements GCI_Iw. bin is converted
468 * into a string which is placed into str. strsize must hold the buffer width
469 * of str and must be greater than 79.
471 * The return code will be GCI_OK.
473 * *strsize is set to the resulting length without the terminator.
475 static GCI_result int2string( void *hidden,
476 GCI_I bin,
477 char *str,
478 int *strsize )
480 (hidden = hidden);
481 assert( *strsize >= 80 );
483 *strsize = GCI_Iw( str, bin );
484 return GCI_OK;
488 * string2uint is the basic routine which implements GCI_Ur. size characters
489 * of str (not strongly 0-terminated) are converted and the number is placed
490 * in *retval.
492 * The string may contain garbage whitespace.
494 * The return code may be GCI_OK, GCI_WrongInput, GCI_NumberRange.
496 static GCI_result string2uint( void *hidden,
497 const char *str,
498 int size,
499 GCI_U *retval )
501 char buf[80]; /* enough even for 256 bit numbers */
502 char *p;
504 preparenum( hidden, &str, &size );
505 if ( !size ||
506 ( size > (int) sizeof( buf ) - 1 ) ||
507 !iswhole( hidden, str, size ) )
508 return GCI_WrongInput;
510 memcpy( buf, str, size );
511 buf[size] = '\0';
514 * Carefully try to detect an overflow. We have to set errno for that
515 * cases where MAX_??? is given in str.
517 errno = 0;
518 *retval = GCI_Ur( buf, &p, 10 );
519 if ( ( *p != '\0' ) || errno )
520 return GCI_NumberRange;
522 return GCI_OK;
526 * uint2string is the basic routine which implements GCI_Uw. bin is converted
527 * into a string which is placed into str. strsize must hold the buffer width
528 * of str and must be greater than 79.
530 * The return code will be GCI_OK.
532 * *strsize is set to the resulting length without the terminator.
534 static GCI_result uint2string( void *hidden,
535 GCI_U bin,
536 char *str,
537 int *strsize )
539 (hidden = hidden);
540 assert( *strsize >= 80 );
542 *strsize = GCI_Uw( str, bin );
543 return GCI_OK;
546 #ifdef GCI_F
548 * string2float is the basic routine which implements GCI_Fr. size characters
549 * of str (not strongly 0-terminated) are converted and the number is placed
550 * in *retval.
552 * The string may contain garbage whitespace.
554 * The return code may be GCI_OK, GCI_NoMemory, GCI_WrongInput,
555 * GCI_NumberRange.
557 static GCI_result string2float( void *hidden,
558 const char *str,
559 int size,
560 GCI_F *retval )
562 char *buf;
563 char *p;
565 (hidden = hidden);
566 preparenum( hidden, &str, &size );
567 if ( !size )
568 return GCI_WrongInput;
570 if ( ( buf = (char *) GCI_malloc( hidden, size + 1 ) ) == NULL )
571 return GCI_NoMemory;
573 memcpy( buf, str, size );
574 buf[size] = '\0';
577 * Carefully try to detect an overflow. We have to set errno for that
578 * cases where MAX_??? is given in str.
580 errno = 0;
581 *retval = GCI_Fr( buf, &p );
582 while ( GCI_isspace( *p ) )
583 p++;
585 if ( *p != '\0' )
587 GCI_free( hidden, buf );
588 return GCI_WrongInput;
591 if ( errno )
593 GCI_free( hidden, buf );
594 return GCI_NumberRange;
597 GCI_free( hidden, buf );
598 return GCI_OK;
602 * float2string is the basic routine which implements GCI_Uw. bin is converted
603 * into a string which is placed into str. *strsize must hold the buffer width
604 * of str and must be greater than 127.
606 * The return code will be GCI_OK or GCI_UnsupportedNumber if the generated
607 * number cannot be represented by digits (e.g. NaN).
609 * *strsize is set to the resulting length without the terminator.
611 static GCI_result float2string( void *hidden,
612 GCI_F bin,
613 char *str,
614 int *strsize )
616 (hidden = hidden);
617 assert( *strsize >= 128 );
619 *strsize = GCI_Fw( str, bin );
620 if ( ( *str == '-' ) || ( *str == '+' ) )
621 str++;
622 if ( !GCI_isdigit( *str ) )
623 return GCI_UnsupportedNumber;
624 return GCI_OK;
626 #endif /* ifdef GCI_F */
629 * We define a set of functions which bases on string2int and int2string.
630 * Each function will either convert to a smaller sized number or display a
631 * smaller sized number.
633 * usage: AUTOIFUNC(x) create the two functions s2ifuncx and i2sfuncx.
635 #define AUTOIFUNC(size) static GCI_result s2ifunc##size( void *hidden, \
636 const char *str, \
637 int strsize, \
638 void *target ) \
640 GCI_result rc; \
641 GCI_I val; \
642 if ( ( rc = string2int( hidden, str, strsize, &val ) ) != GCI_OK ) \
643 return rc; \
645 if ( ( (GCI_I) val < GCI_I_##size##m ) || \
646 ( (GCI_I) val > GCI_I_##size##M ) ) \
647 return GCI_NumberRange; \
649 *((GCI_I_##size *) target) = (GCI_I_##size) val; \
650 return GCI_OK; \
652 static GCI_result i2sfunc##size( void *hidden, \
653 const void *data, \
654 char *str, \
655 int *strsize) \
657 GCI_I val; \
658 val = (GCI_I) *( (GCI_I_##size *) data ); \
659 return int2string( hidden, val, str, strsize ); \
662 #ifdef GCI_I_1
663 AUTOIFUNC(1)
664 #endif
666 #ifdef GCI_I_2
667 AUTOIFUNC(2)
668 #endif
670 #ifdef GCI_I_4
671 AUTOIFUNC(4)
672 #endif
674 #ifdef GCI_I_8
675 AUTOIFUNC(8)
676 #endif
678 #ifdef GCI_I_16
679 AUTOIFUNC(16)
680 #endif
683 * We define a set of functions which bases on string2uint and uint2string.
684 * Each function will either convert to a smaller sized number or display a
685 * smaller sized number.
687 * usage: AUTOUFUNC(x) create the two functions s2ufuncx and u2sfuncx.
689 #define AUTOUFUNC(size) static GCI_result s2ufunc##size( void *hidden, \
690 const char *str, \
691 int strsize, \
692 void *target ) \
694 GCI_result rc; \
695 GCI_U val; \
696 if ( ( rc = string2uint( hidden, str, strsize, &val ) ) != GCI_OK ) \
697 return rc; \
699 if ( (GCI_U) val > GCI_U_##size##M ) \
700 return GCI_NumberRange; \
702 *((GCI_U_##size *) target) = (GCI_U_##size) val; \
703 return GCI_OK; \
705 static GCI_result u2sfunc##size( void *hidden, \
706 const void *data, \
707 char *str, \
708 int *strsize) \
710 GCI_U val; \
711 val = (GCI_U) *( (GCI_U_##size *) data ); \
712 return uint2string( hidden, val, str, strsize ); \
716 #ifdef GCI_U_1
717 AUTOUFUNC(1)
718 #endif
720 #ifdef GCI_U_2
721 AUTOUFUNC(2)
722 #endif
724 #ifdef GCI_U_4
725 AUTOUFUNC(4)
726 #endif
728 #ifdef GCI_U_8
729 AUTOUFUNC(8)
730 #endif
732 #ifdef GCI_U_16
733 AUTOUFUNC(16)
734 #endif
736 #ifdef GCI_F
738 * We define a set of functions which bases on string2float and float2string.
739 * Each function will either convert to a smaller sized number or display a
740 * smaller sized number.
742 * usage: AUTOFFUNC(x) create the two functions s2ffuncx and f2sfuncx.
744 #define AUTOFFUNC(size) static GCI_result s2ffunc##size( void *hidden, \
745 const char *str, \
746 int strsize, \
747 void *target ) \
749 GCI_result rc; \
750 GCI_F val; \
751 if ( ( rc = string2float( hidden, str, strsize, &val ) ) != GCI_OK ) \
752 return rc; \
754 if ( ( (GCI_F) val < GCI_F_##size##m ) || \
755 ( (GCI_F) val > GCI_F_##size##M ) ) \
756 return GCI_NumberRange; \
758 *((GCI_F_##size *) target) = (GCI_F_##size) val; \
759 return GCI_OK; \
761 static GCI_result f2sfunc##size( void *hidden, \
762 const void *data, \
763 char *str, \
764 int *strsize) \
766 GCI_F val; \
767 val = (GCI_F) *( (GCI_F_##size *) data ); \
768 return float2string( hidden, val, str, strsize ); \
771 #ifdef GCI_F_4
772 AUTOFFUNC(4)
773 #endif
775 #ifdef GCI_F_8
776 AUTOFFUNC(8)
777 #endif
779 #ifdef GCI_F_10
780 AUTOFFUNC(10)
781 #endif
783 #ifdef GCI_F_12
784 AUTOFFUNC(12)
785 #endif
787 #ifdef GCI_F_16
788 AUTOFFUNC(16)
789 #endif
790 #endif /* ifdef GCI_F */
793 * setup_functable initializes the functable table without setting illegal
794 * values.
795 * This allows simultaneous access without locking in multi-threading systems.
797 static void setup_functable( void )
799 int i;
801 if ( functable_assigned )
802 return;
804 for ( i = 0; i <= GCI_max; i++)
806 switch ( i )
808 case 1:
809 #ifdef GCI_I_1
810 functable[i].s2ifunc = s2ifunc1;
811 functable[i].i2sfunc = i2sfunc1;
812 #else
813 functable[i].s2ifunc = NULL;
814 functable[i].i2sfunc = NULL;
815 #endif
816 #ifdef GCI_U_1
817 functable[i].s2ufunc = s2ufunc1;
818 functable[i].u2sfunc = u2sfunc1;
819 #else
820 functable[i].s2ufunc = NULL;
821 functable[i].u2sfunc = NULL;
822 #endif
823 functable[i].s2ffunc = NULL;
824 functable[i].f2sfunc = NULL;
825 break;
827 case 2:
828 #ifdef GCI_I_2
829 functable[i].s2ifunc = s2ifunc2;
830 functable[i].i2sfunc = i2sfunc2;
831 #else
832 functable[i].s2ifunc = NULL;
833 functable[i].i2sfunc = NULL;
834 #endif
835 #ifdef GCI_U_2
836 functable[i].s2ufunc = s2ufunc2;
837 functable[i].u2sfunc = u2sfunc2;
838 #else
839 functable[i].s2ufunc = NULL;
840 functable[i].u2sfunc = NULL;
841 #endif
842 functable[i].s2ffunc = NULL;
843 functable[i].f2sfunc = NULL;
844 break;
846 case 4:
847 #ifdef GCI_I_4
848 functable[i].s2ifunc = s2ifunc4;
849 functable[i].i2sfunc = i2sfunc4;
850 #else
851 functable[i].s2ifunc = NULL;
852 functable[i].i2sfunc = NULL;
853 #endif
854 #ifdef GCI_U_4
855 functable[i].s2ufunc = s2ufunc4;
856 functable[i].u2sfunc = u2sfunc4;
857 #else
858 functable[i].s2ufunc = NULL;
859 functable[i].u2sfunc = NULL;
860 #endif
861 #ifdef GCI_F_4
862 functable[i].s2ffunc = s2ffunc4;
863 functable[i].f2sfunc = f2sfunc4;
864 #else
865 functable[i].s2ffunc = NULL;
866 functable[i].f2sfunc = NULL;
867 #endif
868 break;
870 case 8:
871 #ifdef GCI_I_8
872 functable[i].s2ifunc = s2ifunc8;
873 functable[i].i2sfunc = i2sfunc8;
874 #else
875 functable[i].s2ifunc = NULL;
876 functable[i].i2sfunc = NULL;
877 #endif
878 #ifdef GCI_U_8
879 functable[i].s2ufunc = s2ufunc8;
880 functable[i].u2sfunc = u2sfunc8;
881 #else
882 functable[i].s2ufunc = NULL;
883 functable[i].u2sfunc = NULL;
884 #endif
885 #ifdef GCI_F_8
886 functable[i].s2ffunc = s2ffunc8;
887 functable[i].f2sfunc = f2sfunc8;
888 #else
889 functable[i].s2ffunc = NULL;
890 functable[i].f2sfunc = NULL;
891 #endif
892 break;
894 case 10:
895 functable[i].s2ifunc = NULL;
896 functable[i].i2sfunc = NULL;
897 functable[i].s2ufunc = NULL;
898 functable[i].u2sfunc = NULL;
899 #ifdef GCI_F_10
900 functable[i].s2ffunc = s2ffunc10;
901 functable[i].f2sfunc = f2sfunc10;
902 #else
903 functable[i].s2ffunc = NULL;
904 functable[i].f2sfunc = NULL;
905 #endif
906 break;
908 case 12:
909 functable[i].s2ifunc = NULL;
910 functable[i].i2sfunc = NULL;
911 functable[i].s2ufunc = NULL;
912 functable[i].u2sfunc = NULL;
913 #ifdef GCI_F_12
914 functable[i].s2ffunc = s2ffunc12;
915 functable[i].f2sfunc = f2sfunc12;
916 #else
917 functable[i].s2ffunc = NULL;
918 functable[i].f2sfunc = NULL;
919 #endif
920 break;
922 case 16:
923 #ifdef GCI_I_16
924 functable[i].s2ifunc = s2ifunc16;
925 functable[i].i2sfunc = i2sfunc16;
926 #else
927 functable[i].s2ifunc = NULL;
928 functable[i].i2sfunc = NULL;
929 #endif
930 #ifdef GCI_U_16
931 functable[i].s2ufunc = s2ufunc16;
932 functable[i].u2sfunc = u2sfunc16;
933 #else
934 functable[i].s2ufunc = NULL;
935 functable[i].u2sfunc = NULL;
936 #endif
937 #ifdef GCI_F_16
938 functable[i].s2ffunc = s2ffunc16;
939 functable[i].f2sfunc = f2sfunc16;
940 #else
941 functable[i].s2ffunc = NULL;
942 functable[i].f2sfunc = NULL;
943 #endif
944 break;
946 default:
947 functable[i].s2ifunc = NULL;
948 functable[i].i2sfunc = NULL;
949 functable[i].s2ufunc = NULL;
950 functable[i].u2sfunc = NULL;
951 functable[i].s2ffunc = NULL;
952 functable[i].f2sfunc = NULL;
953 break;
957 functable_assigned = 1;
960 /*****************************************************************************
961 *****************************************************************************
962 ** GLOBAL FUNCTIONS *********************************************************
963 *****************************************************************************
964 *****************************************************************************/
967 * GCI_string2bin converts size characters of the not strongly 0-terminated
968 * string in str to a number.
969 * The desired datatype is taken from type. It must be GCI_integer,
970 * GCI_unsigned, GCI_float or GCI_char.
971 * destbyte contains the number of bytes of the desired type.
972 * Exactly destbyte bytes will be written to *dest on success. No checks for
973 * alignment errors are done.
975 * The return code may be
976 * GCI_OK Everything is perfect.
977 * GCI_NoMemory Out of memory when converting a floating point number.
978 * GCI_WrongInput Strange characters occur in the input string.
979 * GCI_NumberRange Number to small or big to fit into the desired type
980 * with the desired destbyte-size.
981 * GCI_UnsupportedType The combination of destbyte/type is unknown or not
982 * supported.
984 GCI_result GCI_string2bin( void *hidden,
985 const char *str,
986 int size,
987 void *dest,
988 int destbyte,
989 GCI_basetype type )
991 if ( !functable_assigned )
992 setup_functable();
994 if ( ( destbyte < 0 ) || ( destbyte >= (int) elements( functable ) ) )
995 return GCI_UnsupportedType;
997 switch ( type )
999 case GCI_integer:
1000 if ( functable[destbyte].s2ifunc == NULL )
1001 return GCI_UnsupportedType;
1002 return functable[destbyte].s2ifunc( hidden, str, size, dest );
1004 case GCI_unsigned:
1005 if ( functable[destbyte].s2ufunc == NULL )
1006 return GCI_UnsupportedType;
1007 return functable[destbyte].s2ufunc( hidden, str, size, dest );
1009 case GCI_float:
1010 if ( functable[destbyte].s2ffunc == NULL )
1011 return GCI_UnsupportedType;
1012 return functable[destbyte].s2ffunc( hidden, str, size, dest );
1014 case GCI_char:
1015 if ( destbyte != 1 )
1016 return GCI_UnsupportedType;
1017 if ( size != 1 )
1018 return GCI_WrongInput;
1019 *((char *) dest) = *str;
1020 return GCI_OK;
1022 default:
1023 break;
1025 return GCI_UnsupportedType;
1029 * GCI_bin2string converts size byte of base into a 0-terminated string with
1030 * a maximum target size of *strsize including the terminator.
1031 * The desired datatype is taken from type. It must be GCI_integer,
1032 * GCI_unsigned, GCI_float or GCI_char. GCI_string is not handled.
1033 * size contains the number of bytes of the desired type.
1034 * Exactly size bytes will be taken from *base. No checks for alignment errors
1035 * are done.
1036 * *strsize is set to the new size of the resulting string without the
1037 * terminator.
1039 * The return code may be
1040 * GCI_OK Everything is perfect.
1041 * GCI_UnsupportedNumber The floating point value in base is not a number
1042 * which can be displayed by digits (e.g. NaN).
1043 * GCI_BufferTooSmall The target buffer size strsize is less than 128.
1044 * GCI_UnsupportedType The combination of size/type is unknown or not
1045 * supported.
1047 GCI_result GCI_bin2string( void *hidden,
1048 const void *base,
1049 int size,
1050 char *str,
1051 int *strsize,
1052 GCI_basetype type )
1054 if ( !functable_assigned )
1055 setup_functable();
1057 if ( ( size < 0 ) || ( size >= (int) elements( functable ) ) )
1058 return GCI_UnsupportedType;
1060 if ( *strsize < 128 )
1061 return GCI_BufferTooSmall;
1063 switch ( type )
1065 case GCI_integer:
1066 if ( functable[size].i2sfunc == NULL )
1067 return GCI_UnsupportedType;
1068 return functable[size].i2sfunc( hidden, base, str, strsize );
1070 case GCI_unsigned:
1071 if ( functable[size].u2sfunc == NULL )
1072 return GCI_UnsupportedType;
1073 return functable[size].u2sfunc( hidden, base, str, strsize );
1075 case GCI_float:
1076 if ( functable[size].f2sfunc == NULL )
1077 return GCI_UnsupportedType;
1078 return functable[size].f2sfunc( hidden, base, str, strsize );
1080 case GCI_char:
1081 if ( size == 0 )
1082 return GCI_BufferTooSmall;
1083 if ( size > 1 )
1084 return GCI_UnsupportedType;
1085 str[0] = *((char *) base);
1086 str[1] = '\0';
1087 *strsize = 1;
1088 return GCI_OK;
1090 default:
1091 break;
1093 return GCI_UnsupportedType;
1097 * GCI_validate tests whether a specific type is supported by both conversion
1098 * routines. If basetype is set, an additional test is done for a base type.
1100 * The return code is
1101 * GCI_OK Everything is perfect.
1102 * GCI_UnsupportedType The combination of size/type is unknown or not
1103 * supported.
1104 * GCI_NoBaseType The type won't fit the requirements for basic types.
1106 GCI_result GCI_validate( int size,
1107 GCI_basetype type,
1108 int basetype )
1110 if ( !functable_assigned )
1111 setup_functable();
1113 if ( size < 0 )
1114 return GCI_UnsupportedType;
1116 if ( ( type == GCI_string ) ||
1117 ( type == GCI_raw ) ||
1118 ( type == GCI_container ) ||
1119 ( type == GCI_array ) )
1120 return ( basetype ) ? GCI_NoBaseType : GCI_OK;
1122 if ( size >= (int) elements( functable ) )
1123 return GCI_UnsupportedType;
1125 switch ( type )
1127 case GCI_integer:
1128 if ( ( functable[size].i2sfunc == NULL ) ||
1129 ( functable[size].s2ifunc == NULL ) )
1130 return GCI_UnsupportedType;
1131 return GCI_OK;
1133 case GCI_unsigned:
1134 if ( ( functable[size].u2sfunc == NULL ) ||
1135 ( functable[size].s2ufunc == NULL ) )
1136 return GCI_UnsupportedType;
1137 return GCI_OK;
1139 case GCI_float:
1140 if ( ( functable[size].f2sfunc == NULL ) ||
1141 ( functable[size].s2ffunc == NULL ) )
1142 return GCI_UnsupportedType;
1143 return GCI_OK;
1145 case GCI_char:
1146 if ( size != 1 ) /* we don't support unicode or other MBCS */
1147 return GCI_UnsupportedType;
1148 return GCI_OK;
1150 default:
1151 break;
1153 return GCI_UnsupportedType;