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