utils: Add utils_strtod

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
This commit is contained in:
Jan Friesse 2020-11-09 15:09:01 +01:00
parent d99c195fc5
commit b9685e4860
3 changed files with 81 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2019 Red Hat, Inc.
* Copyright (c) 2015-2020 Red Hat, Inc.
*
* All rights reserved.
*
@ -35,6 +35,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include "utils.h"
@ -44,6 +45,8 @@ main(void)
{
long long int ll;
long long int lli;
double dbl;
double dbli;
char buf[32];
assert(utils_strtonum("0", 0, 100, &ll) == 0);
@ -92,5 +95,47 @@ main(void)
assert(utils_parse_bool_str("noo") == -1);
assert(utils_parse_bool_str("01") == -1);
assert(utils_strtod("0", 0, 100, &dbl) == 0);
assert(dbl == 0);
assert(utils_strtod("0.0", 0, 100, &dbl) == 0);
assert(dbl == 0);
assert(utils_strtod("100", 0, 100, &dbl) == 0);
assert(dbl == 100);
assert(utils_strtod("100.0", 0, 100, &dbl) == 0);
assert(dbl == 100);
assert(utils_strtod("99.9", 0, 100, &dbl) == 0);
assert(dbl == 99.9);
assert(utils_strtod("101", 0, 100, &dbl) != 0);
assert(utils_strtod("0", 1, 100, &dbl) != 0);
errno = ERANGE;
assert(utils_strtod("10", 0, 100, &dbl) == 0);
assert(dbl == 10);
assert(utils_strtod("-1", -1, 0, &dbl) == 0);
assert(dbl == -1);
assert(utils_strtod("-10", -20, -10, &dbl) == 0);
assert(dbl == -10);
assert(utils_strtod("0", 1, 0, &dbl) == -1);
for (dbli = -100; dbli <= 100; dbli += 0.01) {
assert(snprintf(buf, sizeof(buf), "%f", dbli) > 0);
assert(utils_strtod(buf, -100, 101, &dbl) == 0);
assert(fabs(dbl - dbli) < 0.0001);
}
assert(utils_strtod("test", -1000, 1000, &dbl) == -1);
assert(utils_strtod("12a", -1000, 1000, &dbl) == -1);
assert(utils_strtod("inf", -1000, 1000, &dbl) == -1);
assert(utils_strtod("nan", -1000, 1000, &dbl) == -1);
return (0);
}

View File

@ -42,6 +42,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -236,3 +237,33 @@ utils_strtonum(const char *str, long long int min_val, long long int max_val,
return (0);
}
/*
* Safer wrapper of strtod. Return 0 on success, otherwise -1.
*/
int
utils_strtod(const char *str, double min_val, double max_val,
double *res)
{
double tmp_d;
char *ep;
if (min_val > max_val) {
return (-1);
}
errno = 0;
tmp_d = strtod(str, &ep);
if (ep == str || *ep != '\0' || errno != 0) {
return (-1);
}
if (tmp_d < min_val || tmp_d > max_val || isnan(tmp_d)) {
return (-1);
}
*res = tmp_d;
return (0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2018 Red Hat, Inc.
* Copyright (c) 2015-2020 Red Hat, Inc.
*
* All rights reserved.
*
@ -65,6 +65,9 @@ extern int utils_fd_set_non_blocking(int fd);
extern int utils_strtonum(const char *str, long long int min_val,
long long int max_val, long long int *res);
extern int utils_strtod(const char *str, double min_val, double max_val,
double *res);
#ifdef __cplusplus
}
#endif