Browse Source

opt: add float/double helpers.

bfgminer/cgminer/sgminer want these.  Con implemented some,
but these are independently written (with tests!)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 12 years ago
parent
commit
b989e06c09
3 changed files with 110 additions and 1 deletions
  1. 43 0
      ccan/opt/helpers.c
  2. 6 0
      ccan/opt/opt.h
  3. 61 1
      ccan/opt/test/run-helpers.c

+ 43 - 0
ccan/opt/helpers.c

@@ -116,6 +116,49 @@ char *opt_set_ulongval(const char *arg, unsigned long *ul)
 	return NULL;
 	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)
 char *opt_inc_intval(int *i)
 {
 {
 	(*i)++;
 	(*i)++;

+ 6 - 0
ccan/opt/opt.h

@@ -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);
 char *opt_set_ulongval(const char *arg, unsigned long *ul);
 void opt_show_ulongval(char buf[OPT_SHOW_LEN], const 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
 /* 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
    multiplies the numeric value by the corresponding power of 1000 or 1024
    (for the _si and _bi versions, respectively).
    (for the _si and _bi versions, respectively).

+ 61 - 1
ccan/opt/test/run-helpers.c

@@ -77,7 +77,7 @@ static void set_args(int *argc, char ***argv, ...)
 /* Test helpers. */
 /* Test helpers. */
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
-	plan_tests(454);
+	plan_tests(476);
 
 
 	/* opt_set_bool */
 	/* opt_set_bool */
 	{
 	{
@@ -206,6 +206,32 @@ int main(int argc, char *argv[])
 		else
 		else
 			fail("FIXME: Handle other long sizes");
 			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;
 		const long long k = 1024;
@@ -1140,6 +1166,40 @@ int main(int argc, char *argv[])
 		ok1(buf[OPT_SHOW_LEN] == '!');
 		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. */
 	/* opt_log_stderr. */
 	{
 	{
 		reset_options();
 		reset_options();