Skip to content

Commit 465a968

Browse files
committedFeb 2, 2019
Parse number locale-independently
Previously we were using glibc's strtod function to parse floating point numbers. The problem is, strtod is locale dependent. Meaning 7,7 might be parsed as two numbers (7 and 7) in one locale, and parsed as one number (7 point 7) in another locale. This is undesirable. We need to set the locale to a value we know to make number parsing consistently. We could use setlocale(), but that is not thread-safe. We can also use uselocale(), which is thread-safe, but doesn't cover strtod (Yeah, some of the locale-aware functions only acknowledge the global locale, not the thread local one). So in frustration, I just wrote a simple floating point number parser myself. This parser obviously doesn't cover all cases strtod covers, but is good enough for our needs. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
1 parent 3f5a4d5 commit 465a968

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed
 

‎man/compton.1.asciidoc

+5-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,11 @@ OPTIONS
199199
WIDTH,HEIGHT,ELE1,ELE2,ELE3,ELE4,ELE5...
200200
----
201201
+
202-
The element in the center must not be included, it will be forever 1.0 or changing based on opacity, depending on whether you have `--blur-background-fixed`. Yet the automatic adjustment of blur factor may not work well with a custom blur kernel.
202+
In other words, the matrix is formatted as a list of comma separated numbers. The first two numbers must be integers, which specify the width and height of the matrix. They must be odd numbers. Then, the following 'width * height - 1' numbers specifies the numbers in the matrix, row by row, excluding the center element.
203+
+
204+
The elements are finite floating point numbers. The decimal pointer has to be '.' (a period), and scientific notation is not supported.
205+
+
206+
The element in the center will either be 1.0 or changing based on opacity, depending on whether you have `--blur-background-fixed`. Yet the automatic adjustment of blur factor may not work well with a custom blur kernel.
203207
+
204208
A 7x7 Gaussian blur kernel (sigma = 0.84089642) looks like:
205209
+

‎src/config.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ parse_long(const char *s, long *dest) {
4747
*/
4848
const char *
4949
parse_matrix_readnum(const char *src, double *dest) {
50-
char *pc = NULL;
51-
double val = strtod(src, &pc);
50+
const char *pc = NULL;
51+
double val = strtod_simple(src, &pc);
5252
if (!pc || pc == src) {
5353
log_error("No number found: %s", src);
5454
return src;

‎src/string_utils.c

+31
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,34 @@ void mstrextend(char **psrc1, const char *src2) {
4040
strncpy(*psrc1 + len1, src2, len2);
4141
(*psrc1)[len - 1] = '\0';
4242
}
43+
44+
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
45+
double strtod_simple(const char *src, const char **end) {
46+
double neg = 1;
47+
if (*src == '-') {
48+
neg = -1;
49+
src++;
50+
} else if (*src == '+') {
51+
src++;
52+
}
53+
54+
double ret = 0;
55+
while (*src >= '0' && *src <= '9') {
56+
ret = ret * 10 + (*src - '0');
57+
src++;
58+
}
59+
60+
if (*src == '.') {
61+
double frac = 0, mult = 0.1;
62+
src++;
63+
while (*src >= '0' && *src <= '9') {
64+
frac += mult * (*src - '0');
65+
mult *= 0.1;
66+
src++;
67+
}
68+
ret += frac;
69+
}
70+
71+
*end = src;
72+
return ret * neg;
73+
}

‎src/string_utils.h

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ char *
1111
mstrjoin3(const char *src1, const char *src2, const char *src3);
1212
void mstrextend(char **psrc1, const char *src2);
1313

14+
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
15+
double strtod_simple(const char *, const char **);
16+
1417
static inline int uitostr(unsigned int n, char *buf) {
1518
int ret = 0;
1619
unsigned int tmp = n;

0 commit comments

Comments
 (0)