Просмотр исходного кода

utils: Add utils_strtod

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse 5 лет назад
Родитель
Сommit
b9685e4860
3 измененных файлов с 81 добавлено и 2 удалено
  1. 46 1
      qdevices/test-utils.c
  2. 31 0
      qdevices/utils.c
  3. 4 1
      qdevices/utils.h

+ 46 - 1
qdevices/test-utils.c

@@ -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);
 }

+ 31 - 0
qdevices/utils.c

@@ -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);
+}

+ 4 - 1
qdevices/utils.h

@@ -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