]> git.ipfire.org Git - thirdparty/git.git/commitdiff
config: introduce `git_config_double()`
authorTaylor Blau <me@ttaylorr.com>
Thu, 23 May 2024 21:26:39 +0000 (17:26 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 24 May 2024 18:40:42 +0000 (11:40 -0700)
Future commits will want to parse a double-precision floating point
value from configuration, but we have no way to parse such a value prior
to this patch.

The core of the routine is implemented in git_parse_double(). Unlike
git_parse_unsigned() and git_parse_signed(), however, the function
implemented here only works on type "double", and not related types like
"float", or "long double".

This is because "float" and "long double" use different functions to
convert from ASCII strings to floating point values (strtof() and
strtold(), respectively). Likewise, there is no pointer type that can
assign to any of these values (except for "void *"), so the only way to
define this trio of functions would be with a macro expansion that is
parameterized over the floating point type and conversion function.

That is all doable, but likely to be overkill given our current needs,
which is only to parse double-precision floats.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
config.c
config.h
parse.c
parse.h

index ae3652b08fa6f36af6c085e36b89efdd46d72389..8a8332617f80802929d86b661ae12f9599c1fad2 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1243,6 +1243,15 @@ ssize_t git_config_ssize_t(const char *name, const char *value,
        return ret;
 }
 
+double git_config_double(const char *name, const char *value,
+                        const struct key_value_info *kvi)
+{
+       double ret;
+       if (!git_parse_double(value, &ret))
+               die_bad_number(name, value, kvi);
+       return ret;
+}
+
 static const struct fsync_component_name {
        const char *name;
        enum fsync_component component_bits;
index f4966e374948a59cbe95af6f999f0e70d44aa1e9..f5f306f373d0a745e82b86abf35f0b054e8a8ef9 100644 (file)
--- a/config.h
+++ b/config.h
@@ -261,6 +261,13 @@ unsigned long git_config_ulong(const char *, const char *,
 ssize_t git_config_ssize_t(const char *, const char *,
                           const struct key_value_info *);
 
+/**
+ * Identically to `git_config_double`, but for double-precision floating point
+ * values.
+ */
+double git_config_double(const char *, const char *,
+                        const struct key_value_info *);
+
 /**
  * Same as `git_config_bool`, except that integers are returned as-is, and
  * an `is_bool` flag is unset.
diff --git a/parse.c b/parse.c
index 42d691a0fbb42d62a9f8c1aa7f9cd5033dcb464a..7a60a4f816c3e4f7d473403d6229f6747b3307bb 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -125,6 +125,35 @@ int git_parse_ssize_t(const char *value, ssize_t *ret)
        return 1;
 }
 
+int git_parse_double(const char *value, double *ret)
+{
+       char *end;
+       double val;
+       uintmax_t factor;
+
+       if (!value || !*value) {
+               errno = EINVAL;
+               return 0;
+       }
+
+       errno = 0;
+       val = strtod(value, &end);
+       if (errno == ERANGE)
+               return 0;
+       if (end == value) {
+               errno = EINVAL;
+               return 0;
+       }
+       factor = get_unit_factor(end);
+       if (!factor) {
+               errno = EINVAL;
+               return 0;
+       }
+       val *= factor;
+       *ret = val;
+       return 1;
+}
+
 int git_parse_maybe_bool_text(const char *value)
 {
        if (!value)
diff --git a/parse.h b/parse.h
index 07d2193d6984abcb8d4f6683e9dbb90e9e8876e9..6bb9a54d9ac8f782406fd33e59b9d42c6862d63e 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -6,6 +6,7 @@ int git_parse_ssize_t(const char *, ssize_t *);
 int git_parse_ulong(const char *, unsigned long *);
 int git_parse_int(const char *value, int *ret);
 int git_parse_int64(const char *value, int64_t *ret);
+int git_parse_double(const char *value, double *ret);
 
 /**
  * Same as `git_config_bool`, except that it returns -1 on error rather