Author: kelnos
Date: 2008-04-20 07:39:02 +0000 (Sun, 20 Apr 2008)
New Revision: 26874

Modified:
   xfconf/trunk/common/xfconf-types.c
   xfconf/trunk/docs/spec/backend.txt
   xfconf/trunk/docs/spec/perchannel-xml.txt
   xfconf/trunk/xfconf/xfconf-channel.c
Log:
treat uint16/int16 as uint32/int32 when sending data over dbus

annoyingly, dbus-glib doesn't support sending 16-bit signed or unsigned
integers over the bus, since no 16-bit GTypes exist.  the ability to expose
custom GValue marshallers is not exposed in dbus-glib's API, so custom
GTypes cannot be added.

so, internally, we handle 16-bit values as if they were 32-bit values.
the 16-bit types are kept so that the struct-related functions still work.


Modified: xfconf/trunk/common/xfconf-types.c
===================================================================
--- xfconf/trunk/common/xfconf-types.c  2008-04-20 07:38:50 UTC (rev 26873)
+++ xfconf/trunk/common/xfconf-types.c  2008-04-20 07:39:02 UTC (rev 26874)
@@ -21,13 +21,134 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
 #include "xfconf/xfconf-types.h"
 #include "xfconf-alias.h"
 
 #include <gobject/gvaluecollector.h>
 
+static void
+gvalue_from_short(const GValue *src_value,
+                  GValue *dest_value)
+{
+#define HANDLE_TYPE(gtype_s, getter) \
+    case G_TYPE_ ## gtype_s: \
+        dest = (guint64)g_value_get_ ## getter(src_value); \
+        break;
 
+    guint64 dest;  /* use larger type so we can handle int16 & uint16 */
+
+    switch(G_VALUE_TYPE(src_value)) {
+        case G_TYPE_STRING:
+            dest = atoi(g_value_get_string(src_value));
+            break;
+        case G_TYPE_BOOLEAN:
+            dest = g_value_get_boolean(src_value) == TRUE ? 1 : 0;
+            break;
+        HANDLE_TYPE(CHAR, char)
+        HANDLE_TYPE(UCHAR, uchar)
+        HANDLE_TYPE(INT, int)
+        HANDLE_TYPE(UINT, uint)
+        HANDLE_TYPE(LONG, long)
+        HANDLE_TYPE(ULONG, ulong)
+        HANDLE_TYPE(INT64, int64)
+        HANDLE_TYPE(UINT64, uint64)
+        HANDLE_TYPE(ENUM, enum)
+        HANDLE_TYPE(FLAGS, flags)
+        HANDLE_TYPE(FLOAT, float)
+        HANDLE_TYPE(DOUBLE, double)
+        default:
+            return;
+    }
+
+    if(G_VALUE_TYPE(dest_value) == XFCONF_TYPE_UINT16) {
+        if(dest > USHRT_MAX) {
+            g_warning("Converting type \"%s\" to \"%s\" results in overflow",
+                      G_VALUE_TYPE_NAME(src_value),
+                      G_VALUE_TYPE_NAME(dest_value));
+        }
+        xfconf_g_value_set_uint16(dest_value, (guint16)dest);
+    } else if(G_VALUE_TYPE(dest_value) == XFCONF_TYPE_INT16) {
+        if(dest > SHRT_MAX || dest < SHRT_MIN) {
+            g_warning("Converting type \"%s\" to \"%s\" results in overflow",
+                      G_VALUE_TYPE_NAME(src_value),
+                      G_VALUE_TYPE_NAME(dest_value));
+        }
+        xfconf_g_value_set_int16(dest_value, (gint16)dest);
+    }
+#undef HANDLE_TYPE
+}
+
 static void
