diff --git a/src/libCom/cvtFast.c b/src/libCom/cvtFast.c new file mode 100644 index 000000000..e22e9f005 --- /dev/null +++ b/src/libCom/cvtFast.c @@ -0,0 +1,752 @@ +/* cvtFast.h*/ +/* share/src/libCom @(#)cvtFast.c 1.2 1/12/93 */ +/* Very efficient routines to convert numbers to strings + * Author: Bob Dalesio wrote cvtFloatToString (called FF_TO_STR) + * Code is same for cvtDoubleToString + * Marty Kraimer wrote cvtCharToString,cvtUcharToString + * cvtShortToString,cvtUshortToString, + * cvtLongToString, and cvtUlongToString + * Mark Anderson wrote cvtLongToHexString, cvtLongToOctalString, + * adopted cvt[Float/Double]ExpString and + * cvt[Float/Double]CompactString from fToEStr + * and fixed calls to gcvt + * + * Date: 12 January 1993 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + * .01 mrk 12-09-92 Taken from dbAccess and made into library + * .02 mda 01-12-93 Add cvt[Float/Double]ToExpString, + * cvt[Float/Double]ToCompactString, + * cvtLongToHex, cvtLongToOctal routines, fix + * calls to gcvt, etc. + */ +#include +#include + +/* + * This routine converts numbers less than 10,000,000. It defers to f_to_str for + * numbers requiring more than 8 places of precision. There are only eight decimal + */ +static long frac_multiplier[] = + {1,10,100,1000,10000,100000,1000000,10000000,100000000}; + +int cvtFloatToString( + float flt_value, + char *pstr_value, + unsigned short precision) +{ + unsigned short got_one,i; + long whole,iplace,number,fraction,fplace; + float ftemp; + char *startAddr; + + /* can this routine handle this conversion */ + if (precision > 8 || precision < 0 || flt_value > 10000000.0) { + gcvt((double)flt_value,10,pstr_value); + return((int)strlen(pstr_value)); + /* gcvt from XPG2*/ + } + startAddr = pstr_value; + + /* determine the sign */ + if (flt_value < 0){ + *pstr_value++ = '-'; + flt_value = -flt_value; + }; + + /* remove the whole number portion */ + whole = flt_value; + ftemp = flt_value - whole; + + /* multiplier to convert fractional portion to integer */ + fplace = frac_multiplier[precision]; + fraction = ftemp * fplace * 10; + fraction = (fraction + 5) / 10; /* round up */ + + /* determine rounding into the whole number portion */ + if ((fraction / fplace) >= 1){ + whole++; + fraction -= fplace; + } + + /* whole numbers */ + got_one = 0; + for (iplace = 1000000; iplace >= 1; iplace /= 10){ + if (whole >= iplace){ + got_one = 1; + number = whole / iplace; + whole = whole - (number * iplace); + *pstr_value = number + '0'; + pstr_value++; + }else if (got_one){ + *pstr_value = '0'; + pstr_value++; + } + } + if (!got_one){ + *pstr_value = '0'; + pstr_value++; + } + + /* fraction */ + if (precision > 0){ + /* convert fractional portional to ASCII */ + *pstr_value = '.'; + pstr_value++; + for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){ + number = fraction / fplace; + fraction -= number * fplace; + *pstr_value = number + '0'; + pstr_value++; + } + } + *pstr_value = 0; + + return((int)(pstr_value - startAddr)); +} + + +int cvtDoubleToString( + double flt_value, + char *pstr_value, + unsigned short precision) +{ + unsigned short got_one,i; + long whole,iplace,number,fraction,fplace; + double ftemp; + char *startAddr; + + /* can this routine handle this conversion */ + if (precision > 8 || precision<0 || flt_value>10000000.0) { + gcvt((double)flt_value,10,pstr_value); + return((int)strlen(pstr_value)); + /* gcvt from XPG2*/ + } + startAddr = pstr_value; + + /* determine the sign */ + if (flt_value < 0){ + *pstr_value++ = '-'; + flt_value = -flt_value; + }; + + /* remove the whole number portion */ + whole = flt_value; + ftemp = flt_value - whole; + + /* multiplier to convert fractional portion to integer */ + fplace = frac_multiplier[precision]; + fraction = ftemp * fplace * 10; + fraction = (fraction + 5) / 10; /* round up */ + + /* determine rounding into the whole number portion */ + if ((fraction / fplace) >= 1){ + whole++; + fraction -= fplace; + } + + /* whole numbers */ + got_one = 0; + for (iplace = 1000000; iplace >= 1; iplace /= 10){ + if (whole >= iplace){ + got_one = 1; + number = whole / iplace; + whole = whole - (number * iplace); + *pstr_value = number + '0'; + pstr_value++; + }else if (got_one){ + *pstr_value = '0'; + pstr_value++; + } + } + if (!got_one){ + *pstr_value = '0'; + pstr_value++; + } + + /* fraction */ + if (precision > 0){ + /* convert fractional portional to ASCII */ + *pstr_value = '.'; + pstr_value++; + for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){ + number = fraction / fplace; + fraction -= number * fplace; + *pstr_value = number + '0'; + pstr_value++; + } + } + *pstr_value = 0; + + return((int)(pstr_value - startAddr)); +} + + + +/* + * cvtFloatToExpString + * + * converts floating point numbers to E-format NULL terminated strings + */ + +static float round_up[] = {.5, .05, .005,.0005,.00005,.000005,.0000005, + .00000005,.000000005,.0000000005,.00000000005,.000000000005, + .0000000000005,.00000000000005,.000000000000005,.0000000000000005}; + +int cvtFloatToExpString( + float f_value, + char *pstr_value, + unsigned short f_precision ) +{ + register float place,divisor; + register short e,i; + short number; + register float flt_value = f_value; + register unsigned short precision = f_precision; + char *startAddr; + + /* fix e_resolution to 1 */ +#define e_resolution 1 +#define MAX_OKAY_E_VALUE 1000000000000000.0 + + /* check upper bound, use sprintf if this routine can't handle it */ + if (f_value >= MAX_OKAY_E_VALUE || f_value <= -MAX_OKAY_E_VALUE){ + return(sprintf(pstr_value,"% 1.*e",f_precision,f_value)); + } + + startAddr = pstr_value; + + if (flt_value < 0){ + *pstr_value = '-'; + pstr_value++; + flt_value = -flt_value; + }else if (flt_value == 0.0){ + *pstr_value = '0'; + pstr_value++; + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + *pstr_value = '0'; + pstr_value++; + } + *pstr_value = 'e'; + pstr_value++; + *pstr_value = '+'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '\0'; + return(pstr_value - startAddr); + + } + + + /* determine which 3rd power of 10 to use */ + for (i=0,divisor=1; i= 1.0; place /= 10.0){ + if (flt_value >= place){ + number = flt_value / place; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + } + + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + number = flt_value / place ; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + + /* exponent portion */ + *pstr_value = 'e'; + pstr_value++; + if (e < 0){ + *pstr_value = '-'; + e = -e; + }else{ + *pstr_value = '+'; + } + pstr_value++; + number = e / 10; + *pstr_value = number + '0'; + pstr_value++; + e -= number * 10; + *pstr_value = e + '0'; + pstr_value++; + *pstr_value = 0; + + return(pstr_value - startAddr); +} + + + +/* + * cvtFloatToCompactString + * + * Converts floating point numbers to %g format NULL terminated strings, + * resulting in the most "compact" expression of the value + * ("f" notation if 10-4 < |value| < 10+4, otherwise "e" notation) + */ +int cvtFloatToCompactString( + float f_value, + char *pstr_value, + unsigned short f_precision ) +{ + if ((f_value < 1.e4 && f_value > 1.e-4) || + (f_value > -1.e4 && f_value < -1.e-4)) { + return(cvtFloatToString(f_value,pstr_value,f_precision)); + } else { + return(cvtFloatToExpString(f_value,pstr_value,f_precision)); + } +} + + + +/* + * cvtDoubleToExpString + * + * converts double precision floating point numbers to E-format NULL + * terminated strings + */ + +int cvtDoubleToExpString( + double f_value, + char *pstr_value, + unsigned short f_precision ) +{ + register float place,divisor; + register short e,i; + short number; + register double flt_value = f_value; + register unsigned short precision = f_precision; + char *startAddr; + + /* fix e_resolution to 1 */ +#define e_resolution 1 +#define MAX_OKAY_E_VALUE 1000000000000000.0 + + /* check upper bound, use sprintf if this routine can't handle it */ + if (f_value >= MAX_OKAY_E_VALUE || f_value <= -MAX_OKAY_E_VALUE){ + return(sprintf(pstr_value,"% 1.*e",f_precision,f_value)); + } + + startAddr = pstr_value; + + if (flt_value < 0){ + *pstr_value = '-'; + pstr_value++; + flt_value = -flt_value; + }else if (flt_value == 0.0){ + *pstr_value = '0'; + pstr_value++; + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + *pstr_value = '0'; + pstr_value++; + } + *pstr_value = 'e'; + pstr_value++; + *pstr_value = '+'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '\0'; + return(pstr_value - startAddr); + + } + + + /* determine which 3rd power of 10 to use */ + for (i=0,divisor=1; i= 1.0; place /= 10.0){ + if (flt_value >= place){ + number = flt_value / place; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + } + + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + number = flt_value / place ; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + + /* exponent portion */ + *pstr_value = 'e'; + pstr_value++; + if (e < 0){ + *pstr_value = '-'; + e = -e; + }else{ + *pstr_value = '+'; + } + pstr_value++; + number = e / 10; + *pstr_value = number + '0'; + pstr_value++; + e -= number * 10; + *pstr_value = e + '0'; + pstr_value++; + *pstr_value = 0; + + return(pstr_value - startAddr); +} + + + +/* + * cvtDoubleToCompactString + * + * Converts double precision floating point numbers to %g format NULL + * terminated strings, resulting in the most "compact" expression + * of the value ("f" notation if 10-4 < |value| < 10+4, otherwise + * "e" notation) + */ +int cvtDoubleToCompactString( + double f_value, + char *pstr_value, + unsigned short f_precision ) +{ + if ((f_value < 1.e4 && f_value > 1.e-4) || + (f_value > -1.e4 && f_value < -1.e-4)) { + return(cvtDoubleToString(f_value,pstr_value,f_precision)); + } else { + return(cvtDoubleToExpString(f_value,pstr_value,f_precision)); + } +} + + + + + +/* Convert various integer types to ascii */ + +static char digit_to_ascii[10]={'0','1','2','3','4','5','6','7','8','9'}; + +int cvtCharToString( + char source, + char *pdest) +{ + unsigned char val,temp; + char digit[3]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -128) { + strcpy(pdest,"128"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUcharToString( + unsigned char source, + char *pdest) +{ + unsigned char val,temp; + char digit[3]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtShortToString( + short source, + char *pdest) +{ + short val,temp; + char digit[6]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -32768) { + strcpy(pdest,"32768"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUshortToString( + unsigned short source, + char *pdest) +{ + unsigned short val,temp; + char digit[5]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtLongToString( + long source, + char *pdest) +{ + long val,temp; + char digit[11]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"2147483648"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUlongToString( + unsigned long source, + char *pdest) +{ + unsigned long val,temp; + char digit[10]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +/* Convert hex digits to ascii */ + +static char hex_digit_to_ascii[16]={'0','1','2','3','4','5','6','7','8','9', + 'a','b','c','d','e','f'}; + + +int cvtLongToHexString( + long source, + char *pdest) +{ + long val,temp; + char digit[10]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"80000000"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/16; + digit[i] = hex_digit_to_ascii[val - temp*16]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtLongToOctalString( + long source, + char *pdest) +{ + long val,temp; + char digit[16]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"20000000000"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/8; + /* reuse digit_to_ascii since octal is a subset of decimal */ + digit[i] = digit_to_ascii[val - temp*8]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} diff --git a/src/libCom/cvtFast/cvtFast.c b/src/libCom/cvtFast/cvtFast.c new file mode 100644 index 000000000..e22e9f005 --- /dev/null +++ b/src/libCom/cvtFast/cvtFast.c @@ -0,0 +1,752 @@ +/* cvtFast.h*/ +/* share/src/libCom @(#)cvtFast.c 1.2 1/12/93 */ +/* Very efficient routines to convert numbers to strings + * Author: Bob Dalesio wrote cvtFloatToString (called FF_TO_STR) + * Code is same for cvtDoubleToString + * Marty Kraimer wrote cvtCharToString,cvtUcharToString + * cvtShortToString,cvtUshortToString, + * cvtLongToString, and cvtUlongToString + * Mark Anderson wrote cvtLongToHexString, cvtLongToOctalString, + * adopted cvt[Float/Double]ExpString and + * cvt[Float/Double]CompactString from fToEStr + * and fixed calls to gcvt + * + * Date: 12 January 1993 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + * .01 mrk 12-09-92 Taken from dbAccess and made into library + * .02 mda 01-12-93 Add cvt[Float/Double]ToExpString, + * cvt[Float/Double]ToCompactString, + * cvtLongToHex, cvtLongToOctal routines, fix + * calls to gcvt, etc. + */ +#include +#include + +/* + * This routine converts numbers less than 10,000,000. It defers to f_to_str for + * numbers requiring more than 8 places of precision. There are only eight decimal + */ +static long frac_multiplier[] = + {1,10,100,1000,10000,100000,1000000,10000000,100000000}; + +int cvtFloatToString( + float flt_value, + char *pstr_value, + unsigned short precision) +{ + unsigned short got_one,i; + long whole,iplace,number,fraction,fplace; + float ftemp; + char *startAddr; + + /* can this routine handle this conversion */ + if (precision > 8 || precision < 0 || flt_value > 10000000.0) { + gcvt((double)flt_value,10,pstr_value); + return((int)strlen(pstr_value)); + /* gcvt from XPG2*/ + } + startAddr = pstr_value; + + /* determine the sign */ + if (flt_value < 0){ + *pstr_value++ = '-'; + flt_value = -flt_value; + }; + + /* remove the whole number portion */ + whole = flt_value; + ftemp = flt_value - whole; + + /* multiplier to convert fractional portion to integer */ + fplace = frac_multiplier[precision]; + fraction = ftemp * fplace * 10; + fraction = (fraction + 5) / 10; /* round up */ + + /* determine rounding into the whole number portion */ + if ((fraction / fplace) >= 1){ + whole++; + fraction -= fplace; + } + + /* whole numbers */ + got_one = 0; + for (iplace = 1000000; iplace >= 1; iplace /= 10){ + if (whole >= iplace){ + got_one = 1; + number = whole / iplace; + whole = whole - (number * iplace); + *pstr_value = number + '0'; + pstr_value++; + }else if (got_one){ + *pstr_value = '0'; + pstr_value++; + } + } + if (!got_one){ + *pstr_value = '0'; + pstr_value++; + } + + /* fraction */ + if (precision > 0){ + /* convert fractional portional to ASCII */ + *pstr_value = '.'; + pstr_value++; + for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){ + number = fraction / fplace; + fraction -= number * fplace; + *pstr_value = number + '0'; + pstr_value++; + } + } + *pstr_value = 0; + + return((int)(pstr_value - startAddr)); +} + + +int cvtDoubleToString( + double flt_value, + char *pstr_value, + unsigned short precision) +{ + unsigned short got_one,i; + long whole,iplace,number,fraction,fplace; + double ftemp; + char *startAddr; + + /* can this routine handle this conversion */ + if (precision > 8 || precision<0 || flt_value>10000000.0) { + gcvt((double)flt_value,10,pstr_value); + return((int)strlen(pstr_value)); + /* gcvt from XPG2*/ + } + startAddr = pstr_value; + + /* determine the sign */ + if (flt_value < 0){ + *pstr_value++ = '-'; + flt_value = -flt_value; + }; + + /* remove the whole number portion */ + whole = flt_value; + ftemp = flt_value - whole; + + /* multiplier to convert fractional portion to integer */ + fplace = frac_multiplier[precision]; + fraction = ftemp * fplace * 10; + fraction = (fraction + 5) / 10; /* round up */ + + /* determine rounding into the whole number portion */ + if ((fraction / fplace) >= 1){ + whole++; + fraction -= fplace; + } + + /* whole numbers */ + got_one = 0; + for (iplace = 1000000; iplace >= 1; iplace /= 10){ + if (whole >= iplace){ + got_one = 1; + number = whole / iplace; + whole = whole - (number * iplace); + *pstr_value = number + '0'; + pstr_value++; + }else if (got_one){ + *pstr_value = '0'; + pstr_value++; + } + } + if (!got_one){ + *pstr_value = '0'; + pstr_value++; + } + + /* fraction */ + if (precision > 0){ + /* convert fractional portional to ASCII */ + *pstr_value = '.'; + pstr_value++; + for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){ + number = fraction / fplace; + fraction -= number * fplace; + *pstr_value = number + '0'; + pstr_value++; + } + } + *pstr_value = 0; + + return((int)(pstr_value - startAddr)); +} + + + +/* + * cvtFloatToExpString + * + * converts floating point numbers to E-format NULL terminated strings + */ + +static float round_up[] = {.5, .05, .005,.0005,.00005,.000005,.0000005, + .00000005,.000000005,.0000000005,.00000000005,.000000000005, + .0000000000005,.00000000000005,.000000000000005,.0000000000000005}; + +int cvtFloatToExpString( + float f_value, + char *pstr_value, + unsigned short f_precision ) +{ + register float place,divisor; + register short e,i; + short number; + register float flt_value = f_value; + register unsigned short precision = f_precision; + char *startAddr; + + /* fix e_resolution to 1 */ +#define e_resolution 1 +#define MAX_OKAY_E_VALUE 1000000000000000.0 + + /* check upper bound, use sprintf if this routine can't handle it */ + if (f_value >= MAX_OKAY_E_VALUE || f_value <= -MAX_OKAY_E_VALUE){ + return(sprintf(pstr_value,"% 1.*e",f_precision,f_value)); + } + + startAddr = pstr_value; + + if (flt_value < 0){ + *pstr_value = '-'; + pstr_value++; + flt_value = -flt_value; + }else if (flt_value == 0.0){ + *pstr_value = '0'; + pstr_value++; + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + *pstr_value = '0'; + pstr_value++; + } + *pstr_value = 'e'; + pstr_value++; + *pstr_value = '+'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '\0'; + return(pstr_value - startAddr); + + } + + + /* determine which 3rd power of 10 to use */ + for (i=0,divisor=1; i= 1.0; place /= 10.0){ + if (flt_value >= place){ + number = flt_value / place; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + } + + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + number = flt_value / place ; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + + /* exponent portion */ + *pstr_value = 'e'; + pstr_value++; + if (e < 0){ + *pstr_value = '-'; + e = -e; + }else{ + *pstr_value = '+'; + } + pstr_value++; + number = e / 10; + *pstr_value = number + '0'; + pstr_value++; + e -= number * 10; + *pstr_value = e + '0'; + pstr_value++; + *pstr_value = 0; + + return(pstr_value - startAddr); +} + + + +/* + * cvtFloatToCompactString + * + * Converts floating point numbers to %g format NULL terminated strings, + * resulting in the most "compact" expression of the value + * ("f" notation if 10-4 < |value| < 10+4, otherwise "e" notation) + */ +int cvtFloatToCompactString( + float f_value, + char *pstr_value, + unsigned short f_precision ) +{ + if ((f_value < 1.e4 && f_value > 1.e-4) || + (f_value > -1.e4 && f_value < -1.e-4)) { + return(cvtFloatToString(f_value,pstr_value,f_precision)); + } else { + return(cvtFloatToExpString(f_value,pstr_value,f_precision)); + } +} + + + +/* + * cvtDoubleToExpString + * + * converts double precision floating point numbers to E-format NULL + * terminated strings + */ + +int cvtDoubleToExpString( + double f_value, + char *pstr_value, + unsigned short f_precision ) +{ + register float place,divisor; + register short e,i; + short number; + register double flt_value = f_value; + register unsigned short precision = f_precision; + char *startAddr; + + /* fix e_resolution to 1 */ +#define e_resolution 1 +#define MAX_OKAY_E_VALUE 1000000000000000.0 + + /* check upper bound, use sprintf if this routine can't handle it */ + if (f_value >= MAX_OKAY_E_VALUE || f_value <= -MAX_OKAY_E_VALUE){ + return(sprintf(pstr_value,"% 1.*e",f_precision,f_value)); + } + + startAddr = pstr_value; + + if (flt_value < 0){ + *pstr_value = '-'; + pstr_value++; + flt_value = -flt_value; + }else if (flt_value == 0.0){ + *pstr_value = '0'; + pstr_value++; + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + *pstr_value = '0'; + pstr_value++; + } + *pstr_value = 'e'; + pstr_value++; + *pstr_value = '+'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '0'; + pstr_value++; + *pstr_value = '\0'; + return(pstr_value - startAddr); + + } + + + /* determine which 3rd power of 10 to use */ + for (i=0,divisor=1; i= 1.0; place /= 10.0){ + if (flt_value >= place){ + number = flt_value / place; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + } + + /* fraction */ + *pstr_value = '.'; + pstr_value++; + for (place = .1; precision > 0; place /= 10.0, precision--){ + number = flt_value / place ; + flt_value = flt_value - (number * place); + *pstr_value = number + '0'; + pstr_value++; + } + + /* exponent portion */ + *pstr_value = 'e'; + pstr_value++; + if (e < 0){ + *pstr_value = '-'; + e = -e; + }else{ + *pstr_value = '+'; + } + pstr_value++; + number = e / 10; + *pstr_value = number + '0'; + pstr_value++; + e -= number * 10; + *pstr_value = e + '0'; + pstr_value++; + *pstr_value = 0; + + return(pstr_value - startAddr); +} + + + +/* + * cvtDoubleToCompactString + * + * Converts double precision floating point numbers to %g format NULL + * terminated strings, resulting in the most "compact" expression + * of the value ("f" notation if 10-4 < |value| < 10+4, otherwise + * "e" notation) + */ +int cvtDoubleToCompactString( + double f_value, + char *pstr_value, + unsigned short f_precision ) +{ + if ((f_value < 1.e4 && f_value > 1.e-4) || + (f_value > -1.e4 && f_value < -1.e-4)) { + return(cvtDoubleToString(f_value,pstr_value,f_precision)); + } else { + return(cvtDoubleToExpString(f_value,pstr_value,f_precision)); + } +} + + + + + +/* Convert various integer types to ascii */ + +static char digit_to_ascii[10]={'0','1','2','3','4','5','6','7','8','9'}; + +int cvtCharToString( + char source, + char *pdest) +{ + unsigned char val,temp; + char digit[3]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -128) { + strcpy(pdest,"128"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUcharToString( + unsigned char source, + char *pdest) +{ + unsigned char val,temp; + char digit[3]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtShortToString( + short source, + char *pdest) +{ + short val,temp; + char digit[6]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -32768) { + strcpy(pdest,"32768"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUshortToString( + unsigned short source, + char *pdest) +{ + unsigned short val,temp; + char digit[5]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtLongToString( + long source, + char *pdest) +{ + long val,temp; + char digit[11]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"2147483648"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtUlongToString( + unsigned long source, + char *pdest) +{ + unsigned long val,temp; + char digit[10]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + val = source; + for(i=0; val!=0; i++) { + temp = val/10; + digit[i] = digit_to_ascii[val - temp*10]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +/* Convert hex digits to ascii */ + +static char hex_digit_to_ascii[16]={'0','1','2','3','4','5','6','7','8','9', + 'a','b','c','d','e','f'}; + + +int cvtLongToHexString( + long source, + char *pdest) +{ + long val,temp; + char digit[10]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"80000000"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/16; + digit[i] = hex_digit_to_ascii[val - temp*16]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +} + + +int cvtLongToOctalString( + long source, + char *pdest) +{ + long val,temp; + char digit[16]; + int i,j; + char *startAddr = pdest; + + if(source==0) { + *pdest++ = '0'; + *pdest = 0; + return((int)(pdest-startAddr)); + } + if(source<0) { + *pdest++ = '-'; + if(source == -2147483648) { + strcpy(pdest,"20000000000"); + return((int)(pdest-startAddr)); + } + source = -source; + } + val = source; + for(i=0; val!=0; i++) { + temp = val/8; + /* reuse digit_to_ascii since octal is a subset of decimal */ + digit[i] = digit_to_ascii[val - temp*8]; + val = temp; + } + for(j=i-1; j>=0; j--) { + *pdest++ = digit[j]; + } + *pdest = 0; + return((int)(pdest-startAddr)); +}