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
*/
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
*/
#include "test-lib.h"
+#include <math.h>
#define INVALID(n) { #n, -1, 0 }
#define VALID(n) { #n, 0, n }
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");
test_str_to_u32();
test_str_to_llong();
test_str_to_i32();
+ test_str_to_float();
test_str_is_float();
}