From 9749aa87e5e0f73e7cbb07be08aabbbc25e95157 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 27 Mar 2006 06:57:28 +0000 Subject: [PATCH] Support floating point arguments in goption --- ChangeLog | 11 +++++ ChangeLog.pre-2-12 | 11 +++++ docs/reference/ChangeLog | 4 ++ docs/reference/glib/tmpl/option.sgml | 6 +++ glib/goption.c | 57 +++++++++++++++++++++++ glib/goption.h | 3 +- tests/option-test.c | 69 ++++++++++++++++++++++++++++ 7 files changed, 160 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4eba47c0e..ee5be11ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-03-27 Matthias Clasen + + Add support for floating point numbers to goption. + (#329548, Behdad Esfahbod, patch by Antoine Dopffer and + Dom Lachowicz) + + * glib/goption.h: + * glib/goption.c: Support double arguments. + + * tests/option-test.c: Test double arguments.` + 2006-03-26 Matthias Clasen * glib/goption.c (g_option_context_new): Improve the description diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 4eba47c0e..ee5be11ac 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,14 @@ +2006-03-27 Matthias Clasen + + Add support for floating point numbers to goption. + (#329548, Behdad Esfahbod, patch by Antoine Dopffer and + Dom Lachowicz) + + * glib/goption.h: + * glib/goption.c: Support double arguments. + + * tests/option-test.c: Test double arguments.` + 2006-03-26 Matthias Clasen * glib/goption.c (g_option_context_new): Improve the description diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 0583fa41d..8a620f0f2 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,7 @@ +2006-03-27 Matthias Clasen + + * glib/tmpl/option.sgml: Document floating point arguments + Fri Mar 24 15:22:04 2006 Tim Janik * glib/tmpl/atomic_operations.sgml: some wording fixups. diff --git a/docs/reference/glib/tmpl/option.sgml b/docs/reference/glib/tmpl/option.sgml index 15a9ac69c..7e317f70f 100644 --- a/docs/reference/glib/tmpl/option.sgml +++ b/docs/reference/glib/tmpl/option.sgml @@ -257,6 +257,8 @@ or combined in a single argument: . uses of the option are collected into an array of strings. @G_OPTION_ARG_FILENAME_ARRAY: The option takes a filename as argument, multiple uses of the option are collected into an array of strings. +@G_OPTION_ARG_DOUBLE: The option takes a double argument. The argument + can be formatted either for the user's locale or for the "C" locale. Since 2.12 @@ -350,6 +352,10 @@ g_option_context_add_main_entries() or g_option_group_add_entries(). %G_OPTION_ARG_FILENAME_ARRAY %gchar** + + %G_OPTION_ARG_DOUBLE + %gdouble + @description: the description for the option in output. The @description is translated using the @translate_func of the diff --git a/glib/goption.c b/glib/goption.c index 37a24cd82..42eef854b 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -50,6 +50,7 @@ typedef struct gint integer; gchar *str; gchar **array; + gdouble dbl; } prev; union { @@ -684,6 +685,42 @@ parse_int (const gchar *arg_name, return TRUE; } + +static gboolean +parse_double (const gchar *arg_name, + const gchar *arg, + gdouble *result, + GError **error) +{ + gchar *end; + gdouble tmp; + + errno = 0; + tmp = g_strtod (arg, &end); + + if (*arg == '\0' || *end != '\0') + { + g_set_error (error, + G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + _("Cannot parse double value '%s' for %s"), + arg, arg_name); + return FALSE; + } + if (errno == ERANGE) + { + g_set_error (error, + G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + _("Double value '%s' for %s out of range"), + arg, arg_name); + return FALSE; + } + + *result = tmp; + + return TRUE; +} + + static Change * get_change (GOptionContext *context, GOptionArg arg_type, @@ -900,6 +937,23 @@ parse_arg (GOptionContext *context, return retval; + break; + } + case G_OPTION_ARG_DOUBLE: + { + gdouble data; + + if (!parse_double (option_name, value, + &data, + error)) + { + return FALSE; + } + + change = get_change (context, G_OPTION_ARG_DOUBLE, + entry->arg_data); + change->prev.dbl = *(gdouble *)entry->arg_data; + *(gdouble *)entry->arg_data = data; break; } default: @@ -1166,6 +1220,9 @@ free_changes_list (GOptionContext *context, g_strfreev (change->allocated.array.data); *(gchar ***)change->arg_data = change->prev.array; break; + case G_OPTION_ARG_DOUBLE: + *(gdouble *)change->arg_data = change->prev.dbl; + break; default: g_assert_not_reached (); } diff --git a/glib/goption.h b/glib/goption.h index 4448fd0c3..6a5bba224 100644 --- a/glib/goption.h +++ b/glib/goption.h @@ -49,7 +49,8 @@ typedef enum G_OPTION_ARG_CALLBACK, G_OPTION_ARG_FILENAME, G_OPTION_ARG_STRING_ARRAY, - G_OPTION_ARG_FILENAME_ARRAY + G_OPTION_ARG_FILENAME_ARRAY, + G_OPTION_ARG_DOUBLE } GOptionArg; typedef gboolean (*GOptionArgFunc) (const gchar *option_name, diff --git a/tests/option-test.c b/tests/option-test.c index 4699afd7d..800c97f3e 100644 --- a/tests/option-test.c +++ b/tests/option-test.c @@ -1,5 +1,6 @@ #include #include +#include int error_test1_int; char *error_test2_string; @@ -8,6 +9,8 @@ gboolean error_test3_boolean; int arg_test1_int; gchar *arg_test2_string; gchar *arg_test3_filename; +gdouble arg_test4_double; +gdouble arg_test5_double; gchar *callback_test1_string; gboolean callback_test2_int; @@ -330,6 +333,70 @@ arg_test3 (void) g_option_context_free (context); } + +void +arg_test4 (void) +{ + GOptionContext *context; + gboolean retval; + GError *error = NULL; + gchar **argv; + int argc; + GOptionEntry entries [] = + { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test4_double, NULL, NULL }, + { NULL } }; + + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, entries, NULL); + + /* Now try parsing */ + argv = split_string ("program --test 20.0 --test 30.03", &argc); + + retval = g_option_context_parse (context, &argc, &argv, &error); + g_assert (retval); + + /* Last arg specified is the one that should be stored */ + g_assert (arg_test4_double == 30.03); + + g_strfreev (argv); + g_option_context_free (context); +} + +void +arg_test5 (void) +{ + GOptionContext *context; + gboolean retval; + GError *error = NULL; + gchar **argv; + int argc; + char *old_locale; + GOptionEntry entries [] = + { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL }, + { NULL } }; + + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, entries, NULL); + + /* Now try parsing */ + argv = split_string ("program --test 20,0 --test 30,03", &argc); + + /* set it to some locale that uses commas instead of decimal points */ + old_locale = g_strdup (setlocale(LC_NUMERIC, "de")); + + retval = g_option_context_parse (context, &argc, &argv, &error); + g_assert (retval); + + /* Last arg specified is the one that should be stored */ + g_assert (arg_test4_double == 30.03); + + setlocale(LC_NUMERIC, old_locale); + g_free (old_locale); + + g_strfreev (argv); + g_option_context_free (context); +} + static gboolean callback_parse1 (const gchar *option_name, const gchar *value, gpointer data, GError **error) @@ -1288,6 +1355,8 @@ main (int argc, char **argv) arg_test1 (); arg_test2 (); arg_test3 (); + arg_test4 (); + /* arg_test5 (); */ /* Test string arrays */ array_test1 ();