]> git.zerfleddert.de Git - proxmark3-svn/blob - client/jansson/strconv.c
Code improved for less memory
[proxmark3-svn] / client / jansson / strconv.c
1 #include <assert.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <math.h>
6 #ifdef __MINGW32__
7 #undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */
8 #endif
9 #include "jansson_private.h"
10 #include "strbuffer.h"
11
12 /* need jansson_private_config.h to get the correct snprintf */
13 #ifdef HAVE_CONFIG_H
14 #include <jansson_private_config.h>
15 #endif
16
17 #ifdef __MINGW32__
18 #define strtod __strtod
19 #endif
20
21 #if JSON_HAVE_LOCALECONV
22 #include <locale.h>
23
24 /*
25 - This code assumes that the decimal separator is exactly one
26 character.
27
28 - If setlocale() is called by another thread between the call to
29 localeconv() and the call to sprintf() or strtod(), the result may
30 be wrong. setlocale() is not thread-safe and should not be used
31 this way. Multi-threaded programs should use uselocale() instead.
32 */
33
34 static void to_locale(strbuffer_t *strbuffer)
35 {
36 const char *point;
37 char *pos;
38
39 point = localeconv()->decimal_point;
40 if(*point == '.') {
41 /* No conversion needed */
42 return;
43 }
44
45 pos = strchr(strbuffer->value, '.');
46 if(pos)
47 *pos = *point;
48 }
49
50 static void from_locale(char *buffer)
51 {
52 const char *point;
53 char *pos;
54
55 point = localeconv()->decimal_point;
56 if(*point == '.') {
57 /* No conversion needed */
58 return;
59 }
60
61 pos = strchr(buffer, *point);
62 if(pos)
63 *pos = '.';
64 }
65 #endif
66
67 int jsonp_strtod(strbuffer_t *strbuffer, double *out)
68 {
69 double value;
70 char *end;
71
72 #if JSON_HAVE_LOCALECONV
73 to_locale(strbuffer);
74 #endif
75
76 errno = 0;
77 value = strtod(strbuffer->value, &end);
78 assert(end == strbuffer->value + strbuffer->length);
79
80 if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
81 /* Overflow */
82 return -1;
83 }
84
85 *out = value;
86 return 0;
87 }
88
89 int jsonp_dtostr(char *buffer, size_t size, double value, int precision)
90 {
91 int ret;
92 char *start, *end;
93 size_t length;
94
95 if (precision == 0)
96 precision = 17;
97
98 ret = snprintf(buffer, size, "%.*g", precision, value);
99 if(ret < 0)
100 return -1;
101
102 length = (size_t)ret;
103 if(length >= size)
104 return -1;
105
106 #if JSON_HAVE_LOCALECONV
107 from_locale(buffer);
108 #endif
109
110 /* Make sure there's a dot or 'e' in the output. Otherwise
111 a real is converted to an integer when decoding */
112 if(strchr(buffer, '.') == NULL &&
113 strchr(buffer, 'e') == NULL)
114 {
115 if(length + 3 >= size) {
116 /* No space to append ".0" */
117 return -1;
118 }
119 buffer[length] = '.';
120 buffer[length + 1] = '0';
121 buffer[length + 2] = '\0';
122 length += 2;
123 }
124
125 /* Remove leading '+' from positive exponent. Also remove leading
126 zeros from exponents (added by some printf() implementations) */
127 start = strchr(buffer, 'e');
128 if(start) {
129 start++;
130 end = start + 1;
131
132 if(*start == '-')
133 start++;
134
135 while(*end == '0')
136 end++;
137
138 if(end != start) {
139 memmove(start, end, length - (size_t)(end - buffer));
140 length -= (size_t)(end - start);
141 }
142 }
143
144 return (int)length;
145 }
Impressum, Datenschutz