+short_from_gvalue(const GValue *src_value,
+                  GValue *dest_value)
+{
+#define HANDLE_TYPE(gtype_s, setter) \
+    case G_TYPE_ ## gtype_s: \
+        g_value_set_ ## setter(dest_value, src); \
+        break;
+
+    guint16 src;
+    gboolean is_signed = FALSE;
+
+    if(G_VALUE_TYPE(src_value) == XFCONF_TYPE_UINT16)
+        src = xfconf_g_value_get_uint16(src_value);
+    else if(G_VALUE_TYPE(src_value) == XFCONF_TYPE_INT16) {
+        src = xfconf_g_value_get_int16(src_value);
+        is_signed = TRUE;
+    } else
+        return;
+
+    switch(G_VALUE_TYPE(dest_value)) {
+        case G_TYPE_STRING: {
+            gchar *str = g_strdup_printf(is_signed ? "%d" : "%u",
+                                         is_signed ? (gint16)src : src);
+            g_value_set_string(dest_value, str);
+            g_free(str);
+            break;
+        }
+        case G_TYPE_BOOLEAN:
+            g_value_set_boolean(dest_value, src ? TRUE : FALSE);
+            break;
+        HANDLE_TYPE(CHAR, char)
+        HANDLE_TYPE(UCHAR, uchar)
+        HANDLE_TYPE(INT, int)
+        HANDLE_TYPE(UINT, uint)
+        HANDLE_TYPE(LONG, long)
+        HANDLE_TYPE(ULONG, ulong)
+        HANDLE_TYPE(INT64, int64)
+        HANDLE_TYPE(UINT64, uint64)
+        HANDLE_TYPE(ENUM, enum)
+        HANDLE_TYPE(FLAGS, flags)
+        HANDLE_TYPE(FLOAT, float)
+        HANDLE_TYPE(DOUBLE, double)
+        default:
+            return;
+    }
+#undef HANDLE_TYPE
+}
+
+static void
+register_transforms(GType gtype)
+{
+    GType types[] = {
+        G_TYPE_CHAR, G_TYPE_UCHAR, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_UINT,
+        G_TYPE_LONG, G_TYPE_ULONG, G_TYPE_INT64, G_TYPE_UINT64,
+        G_TYPE_ENUM, G_TYPE_FLAGS, G_TYPE_FLOAT, G_TYPE_DOUBLE,
+        G_TYPE_STRING, G_TYPE_INVALID,
+    };
+    gint i;
+
+    for(i = 0; types[i] != G_TYPE_INVALID; ++i) {
+        g_value_register_transform_func(gtype, types[i], gvalue_from_short);
+        g_value_register_transform_func(types[i], gtype, short_from_gvalue);
+    }
+}
+
+static void
 ushort_value_init(GValue *value)
 {
     value->data[0].v_int = 0;
@@ -91,6 +212,7 @@
         uint16_type = g_type_register_fundamental(g_type_fundamental_next(),
                                                   "XfconfUint16", &info,
                                                    &finfo, 0);
+        register_transforms(uint16_type);
     }
 
     return uint16_type;
@@ -148,6 +270,7 @@
         int16_type = g_type_register_fundamental(g_type_fundamental_next(),
                                                  "XfconfInt16", &info,
                                                   &finfo, 0);
+        register_transforms(int16_type);
     }
 
     return int16_type;

Modified: xfconf/trunk/docs/spec/backend.txt
===================================================================
--- xfconf/trunk/docs/spec/backend.txt  2008-04-20 07:38:50 UTC (rev 26873)
+++ xfconf/trunk/docs/spec/backend.txt  2008-04-20 07:39:02 UTC (rev 26874)
@@ -14,13 +14,11 @@
 xfconf_channel_set_uint64()), users of the library can also set other,
 semi-arbitrary types, as well as array types.
 
-So, the backend must, at minimum, be able to understand the following GTypes:
+So, the backend must, be able to understand the following GTypes:
 
 G_TYPE_STRING
 G_TYPE_UCHAR
 G_TYPE_CHAR
-XFCONF_TYPE_UINT16
-XFCONF_TYPE_INT16
 G_TYPE_UINT
 G_TYPE_INT
 G_TYPE_UINT64
@@ -29,6 +27,12 @@
 G_TYPE_DOUBLE
 G_TYPE_BOOLEAN
 
