g_application_add_main_option: fix type signature
[platform/upstream/glib.git] / gio / gsettings-mapping.c
index e7f1ba5..12b7f34 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Vincent Untz <vuntz@gnome.org>
  */
 #include "gsettings-mapping.h"
 
 static GVariant *
-g_settings_set_mapping_numeric (const GValue       *value,
-                                const GVariantType *expected_type)
+g_settings_set_mapping_int (const GValue       *value,
+                            const GVariantType *expected_type)
 {
   GVariant *variant = NULL;
-  glong l;
+  gint64 l;
 
   if (G_VALUE_HOLDS_INT (value))
     l = g_value_get_int (value);
   else if (G_VALUE_HOLDS_INT64 (value))
     l = g_value_get_int64 (value);
-  else if (G_VALUE_HOLDS_DOUBLE (value))
-    l = g_value_get_double (value);
   else
     return NULL;
 
@@ -75,17 +71,71 @@ g_settings_set_mapping_numeric (const GValue       *value,
         variant = g_variant_new_handle ((guint) l);
     }
   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
-    variant = g_variant_new_double ((double) l);
+    variant = g_variant_new_double ((gdouble) l);
 
   return variant;
 }
 
 static GVariant *
-g_settings_set_mapping_unsigned_numeric (const GValue       *value,
-                                         const GVariantType *expected_type)
+g_settings_set_mapping_float (const GValue       *value,
+                              const GVariantType *expected_type)
+{
+  GVariant *variant = NULL;
+  gdouble d;
+  gint64 l;
+
+  if (G_VALUE_HOLDS_DOUBLE (value))
+    d = g_value_get_double (value);
+  else
+    return NULL;
+
+  l = (gint64) d;
+  if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
+    {
+      if (G_MININT16 <= l && l <= G_MAXINT16)
+        variant = g_variant_new_int16 ((gint16) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
+    {
+      if (0 <= l && l <= G_MAXUINT16)
+        variant = g_variant_new_uint16 ((guint16) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
+    {
+      if (G_MININT32 <= l && l <= G_MAXINT32)
+        variant = g_variant_new_int32 ((gint) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
+    {
+      if (0 <= l && l <= G_MAXUINT32)
+        variant = g_variant_new_uint32 ((guint) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
+    {
+      if (G_MININT64 <= l && l <= G_MAXINT64)
+        variant = g_variant_new_int64 ((gint64) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
+    {
+      if (0 <= l && l <= G_MAXUINT64)
+        variant = g_variant_new_uint64 ((guint64) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
+    {
+      if (0 <= l && l <= G_MAXUINT32)
+        variant = g_variant_new_handle ((guint) l);
+    }
+  else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
+    variant = g_variant_new_double ((gdouble) d);
+
+  return variant;
+}
+static GVariant *
+g_settings_set_mapping_unsigned_int (const GValue       *value,
+                                     const GVariantType *expected_type)
 {
   GVariant *variant = NULL;
-  gulong u;
+  guint64 u;
 
   if (G_VALUE_HOLDS_UINT (value))
     u = g_value_get_uint (value);
@@ -130,17 +180,17 @@ g_settings_set_mapping_unsigned_numeric (const GValue       *value,
         variant = g_variant_new_handle ((guint) u);
     }
   else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
-    variant = g_variant_new_double ((double) u);
+    variant = g_variant_new_double ((gdouble) u);
 
   return variant;
 }
 
 static gboolean
-g_settings_get_mapping_numeric (GValue   *value,
-                                GVariant *variant)
+g_settings_get_mapping_int (GValue   *value,
+                            GVariant *variant)
 {
   const GVariantType *type;
-  glong l;
+  gint64 l;
 
   type = g_variant_get_type (variant);
 
@@ -150,8 +200,6 @@ g_settings_get_mapping_numeric (GValue   *value,
     l = g_variant_get_int32 (variant);
   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
     l = g_variant_get_int64 (variant);
-  else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
-    l = g_variant_get_double (variant);
   else
     return FALSE;
 
@@ -185,11 +233,55 @@ g_settings_get_mapping_numeric (GValue   *value,
 }
 
 static gboolean
-g_settings_get_mapping_unsigned_numeric (GValue   *value,
-                                         GVariant *variant)
+g_settings_get_mapping_float (GValue   *value,
+                              GVariant *variant)
 {
   const GVariantType *type;
-  gulong u;
+  gdouble d;
+  gint64 l;
+
+  type = g_variant_get_type (variant);
+
+  if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
+    d = g_variant_get_double (variant);
+  else
+    return FALSE;
+
+  l = (gint64)d;
+  if (G_VALUE_HOLDS_INT (value))
+    {
+      g_value_set_int (value, l);
+      return (G_MININT32 <= l && l <= G_MAXINT32);
+    }
+  else if (G_VALUE_HOLDS_UINT (value))
+    {
+      g_value_set_uint (value, l);
+      return (0 <= l && l <= G_MAXUINT32);
+    }
+  else if (G_VALUE_HOLDS_INT64 (value))
+    {
+      g_value_set_int64 (value, l);
+      return (G_MININT64 <= l && l <= G_MAXINT64);
+    }
+  else if (G_VALUE_HOLDS_UINT64 (value))
+    {
+      g_value_set_uint64 (value, l);
+      return (0 <= l && l <= G_MAXUINT64);
+    }
+  else if (G_VALUE_HOLDS_DOUBLE (value))
+    {
+      g_value_set_double (value, d);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+static gboolean
+g_settings_get_mapping_unsigned_int (GValue   *value,
+                                     GVariant *variant)
+{
+  const GVariantType *type;
+  guint64 u;
 
   type = g_variant_get_type (variant);
 
@@ -252,31 +344,88 @@ g_settings_set_mapping (const GValue       *value,
       if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
         {
           if (G_VALUE_HOLDS_CHAR (value))
-            return g_variant_new_byte (g_value_get_char (value));
+            return g_variant_new_byte (g_value_get_schar (value));
           else
             return g_variant_new_byte (g_value_get_uchar (value));
         }
     }
 
   else if (G_VALUE_HOLDS_INT (value)   ||
-           G_VALUE_HOLDS_INT64 (value) ||
-           G_VALUE_HOLDS_DOUBLE (value))
-    return g_settings_set_mapping_numeric (value, expected_type);
+           G_VALUE_HOLDS_INT64 (value))
+    return g_settings_set_mapping_int (value, expected_type);
+
+  else if (G_VALUE_HOLDS_DOUBLE (value))
+    return g_settings_set_mapping_float (value, expected_type);
 
   else if (G_VALUE_HOLDS_UINT (value)  ||
            G_VALUE_HOLDS_UINT64 (value))
-    return g_settings_set_mapping_unsigned_numeric (value, expected_type);
+    return g_settings_set_mapping_unsigned_int (value, expected_type);
 
   else if (G_VALUE_HOLDS_STRING (value))
     {
-      if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
+      if (g_value_get_string (value) == NULL)
+        return NULL;
+      else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
         return g_variant_new_string (g_value_get_string (value));
+      else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTESTRING))
+        return g_variant_new_bytestring (g_value_get_string (value));
       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
         return g_variant_new_object_path (g_value_get_string (value));
       else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
         return g_variant_new_signature (g_value_get_string (value));
     }
 
+  else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+    {
+      if (g_value_get_boxed (value) == NULL)
+        return NULL;
+      return g_variant_new_strv ((const gchar **) g_value_get_boxed (value),
+                                 -1);
+    }
+
+  else if (G_VALUE_HOLDS_ENUM (value))
+    {
+      GEnumValue *enumval;
+      GEnumClass *eclass;
+
+      /* GParamSpecEnum holds a ref on the class so we just peek... */
+      eclass = g_type_class_peek (G_VALUE_TYPE (value));
+      enumval = g_enum_get_value (eclass, g_value_get_enum (value));
+
+      if (enumval)
+        return g_variant_new_string (enumval->value_nick);
+      else
+        return NULL;
+    }
+
+  else if (G_VALUE_HOLDS_FLAGS (value))
+    {
+      GVariantBuilder builder;
+      GFlagsValue *flagsval;
+      GFlagsClass *fclass;
+      guint flags;
+
+      fclass = g_type_class_peek (G_VALUE_TYPE (value));
+      flags = g_value_get_flags (value);
+
+      g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+      while (flags)
+        {
+          flagsval = g_flags_get_first_value (fclass, flags);
+
+          if (flagsval == NULL)
+            {
+              g_variant_builder_clear (&builder);
+              return NULL;
+            }
+
+          g_variant_builder_add (&builder, "s", flagsval->value_nick);
+          flags &= ~flagsval->value;
+        }
+
+      return g_variant_builder_end (&builder);
+    }
+
   type_string = g_variant_type_dup_string (expected_type);
   g_critical ("No GSettings bind handler for type \"%s\".", type_string);
   g_free (type_string);
@@ -302,7 +451,7 @@ g_settings_get_mapping (GValue   *value,
       if (G_VALUE_HOLDS_UCHAR (value))
         g_value_set_uchar (value, g_variant_get_byte (variant));
       else if (G_VALUE_HOLDS_CHAR (value))
-        g_value_set_char (value, (gchar) g_variant_get_byte (variant));
+        g_value_set_schar (value, (gint8)g_variant_get_byte (variant));
       else
         return FALSE;
       return TRUE;
@@ -310,21 +459,90 @@ g_settings_get_mapping (GValue   *value,
 
   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)  ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)  ||
-           g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)  ||
-           g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
-    return g_settings_get_mapping_numeric (value, variant);
+           g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64))
+    return g_settings_get_mapping_int (value, variant);
+
+  else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
+    return g_settings_get_mapping_float (value, variant);
 
   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
-    return g_settings_get_mapping_unsigned_numeric (value, variant);
+    return g_settings_get_mapping_unsigned_int (value, variant);
 
   else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)      ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
            g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
     {
-      g_value_set_string (value, g_variant_get_string (variant, NULL));
+      if (G_VALUE_HOLDS_STRING (value))
+        {
+          g_value_set_string (value, g_variant_get_string (variant, NULL));
+          return TRUE;
+        }
+
+      else if (G_VALUE_HOLDS_ENUM (value))
+        {
+          GEnumClass *eclass;
+          GEnumValue *evalue;
+          const gchar *nick;
+
+          /* GParamSpecEnum holds a ref on the class so we just peek... */
+          eclass = g_type_class_peek (G_VALUE_TYPE (value));
+          nick = g_variant_get_string (variant, NULL);
+          evalue = g_enum_get_value_by_nick (eclass, nick);
+
+          if (evalue)
+            {
+             g_value_set_enum (value, evalue->value);
+             return TRUE;
+            }
+
+          g_warning ("Unable to lookup enum nick '%s' via GType\n", nick);
+          return FALSE;
+        }
+    }
+  else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("as")))
+    {
+      if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        {
+          g_value_take_boxed (value, g_variant_dup_strv (variant, NULL));
+          return TRUE;
+        }
+
+      else if (G_VALUE_HOLDS_FLAGS (value))
+        {
+          GFlagsClass *fclass;
+          GFlagsValue *fvalue;
+          const gchar *nick;
+          GVariantIter iter;
+          guint flags = 0;
+
+          fclass = g_type_class_peek (G_VALUE_TYPE (value));
+
+          g_variant_iter_init (&iter, variant);
+          while (g_variant_iter_next (&iter, "&s", &nick))
+            {
+              fvalue = g_flags_get_value_by_nick (fclass, nick);
+
+              if (fvalue)
+                flags |= fvalue->value;
+
+              else
+                {
+                  g_warning ("Unable to lookup flags nick '%s' via GType\n",
+                             nick);
+                  return FALSE;
+                }
+            }
+
+          g_value_set_flags (value, flags);
+          return TRUE;
+        }
+    }
+  else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTESTRING))
+    {
+      g_value_set_string (value, g_variant_get_bytestring (variant));
       return TRUE;
     }
 
@@ -360,8 +578,15 @@ g_settings_mapping_is_compatible (GType               gvalue_type,
           g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
   else if (gvalue_type == G_TYPE_STRING)
     ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)      ||
+          g_variant_type_equal (variant_type, G_VARIANT_TYPE ("ay")) ||
           g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
           g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
+  else if (gvalue_type == G_TYPE_STRV)
+    ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
+  else if (G_TYPE_IS_ENUM (gvalue_type))
+    ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
+  else if (G_TYPE_IS_FLAGS (gvalue_type))
+    ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
 
   return ok;
 }