]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add str_to_float() and str_to_double()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 28 Feb 2022 21:33:09 +0000 (16:33 -0500)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 4 Mar 2022 06:57:51 +0000 (06:57 +0000)
src/lib/strnum.c
src/lib/strnum.h
src/lib/test-strnum.c

index 4b3da4a5f906e603c03e1697f2a28f555f88da42..d25f426d7dd448a91069cbc63a7f78ca49a01ef2 100644 (file)
@@ -446,6 +446,32 @@ int str_to_time(const char *str, time_t *num_r)
 
 STR_PARSE_U__TEMPLATE(str_parse_uoff, uoff_t)
 
+/*
+ * Floating point types
+ */
+
+int str_to_float(const char *str, float *num_r)
+{
+       char *endp;
+       float num = strtof(str, &endp);
+       if (*endp != '\0')
+               return -1;
+
+       *num_r = num;
+       return 0;
+}
+
+int str_to_double(const char *str, double *num_r)
+{
+       char *endp;
+       double num = strtod(str, &endp);
+       if (*endp != '\0')
+               return -1;
+
+       *num_r = num;
+       return 0;
+}
+
 /*
  * Error handling
  */
index 471d4aa3657f57182cb9792da79dc4b124d733e3..a46f955c6396e457a226c75aba5079affbb8edec 100644 (file)
@@ -172,6 +172,17 @@ int str_parse_uoff(const char *str, uoff_t *num_r,
 int str_to_time(const char *str, time_t *num_r)
        ATTR_WARN_UNUSED_RESULT;
 
+/*
+ * Floating point types
+ *
+ * Note: These use strto[fd](), which have locale-dependent behavior. However,
+ * Dovecot never calls setlocale(), so the locale is always C.
+ */
+int str_to_float(const char *str, float *num_r)
+       ATTR_WARN_UNUSED_RESULT;
+int str_to_double(const char *str, double *num_r)
+       ATTR_WARN_UNUSED_RESULT;
+
 /*
  * Utility
  */
index 892c579a184f993261fde38fe3fde85f3cfeb953..fff060615255261a366fce3def1e9bd46a050918 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "test-lib.h"
 
+#include <math.h>
 
 #define INVALID(n) { #n, -1, 0 }
 #define VALID(n) { #n, 0, n }
@@ -358,6 +359,39 @@ static void test_str_to_i32(void)
        test_end();
 }
 
+static void test_str_to_float(void)
+{
+       unsigned int i;
+       const struct {
+               const char *input;
+               int ret;
+               float val;
+       } tests[] = {
+               VALID(0.1),
+               VALID(0),
+               VALID(-0.1),
+               INVALID(--0),
+               INVALID(0.1x),
+               INVALID(0.1.2),
+               INVALID(bad),
+       };
+       test_begin("str_to_int");
+       for (i = 0; i < N_ELEMENTS(tests); ++i) {
+               float val = 1234.0;
+               double val2 = 1234.0;
+               int ret = str_to_float(tests[i].input, &val);
+               int ret2 = str_to_double(tests[i].input, &val2);
+               test_assert_idx(ret == tests[i].ret, i);
+               if (ret == 0)
+                       test_assert_idx(val == tests[i].val, i);
+               else
+                       test_assert_idx(val == 1234.0, i);
+               test_assert_idx(ret == ret2, i);
+               test_assert_idx(fabs(val-val2) < 0.000001, i);
+       }
+       test_end();
+}
+
 static void test_str_is_float(void)
 {
        test_begin("str_is_float accepts integer");
@@ -394,5 +428,6 @@ void test_strnum(void)
        test_str_to_u32();
        test_str_to_llong();
        test_str_to_i32();
+       test_str_to_float();
        test_str_is_float();
 }