opt: add float/double helpers.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 24 Feb 2014 03:26:32 +0000 (13:56 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 24 Feb 2014 03:27:10 +0000 (13:57 +1030)
bfgminer/cgminer/sgminer want these.  Con implemented some,
but these are independently written (with tests!)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/opt/helpers.c
ccan/opt/opt.h
ccan/opt/test/run-helpers.c

index 2c771bc3309062aa7cfea03423f719128f3c9686..747a78e9139b875e7f7f6620d194510418c2c300 100644 (file)
@@ -116,6 +116,49 @@ char *opt_set_ulongval(const char *arg, unsigned long *ul)
        return NULL;
 }
 
+char *opt_set_floatval(const char *arg, float *f)
+{
+       double d;
+       char *err;
+
+       err = opt_set_doubleval(arg, &d);
+       if (err)
+               return err;
+
+       *f = d;
+       if (*f != d)
+               return arg_bad("'%s' is out of range", arg);
+
+       return NULL;
+}
+
+void opt_show_floatval(char buf[OPT_SHOW_LEN], const float *f)
+{
+       double d = *f;
+       opt_show_doubleval(buf, &d);
+}
+
+char *opt_set_doubleval(const char *arg, double *d)
+{
+       char *endp;
+
+       /* This is how the manpage says to do it.  Yech. */
+       errno = 0;
+       /* Don't assume strtof */
+       *d = strtod(arg, &endp);
+       if (*endp || !arg[0])
+               return arg_bad("'%s' is not a number", arg);
+       if (errno)
+               return arg_bad("'%s' is out of range", arg);
+
+       return NULL;
+}
+
+void opt_show_doubleval(char buf[OPT_SHOW_LEN], const double *d)
+{
+       snprintf(buf, OPT_SHOW_LEN, "%f", *d);
+}
+
 char *opt_inc_intval(int *i)
 {
        (*i)++;
index 3dd4edc640b268fd4ad8fa76eff578d6f941807b..f891002fa53890be40251b3e2557c4af3d2cd15e 100644 (file)
@@ -409,6 +409,12 @@ void opt_show_longval(char buf[OPT_SHOW_LEN], const long *l);
 char *opt_set_ulongval(const char *arg, unsigned long *ul);
 void opt_show_ulongval(char buf[OPT_SHOW_LEN], const unsigned long *ul);
 
+/* Set an floating point value, various forms. */
+char *opt_set_floatval(const char *arg, float *f);
+void opt_show_floatval(char buf[OPT_SHOW_LEN], const float *f);
+char *opt_set_doubleval(const char *arg, double *d);
+void opt_show_doubleval(char buf[OPT_SHOW_LEN], const double *d);
+
 /* the following setting functions accept k, M, G, T, P, or E suffixes, which
    multiplies the numeric value by the corresponding power of 1000 or 1024
    (for the _si and _bi versions, respectively).
index 10b241908add534cd0f816457214debe28be1fea..49fb2062e30427725c4b79b33303df55edc02e14 100644 (file)
@@ -77,7 +77,7 @@ static void set_args(int *argc, char ***argv, ...)
 /* Test helpers. */
 int main(int argc, char *argv[])
 {
-       plan_tests(454);
+       plan_tests(476);
 
        /* opt_set_bool */
        {
@@ -206,6 +206,32 @@ int main(int argc, char *argv[])
                else
                        fail("FIXME: Handle other long sizes");
        }
+       /* opt_set_floatval */
+       {
+               float arg = 1000;
+               reset_options();
+               opt_register_arg("-a", opt_set_floatval, NULL, &arg, "All");
+               ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
+               ok1(arg == 9999);
+               ok1(parse_args(&argc, &argv, "-a", "-9999", NULL));
+               ok1(arg == -9999);
+               ok1(parse_args(&argc, &argv, "-a", "0", NULL));
+               ok1(arg == 0);
+               ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
+       }
+       /* opt_set_doubleval */
+       {
+               double arg = 1000;
+               reset_options();
+               opt_register_arg("-a", opt_set_doubleval, NULL, &arg, "All");
+               ok1(parse_args(&argc, &argv, "-a", "9999", NULL));
+               ok1(arg == 9999);
+               ok1(parse_args(&argc, &argv, "-a", "-9999", NULL));
+               ok1(arg == -9999);
+               ok1(parse_args(&argc, &argv, "-a", "0", NULL));
+               ok1(arg == 0);
+               ok1(!parse_args(&argc, &argv, "-a", "100crap", NULL));
+       }
 
        {
                const long long k = 1024;
@@ -1140,6 +1166,40 @@ int main(int argc, char *argv[])
                ok1(buf[OPT_SHOW_LEN] == '!');
        }
 
+       /* opt_show_floatval */
+       {
+               float f;
+               char buf[OPT_SHOW_LEN+2] = { 0 };
+               buf[OPT_SHOW_LEN] = '!';
+
+               f = -77.5;
+               opt_show_floatval(buf, &f);
+               ok1(strcmp(buf, "-77.500000") == 0);
+               ok1(buf[OPT_SHOW_LEN] == '!');
+
+               f = 77.5;
+               opt_show_floatval(buf, &f);
+               ok1(strcmp(buf, "77.500000") == 0);
+               ok1(buf[OPT_SHOW_LEN] == '!');
+       }
+
+       /* opt_show_doubleval */
+       {
+               double d;
+               char buf[OPT_SHOW_LEN+2] = { 0 };
+               buf[OPT_SHOW_LEN] = '!';
+
+               d = -77;
+               opt_show_doubleval(buf, &d);
+               ok1(strcmp(buf, "-77.000000") == 0);
+               ok1(buf[OPT_SHOW_LEN] == '!');
+
+               d = 77;
+               opt_show_doubleval(buf, &d);
+               ok1(strcmp(buf, "77.000000") == 0);
+               ok1(buf[OPT_SHOW_LEN] == '!');
+       }
+
        /* opt_log_stderr. */
        {
                reset_options();