4coder-non-source/test_data/lots_of_files/xwstoflt.c

110 lines
3.1 KiB
C
Raw Normal View History

2023-09-30 01:17:40 +00:00
/* _WStoflt function */
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
#include "xmath.h"
_C_STD_BEGIN
#if !defined(MRTDLL)
_C_LIB_DECL
#endif /* defined(MRTDLL) */
#define BASE 10 /* decimal */
#define NDIG 9 /* decimal digits per long element */
#define MAXSIG (5 * NDIG) /* maximum significant digits to keep */
_CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _WStoflt(const wchar_t *s0, const wchar_t *s,
wchar_t **endptr, long lo[], int maxsig)
{ /* convert wide string to array of long plus exponent */
char buf[MAXSIG + 1]; /* worst case, with room for rounding digit */
int nsig; /* number of significant digits seen */
int seen; /* any valid field characters seen */
int word = 0; /* current long word to fill */
maxsig *= NDIG; /* convert word count to digit count */
if (MAXSIG < maxsig)
maxsig = MAXSIG; /* protect against bad call */
lo[0] = 0; /* power of ten exponent */
lo[1] = 0; /* first NDIG-digit word of fraction */
for (seen = 0; *s == L'0'; ++s, seen = 1)
; /* strip leading zeros */
for (nsig = 0; iswdigit(*s); ++s, seen = 1)
if (nsig <= maxsig)
buf[nsig++] = (char)(*s - L'0'); /* accumulate a digit */
else
++lo[0]; /* too many digits, just scale exponent */
if (*s == btowc(localeconv()->decimal_point[0]))
++s;
if (nsig == 0)
for (; *s == L'0'; ++s, seen = 1)
--lo[0]; /* scale for stripped zeros after point */
for (; iswdigit(*s); ++s, seen = 1)
if (nsig <= maxsig)
{ /* accumulate a fraction digit */
buf[nsig++] = (char)(*s - L'0');
--lo[0];
}
if (maxsig < nsig)
{ /* discard excess digit after rounding up */
unsigned int ms = maxsig; /* to quiet warnings */
if (BASE / 2 <= buf[ms])
++buf[ms - 1]; /* okay if digit becomes BASE */
nsig = maxsig;
++lo[0];
}
for (; 0 < nsig && buf[nsig - 1] == '\0'; --nsig)
++lo[0]; /* discard trailing zeros */
if (nsig == 0)
buf[nsig++] = '\0'; /* ensure at least one digit */
if (seen)
{ /* convert digit sequence to words */
int bufidx = 0; /* next digit in buffer */
int wordidx = NDIG - nsig % NDIG; /* next digit in word (% NDIG) */
word = wordidx % NDIG == 0 ? 0 : 1;
for (; bufidx < nsig; ++wordidx, ++bufidx)
if (wordidx % NDIG == 0)
lo[++word] = buf[bufidx];
else
lo[word] = lo[word] * BASE + buf[bufidx];
if (*s == L'e' || *s == L'E')
{ /* parse exponent */
const wchar_t *ssav = s;
const wchar_t esign = *++s == L'+' || *s == L'-'
? *s++ : L'+';
int eseen = 0;
long lexp = 0;
for (; iswdigit(*s); ++s, eseen = 1)
if (lexp < 100000000) /* else overflow */
lexp = lexp * 10 + *s - L'0';
if (esign == L'-')
lexp = -lexp;
lo[0] += lexp;
if (!eseen)
s = ssav; /* roll back if incomplete exponent */
}
}
if (!seen)
word = 0; /* return zero if bad parse */
if (endptr)
*endptr = (wchar_t *)(seen ? s : s0); /* roll back if bad parse */
return (word);
}
#if !defined(MRTDLL)
_END_C_LIB_DECL
#endif /* !defined(MRTDLL) */
_C_STD_END
/*
* Copyright (c) 1992-2012 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V6.00:0009 */