Support floating point arguments in goption
authorMatthias Clasen <matthiasc@src.gnome.org>
Mon, 27 Mar 2006 06:57:28 +0000 (06:57 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Mon, 27 Mar 2006 06:57:28 +0000 (06:57 +0000)
ChangeLog
ChangeLog.pre-2-12
docs/reference/ChangeLog
docs/reference/glib/tmpl/option.sgml
glib/goption.c
glib/goption.h
tests/option-test.c

index 4eba47c..ee5be11 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-27  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
         * glib/goption.c (g_option_context_new): Improve the description
index 4eba47c..ee5be11 100644 (file)
@@ -1,3 +1,14 @@
+2006-03-27  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
         * glib/goption.c (g_option_context_new): Improve the description
index 0583fa4..8a620f0 100644 (file)
@@ -1,3 +1,7 @@
+2006-03-27  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/tmpl/option.sgml: Document floating point arguments
+
 Fri Mar 24 15:22:04 2006  Tim Janik  <timj@imendio.com>
 
        * glib/tmpl/atomic_operations.sgml: some wording fixups.
index 15a9ac6..7e317f7 100644 (file)
@@ -257,6 +257,8 @@ or combined in a single argument: <option>--name=arg</option>.
   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
 
 <!-- ##### ENUM GOptionFlags ##### -->
 <para>
@@ -350,6 +352,10 @@ g_option_context_add_main_entries() or g_option_group_add_entries().
       <term>%G_OPTION_ARG_FILENAME_ARRAY</term>
       <listitem><para>%gchar**</para></listitem>
     </varlistentry>
+    <varlistentry>
+      <term>%G_OPTION_ARG_DOUBLE</term>
+      <listitem><para>%gdouble</para></listitem>
+    </varlistentry>
   </variablelist>
 @description: the description for the option in <option>--help</option>
   output. The @description is translated using the @translate_func of the
index 37a24cd..42eef85 100644 (file)
@@ -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,
@@ -902,6 +939,23 @@ parse_arg (GOptionContext *context,
        
        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:
       g_assert_not_reached ();
     }
@@ -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 ();
            }
index 4448fd0..6a5bba2 100644 (file)
@@ -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,
index 4699afd..800c97f 100644 (file)
@@ -1,5 +1,6 @@
 #include <glib.h>
 #include <string.h>
+#include <locale.h>
 
 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 ();