+Note about 16-bit values: dbus-glib does not support sending 16-bit signed
+and unsigned integers over D-Bus, even though libdbus does.  For convenience,
+libxfconf will take any 16-bit values it receives and convert them into
+32-bit values before sending them to the daemon.  From the daemon/backend
+point of view, 16-bit values are simply not supported.
+
 In addition, the backend must be able to handle arrays of arbitrary
 types from the above list.  A single array may hold multiple values
 of the same type, or of different types.  Because of this, an array is

Modified: xfconf/trunk/docs/spec/perchannel-xml.txt
===================================================================
--- xfconf/trunk/docs/spec/perchannel-xml.txt   2008-04-20 07:38:50 UTC (rev 
26873)
+++ xfconf/trunk/docs/spec/perchannel-xml.txt   2008-04-20 07:39:02 UTC (rev 
26874)
@@ -59,6 +59,9 @@
        + type(string): The type of property.  Must be one of: "string",
          "uchar", "char", "uint16", "int16", "uint", "int", "uint64",
          "int64", "float", "double", "bool", "array", or "empty" (required).
+         Note that due to a limitation in dbus-glib, uint16 and int16 aren't
+         actually used, but they are supported in the backend in case
+         support for 16-bit values becomes supported in the future.
        + value(string): The value of the property (required except for
          type="array" and type="empty").
        + locked(userlist): A list of users/groups who cannot modify

Modified: xfconf/trunk/xfconf/xfconf-channel.c
===================================================================
--- xfconf/trunk/xfconf/xfconf-channel.c        2008-04-20 07:38:50 UTC (rev 
26873)
+++ xfconf/trunk/xfconf/xfconf-channel.c        2008-04-20 07:39:02 UTC (rev 
26874)
@@ -244,18 +244,84 @@
                             GValue *value)
 {
     DBusGProxy *proxy = _xfconf_get_dbus_g_proxy();
+    GValue tmp_val = { 0, }, *val;
     gboolean ret;
     ERROR_DEFINE;
 
+    /* we support 2 ways of using this function:
+     * 1.  |value| is unset, and we just take the property from xfconf
+     *     and give it to the caller as-is, in the type xfconf gives
+     * 2.  |value| is initialised, so we (try to) transform the value
+     *     returned into the type the caller requested
+     */
+
+    if(G_VALUE_TYPE(value))
+        val = &tmp_val;
+    else
+        val = value;
+
     ret = xfconf_client_get_property(proxy, channel->channel_name, property,
-                                     value, ERROR);
+                                     val, ERROR);
     if(!ret)
         ERROR_CHECK;
 
+    if(ret && val == &tmp_val) {
+        if(!g_value_transform(val, value)) {
+            g_warning("Unable to tranform value of type \"%s\" to type \"%s\" 
for property %s",
+                      G_VALUE_TYPE_NAME(val), G_VALUE_TYPE_NAME(value),
+                      property);
+            g_value_unset(val);
+            return FALSE;
+        }
+        g_value_unset(val);
+    }
+
     return ret;
 }
 
+static GPtrArray *
+xfconf_fixup_16bit_ints(GPtrArray *arr)
+{
+    GPtrArray *arr_new = NULL;
+    gint i;
 
+    for(i = 0; i < arr->len; ++i) {
+        GValue *v = g_ptr_array_index(arr, i);
+
+        if(G_VALUE_TYPE(v) == XFCONF_TYPE_UINT16
+           || G_VALUE_TYPE(v) == XFCONF_TYPE_INT16)
+        {
+            arr_new = g_ptr_array_sized_new(arr->len);
+            break;
+        }
+    }
+
+    if(!arr_new)
+        return NULL;
+
+    for(i = 0; i < arr->len; ++i) {
+        GValue *v_src, *v_dest;
+
+        v_src = g_ptr_array_index(arr, i);
+        v_dest = g_new0(GValue, 1);
+        if(G_VALUE_TYPE(v_src) == XFCONF_TYPE_UINT16) {
+            g_value_init(v_dest, G_TYPE_UINT);
+            g_value_set_uint(v_dest, xfconf_g_value_get_uint16(v_src));
+        } else if(G_VALUE_TYPE(v_src) == XFCONF_TYPE_INT16) {
+            g_value_init(v_dest, G_TYPE_INT);
+            g_value_set_int(v_dest, xfconf_g_value_get_int16(v_src));
+        } else {
+            g_value_init(v_dest, G_VALUE_TYPE(v_src));
+            g_value_copy(v_src, v_dest);
+        }
+
+        g_ptr_array_add(arr_new, v_dest);
+    }
+
+    return arr_new;
+}
+
+
 /**
  * xfconf_channel_new:
  * @channel_name: A channel name.
@@ -774,6 +840,13 @@
  * Gets a property on @channel and stores it in @value.  The caller is
  * responsible for calling g_value_unset() when finished with @value.
  *
+ * This function can be called with an initialized or uninitialized
+ * @value.  If @value is initialized to a particular type, libxfconf
+ * will attempt to convert the value returned from the configuration
+ * store to that type if they don't match.  If @value is uninitialized,
+ * The value in the configuration store will be returned in its native
+ * type.
+ *
  * Returns: %TRUE if the property was retrieved successfully,
  *          %FALSE otherwise.
  **/
