reactos/sdk/lib/crt/stdlib/ecvt.c
2021-06-11 15:33:08 +03:00

118 lines
2.2 KiB
C

/*
* PROJECT: ReactOS CRT
* LICENSE: See COPYING in the top level directory
* PURPOSE: CRT's ecvt
* FILE: lib/sdk/crt/stdlib/ecvt.c
* PROGRAMERS: Gregor Schneider (parts based on ecvtbuf.c by DJ Delorie)
*/
#include <precomp.h>
#define NUMBER_EFMT 18 /* sign, dot, null, 15 for alignment */
/*
* @implemented
*/
char *
_ecvt (double value, int ndigits, int *decpt, int *sign)
{
static char ecvtbuf[DBL_MAX_10_EXP + 10];
char *cvtbuf, *s, *d;
if (ndigits < 0) ndigits = 0;
s = cvtbuf = (char*)malloc(ndigits + NUMBER_EFMT);
d = ecvtbuf;
*sign = 0;
*decpt = 0;
if (cvtbuf == NULL)
{
return NULL;
}
sprintf(cvtbuf, "%-+.*E", ndigits, value);
/* Treat special values */
if (strncmp(s, "NaN", 3) == 0)
{
memcpy(ecvtbuf, s, 4);
}
else if (strncmp(s + 1, "Inf", 3) == 0)
{
memcpy(ecvtbuf, s, 5);
}
else
{
/* Set the sign */
if (*s && *s == '-')
{
*sign = 1;
}
s++;
/* Copy the first digit */
if (*s && *s != '.')
{
if (d - ecvtbuf < ndigits)
{
*d++ = *s++;
}
else
{
s++;
}
}
/* Skip the decimal point */
if (*s && *s == '.')
{
s++;
}
/* Copy fractional digits */
while (*s && *s != 'E')
{
if (d - ecvtbuf < ndigits)
{
*d++ = *s++;
}
else
{
s++;
}
}
/* Skip the exponent */
if (*s && *s == 'E')
{
s++;
}
/* Set the decimal point to the exponent value plus the one digit we copied */
*decpt = atoi(s) + 1;
/* Handle special decimal point cases */
if (cvtbuf[1] == '0')
{
*decpt = 0;
}
if (ndigits < 1)
{
/* Need enhanced precision*/
char* tbuf = (char*)malloc(NUMBER_EFMT);
if (tbuf == NULL)
{
free(cvtbuf);
return NULL;
}
sprintf(tbuf, "%-+.*E", ndigits + 2, value);
if (tbuf[1] >= '5')
{
(*decpt)++;
}
free(tbuf);
}
/* Pad with zeroes */
while (d - ecvtbuf < ndigits)
{
*d++ = '0';
}
/* Terminate */
*d = '\0';
}
free(cvtbuf);
return ecvtbuf;
}