forked from openresty/lua-cjson
-
Notifications
You must be signed in to change notification settings - Fork 4
/
g_fmt.c
111 lines (107 loc) · 2.42 KB
/
g_fmt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991, 1996 by Lucent Technologies.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
* it suffices to declare buf
* char buf[32];
*/
#ifdef __cplusplus
extern "C" {
#endif
extern char *dtoa(double, int, int, int *, int *, char **);
extern int g_fmt(char *, double, int);
extern void freedtoa(char*);
#ifdef __cplusplus
}
#endif
int
fpconv_g_fmt(char *b, double x, int precision)
{
register int i, k;
register char *s;
int decpt, j, sign;
char *b0, *s0, *se;
b0 = b;
#ifdef IGNORE_ZERO_SIGN
if (!x) {
*b++ = '0';
*b = 0;
goto done;
}
#endif
s = s0 = dtoa(x, 2, precision, &decpt, &sign, &se);
if (sign)
*b++ = '-';
if (decpt == 9999) /* Infinity or Nan */ {
while((*b++ = *s++));
/* "b" is used to calculate the return length. Decrement to exclude the
* Null terminator from the length */
b--;
goto done0;
}
if (decpt <= -4 || decpt > precision) {
*b++ = *s++;
if (*s) {
*b++ = '.';
while((*b = *s++))
b++;
}
*b++ = 'e';
/* sprintf(b, "%+.2d", decpt - 1); */
if (--decpt < 0) {
*b++ = '-';
decpt = -decpt;
}
else
*b++ = '+';
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
for(;;) {
i = decpt / k;
*b++ = i + '0';
if (--j <= 0)
break;
decpt -= i*k;
decpt *= 10;
}
*b = 0;
}
else if (decpt <= 0) {
*b++ = '0';
*b++ = '.';
for(; decpt < 0; decpt++)
*b++ = '0';
while((*b++ = *s++));
b--;
}
else {
while((*b = *s++)) {
b++;
if (--decpt == 0 && *s)
*b++ = '.';
}
for(; decpt > 0; decpt--)
*b++ = '0';
*b = 0;
}
done0:
freedtoa(s0);
#ifdef IGNORE_ZERO_SIGN
done:
#endif
return b - b0;
}