@@ -782,7 +855,7 @@
                             const gchar *property,
                             GValue *value)
 {
-    GValue val1 = {0, };
+    GValue val1 = { 0, };
     gboolean ret;
 
     g_return_val_if_fail(XFCONF_IS_CHANNEL(channel) && property && value,
@@ -818,17 +891,34 @@
                             const GValue *value)
 {
     DBusGProxy *proxy = _xfconf_get_dbus_g_proxy();
+    GValue *val, tmp_val = { 0, };
     gboolean ret;
     ERROR_DEFINE;
 
     g_return_val_if_fail(XFCONF_IS_CHANNEL(channel) && property && value,
                          FALSE);
 
+    /* intercept uint16/int16 since dbus-glib doesn't know how to send
+     * them over the wire */
+    if(G_VALUE_TYPE(value) == XFCONF_TYPE_UINT16) {
+        val = &tmp_val;
+        g_value_init(&tmp_val, G_TYPE_UINT);
+        g_value_set_uint(&tmp_val, xfconf_g_value_get_uint16(value));
+    } else if(G_VALUE_TYPE(value) == XFCONF_TYPE_INT16) {
+        val = &tmp_val;
+        g_value_init(&tmp_val, G_TYPE_INT);
+        g_value_set_int(&tmp_val, xfconf_g_value_get_int16(value));
+    } else
+        val = (GValue *)value;
+
     ret = xfconf_client_set_property(proxy, channel->channel_name, property,
-                                     value, ERROR);
+                                     val, ERROR);
     if(!ret)
         ERROR_CHECK;
 
+    if(val == &tmp_val)
+        g_value_unset(&tmp_val);
+
     return ret;
 }
 
@@ -913,7 +1003,11 @@
 
         val = g_ptr_array_index(arr, i);
 
