mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
parent
d68376f2ac
commit
a457542fb1
5 changed files with 138 additions and 3 deletions
|
|
@ -10,6 +10,7 @@ labwc_sources += files(
|
|||
'mem.c',
|
||||
'nodename.c',
|
||||
'parse-bool.c',
|
||||
'parse-double.c',
|
||||
'scaled_font_buffer.c',
|
||||
'scaled_scene_buffer.c',
|
||||
'scene-helpers.c',
|
||||
|
|
|
|||
99
src/common/parse-double.c
Normal file
99
src/common/parse-double.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/mem.h"
|
||||
#include "common/parse-double.h"
|
||||
|
||||
struct dec_separator {
|
||||
int index;
|
||||
bool multiple;
|
||||
};
|
||||
|
||||
struct converted_double {
|
||||
double value;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
static struct dec_separator
|
||||
find_dec_separator(const char *str)
|
||||
{
|
||||
struct dec_separator loc = {
|
||||
.index = -1,
|
||||
.multiple = false
|
||||
};
|
||||
|
||||
for (int i = 0; *str; i++, str++) {
|
||||
switch (*str) {
|
||||
case ',':
|
||||
case '.':
|
||||
if (loc.index >= 0) {
|
||||
loc.multiple = true;
|
||||
return loc;
|
||||
} else {
|
||||
loc.index = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
static struct converted_double
|
||||
convert_double(const char *str)
|
||||
{
|
||||
struct converted_double result = {
|
||||
.value = 0,
|
||||
.valid = true,
|
||||
};
|
||||
|
||||
char *eptr = NULL;
|
||||
|
||||
errno = 0;
|
||||
result.value = strtod(str, &eptr);
|
||||
|
||||
if (errno) {
|
||||
wlr_log(WLR_ERROR, "value '%s' is out of range", str);
|
||||
result.valid = false;
|
||||
}
|
||||
|
||||
if (*eptr) {
|
||||
wlr_log(WLR_ERROR, "value '%s' contains trailing garbage", str);
|
||||
result.valid = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
set_double(const char *str, double *val)
|
||||
{
|
||||
assert(str);
|
||||
assert(val);
|
||||
|
||||
struct dec_separator dloc = find_dec_separator(str);
|
||||
if (dloc.multiple) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"value '%s' contains multiple decimal markers", str);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *lstr = NULL;
|
||||
|
||||
if (dloc.index >= 0) {
|
||||
lstr = xstrdup(str);
|
||||
struct lconv *lc = localeconv();
|
||||
lstr[dloc.index] = *lc->decimal_point;
|
||||
str = lstr;
|
||||
}
|
||||
|
||||
struct converted_double conv = convert_double(str);
|
||||
if (conv.valid) {
|
||||
*val = conv.value;
|
||||
}
|
||||
|
||||
free(lstr);
|
||||
return conv.valid;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue