-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathutilities.c
137 lines (111 loc) · 2.5 KB
/
utilities.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "libad9166-iio-config.h"
#include "utilities.h"
#if defined(_WIN32) || \
(defined(__APPLE__) && defined(__MACH__)) || \
(defined(__USE_XOPEN2K8) && \
(!defined(__UCLIBC__) || defined(__UCLIBC_HAS_LOCALE__)))
#define LOCALE_SUPPORT
#endif
#ifdef LOCALE_SUPPORT
#if defined(__MINGW32__) || (!defined(_WIN32) && !defined(HAS_NEWLOCALE))
static int read_double_locale(const char *str, double *val)
{
char *end, *old_locale;
double value;
bool problem = false;
/* XXX: This is not thread-safe, but it's the only way we have to
* support locales under MinGW without linking with Visual Studio
* libraries. */
old_locale = util_strdup(setlocale(LC_NUMERIC, NULL));
if (!old_locale)
return -ENOMEM;
setlocale(LC_NUMERIC, "C");
errno = 0;
value = strtod(str, &end);
if (end == str || errno == ERANGE)
problem = true;
setlocale(LC_NUMERIC, old_locale);
free(old_locale);
if (problem)
return -EINVAL;
*val = value;
return 0;
}
#elif defined(_WIN32)
static int read_double_locale(const char *str, double *val)
{
char *end;
double value;
bool problem = false;
_locale_t locale = _create_locale(LC_NUMERIC, "C");
if (!locale)
return -ENOMEM;
errno = 0;
value = _strtod_l(str, &end, locale);
if (end == str || errno == ERANGE)
problem = true;
_free_locale(locale);
if (problem)
return -EINVAL;
*val = value;
return 0;
}
#else
static int read_double_locale(const char *str, double *val)
{
char *end;
double value;
bool problem = false;
locale_t old_locale, new_locale;
new_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
if (!new_locale)
return -errno;
old_locale = uselocale(new_locale);
errno = 0;
value = strtod(str, &end);
if (end == str || errno == ERANGE)
problem = true;
uselocale(old_locale);
freelocale(new_locale);
if (problem)
return -EINVAL;
*val = value;
return 0;
}
#endif
#endif
int util_read_double(const char *str, double *val)
{
#ifdef LOCALE_SUPPORT
return read_double_locale(str, val);
#else
char *end;
double value;
errno = 0;
value = strtod(str, &end);
if (end == str || errno == ERANGE)
return -EINVAL;
*val = value;
return 0;
#endif
}
char *util_strdup(const char *str)
{
#if defined(_WIN32)
return _strdup(str);
#elif defined(HAS_STRDUP)
return strdup(str);
#else
size_t len = strlen(str);
char *buf = malloc(len + 1);
if (buf)
memcpy(buf, str, len + 1);
return buf;
#endif
}