-        if(G_VALUE_TYPE(val) != cur_value_type) {
+        /* special case: uint16/int16 are stored as uint/int */
+        if(G_VALUE_TYPE(val) != cur_value_type
+           && !((G_VALUE_TYPE(val) == G_TYPE_UINT && cur_value_type == 
XFCONF_TYPE_UINT16)
+                || (G_VALUE_TYPE(val) == G_TYPE_INT && cur_value_type == 
XFCONF_TYPE_INT16)))
+        {
 #ifdef XFCONF_ENABLE_CHECKS
             g_warning("Value types don't match (%d != %d) at parameter %d",
                        (int)G_VALUE_TYPE(val), (int)cur_value_type, i);
@@ -948,11 +1042,13 @@
 
             default:
                 if(XFCONF_TYPE_UINT16 == cur_value_type) {
+                    /* uint16 is stored as uint */
                     guint16 *__val_p = va_arg(var_args, guint16 *);
-                    *__val_p = xfconf_g_value_get_uint16(val);
+                    *__val_p = (guint16)g_value_get_uint(val);
                 } else if(XFCONF_TYPE_INT16 == cur_value_type) {
+                    /* int16 is stored as int */
                     gint16 *__val_p = va_arg(var_args, gint16 *);
-                    *__val_p = xfconf_g_value_get_int16(val);
+                    *__val_p = (gint16)g_value_get_int(val);
                 } else if(G_TYPE_STRV == cur_value_type) {
                     gchar ***__val_p = va_arg(var_args, gchar ***);
                     *__val_p = g_value_dup_boxed(val);
@@ -1129,16 +1225,18 @@
 
             default:
                 if(XFCONF_TYPE_UINT16 == cur_value_type) {
+                    /* uint16 is stored as uint */
                     guint16 *__val = va_arg(var_args, guint16 *);
                     val = g_new0(GValue, 1);
-                    g_value_init(val, XFCONF_TYPE_UINT16);
-                    xfconf_g_value_set_uint16(val, *__val);
+                    g_value_init(val, G_TYPE_UINT);
+                    g_value_set_uint(val, (guint)*__val);
                     g_ptr_array_add(arr, val);
                 } else if(XFCONF_TYPE_INT16 == cur_value_type) {
+                    /* int16 is stored as int */
                     gint16 *__val = va_arg(var_args, gint16 *);
                     val = g_new0(GValue, 1);
-                    g_value_init(val, XFCONF_TYPE_INT16);
-                    xfconf_g_value_set_int16(val, *__val);
+                    g_value_init(val, G_TYPE_INT);
+                    g_value_set_int(val, (gint)*__val);
                     g_ptr_array_add(arr, val);
                 } else if(G_TYPE_STRV == cur_value_type) {
                     gchar **__val = va_arg(var_args, gchar **);
@@ -1180,6 +1278,7 @@
                           GPtrArray *values)
 {
     DBusGProxy *proxy = _xfconf_get_dbus_g_proxy();
+    GPtrArray *values_new = NULL;
     GValue val = { 0, };
     gboolean ret;
     ERROR_DEFINE;
@@ -1187,8 +1286,10 @@
     g_return_val_if_fail(XFCONF_IS_CHANNEL(channel) && property && values,
                          FALSE);
 
+    values_new = xfconf_fixup_16bit_ints(values);
+
     g_value_init(&val, XFCONF_TYPE_G_VALUE_ARRAY);
-    g_value_set_static_boxed(&val, values);
+    g_value_set_static_boxed(&val, values_new ? values_new : values);
     
     ret = xfconf_client_set_property(proxy, channel->channel_name, property,
                                      &val, ERROR);
@@ -1198,6 +1299,9 @@
     
     g_value_unset(&val);
 
+    if(values_new)
+        xfconf_array_free(values_new);
+
     return ret;
 }
 
@@ -1486,11 +1590,13 @@
 
             default:
                 if(XFCONF_TYPE_UINT16 == member_types[i]) {
-                    SET_STRUCT_VAL(guint16, XFCONF_TYPE_UINT16,
-                                   ALIGNOF_GUINT16, xfconf_g_value_get_uint16);
+                    /* uint16 is stored as uint */
+                    SET_STRUCT_VAL(guint16, G_TYPE_UINT,
+                                   ALIGNOF_GUINT16, g_value_get_uint);
                 } else if(XFCONF_TYPE_INT16 == member_types[i]) {
-                    SET_STRUCT_VAL(gint16, XFCONF_TYPE_INT16,
-                                   ALIGNOF_GINT16, xfconf_g_value_get_int16);
+                    /* int16 is stored as int */
+                    SET_STRUCT_VAL(gint16, G_TYPE_INT,
+                                   ALIGNOF_GINT16, g_value_get_int);
                 } else {
 #ifdef XFCONF_ENABLE_CHECKS
                     g_warning("Unable to handle value type %d (%s) when " \
@@ -1703,9 +1809,11 @@
 
             default:
                 if(XFCONF_TYPE_UINT16 == member_types[i]) {
+                    /* _set_arrayv() will convert these */
                     GET_STRUCT_VAL(guint16, XFCONF_TYPE_UINT16,
                                    ALIGNOF_GUINT16, xfconf_g_value_set_uint16);
                 } else if(XFCONF_TYPE_INT16 == member_types[i]) {
+                    /* _set_arrayv() will convert these */
                     GET_STRUCT_VAL(gint16, XFCONF_TYPE_INT16,
                                    ALIGNOF_GINT16, xfconf_g_value_set_int16);
                 } else {

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to