d7e48db80bc72d96601e0f508417224f66dfb13d
[reactos.git] / reactos / lib / sdk / crt / stdlib / ecvt.c
1 /*
2 * PROJECT: ReactOS CRT
3 * LICENSE: See COPYING in the top level directory
4 * PURPOSE: CRT's ecvt
5 * FILE: lib/sdk/crt/stdlib/ecvt.c
6 * PROGRAMERS: Gregor Schneider (parts based on ecvtbuf.c by DJ Delorie)
7 */
8
9 #include <precomp.h>
10
11 /*
12 * @implemented
13 */
14 char *
15 _ecvt (double value, int ndigits, int *decpt, int *sign)
16 {
17 char *ecvtbuf, *cvtbuf;
18 char *s, *d;
19
20 s = cvtbuf = (char*)malloc(ndigits + 18); /* sign, dot, null, 15 for alignment */
21 d = ecvtbuf = (char*)malloc(DBL_MAX_10_EXP + 10);
22
23 *sign = 0;
24 *decpt = 0;
25
26 if (cvtbuf == NULL || ecvtbuf == NULL)
27 {
28 return NULL;
29 }
30
31 sprintf(cvtbuf, "%-+.*E", ndigits, value);
32 /* Treat special values */
33 if (strncmp(s, "NaN", 3) == 0)
34 {
35 memcpy(ecvtbuf, s, 4);
36 }
37 else if (strncmp(s + 1, "Inf", 3) == 0)
38 {
39 memcpy(ecvtbuf, s, 5);
40 }
41 else
42 {
43 /* Set the sign */
44 if (*s && *s == '-')
45 {
46 *sign = 1;
47 }
48 s++;
49 /* Copy the first digit */
50 if (*s && *s != '.')
51 {
52 if (d - ecvtbuf < ndigits)
53 {
54 *d++ = *s++;
55 }
56 else
57 {
58 s++;
59 }
60 }
61 /* Skip the decimal point */
62 if (*s && *s == '.')
63 {
64 s++;
65 }
66 /* Copy fractional digits */
67 while (*s && *s != 'E')
68 {
69 if (d - ecvtbuf < ndigits)
70 {
71 *d++ = *s++;
72 }
73 else
74 {
75 s++;
76 }
77 }
78 /* Skip the exponent */
79 if (*s && *s == 'E')
80 {
81 s++;
82 }
83 /* Set the decimal point to the exponent value plus the one digit we copied */
84 *decpt = atoi(s) + 1;
85 /* Handle special decimal point cases */
86 if (cvtbuf[1] == '0')
87 {
88 *decpt = 0;
89 }
90 if (ndigits < 1)
91 {
92 /* Need enhanced precision*/
93 char* tbuf = (char*)malloc(ndigits + 18);
94 sprintf(tbuf, "%-+.*E", ndigits + 2, value);
95 if (tbuf[1] >= '5')
96 {
97 (*decpt)++;
98 }
99 free(tbuf);
100 }
101 /* Pad with zeroes */
102 while (d - ecvtbuf < ndigits)
103 {
104 *d++ = '0';
105 }
106 /* Terminate */
107 *d = '\0';
108 }
109 free(cvtbuf);
110 return ecvtbuf;
111 }