00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "dbus-gtest.h"
00027 #include "dbus-gvalue.h"
00028 #include "dbus-gsignature.h"
00029 #include "dbus-gobject.h"
00030 #include "dbus-gvalue-utils.h"
00031 #include "dbus/dbus-glib.h"
00032 #include <string.h>
00033 #include <glib.h>
00034 #include <glib/gi18n.h>
00035 #include "dbus/dbus-signature.h"
00036
00037 static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
00038 DBusMessageIter *iter,
00039 GValue *value,
00040 GError **error);
00041
00042
00043 static gboolean marshal_basic (DBusMessageIter *iter,
00044 const GValue *value);
00045 static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
00046 DBusMessageIter *iter,
00047 GValue *value,
00048 GError **error);
00049 static gboolean marshal_strv (DBusMessageIter *iter,
00050 const GValue *value);
00051 static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
00052 DBusMessageIter *iter,
00053 GValue *value,
00054 GError **error);
00055 static gboolean marshal_valuearray (DBusMessageIter *iter,
00056 const GValue *value);
00057 static gboolean demarshal_valuearray (DBusGValueMarshalCtx *context,
00058 DBusMessageIter *iter,
00059 GValue *value,
00060 GError **error);
00061 static gboolean marshal_variant (DBusMessageIter *iter,
00062 const GValue *value);
00063 static gboolean demarshal_variant (DBusGValueMarshalCtx *context,
00064 DBusMessageIter *iter,
00065 GValue *value,
00066 GError **error);
00067 static gboolean marshal_proxy (DBusMessageIter *iter,
00068 const GValue *value);
00069 static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
00070 DBusMessageIter *iter,
00071 GValue *value,
00072 GError **error);
00073 static gboolean marshal_object_path (DBusMessageIter *iter,
00074 const GValue *value);
00075 static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
00076 DBusMessageIter *iter,
00077 GValue *value,
00078 GError **error);
00079 static gboolean marshal_object (DBusMessageIter *iter,
00080 const GValue *value);
00081 static gboolean demarshal_object (DBusGValueMarshalCtx *context,
00082 DBusMessageIter *iter,
00083 GValue *value,
00084 GError **error);
00085 static gboolean marshal_map (DBusMessageIter *iter,
00086 const GValue *value);
00087 static gboolean demarshal_map (DBusGValueMarshalCtx *context,
00088 DBusMessageIter *iter,
00089 GValue *value,
00090 GError **error);
00091
00092 static gboolean marshal_collection (DBusMessageIter *iter,
00093 const GValue *value);
00094 static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
00095 const GValue *value);
00096 static gboolean marshal_collection_array (DBusMessageIter *iter,
00097 const GValue *value);
00098 static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
00099 DBusMessageIter *iter,
00100 GValue *value,
00101 GError **error);
00102 static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
00103 DBusMessageIter *iter,
00104 GValue *value,
00105 GError **error);
00106 static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
00107 DBusMessageIter *iter,
00108 GValue *value,
00109 GError **error);
00110 static gboolean marshal_struct (DBusMessageIter *iter,
00111 const GValue *value);
00112 static gboolean demarshal_struct (DBusGValueMarshalCtx *context,
00113 DBusMessageIter *iter,
00114 GValue *value,
00115 GError **error);
00116
00117
00118 typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
00119 const GValue *value);
00120 typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
00121 DBusMessageIter *iter,
00122 GValue *value,
00123 GError **error);
00124
00125 typedef struct {
00126 DBusGValueMarshalFunc marshaller;
00127 DBusGValueDemarshalFunc demarshaller;
00128 } DBusGTypeMarshalVtable;
00129
00130 typedef struct {
00131 const char *sig;
00132 const DBusGTypeMarshalVtable *vtable;
00133 } DBusGTypeMarshalData;
00134
00135 static GQuark
00136 dbus_g_type_metadata_data_quark ()
00137 {
00138 static GQuark quark;
00139 if (!quark)
00140 quark = g_quark_from_static_string ("DBusGTypeMetaData");
00141
00142 return quark;
00143 }
00144
00145 static void
00146 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
00147 {
00148 g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
00149 }
00150
00151 static void
00152 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
00153 {
00154 set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
00155 }
00156
00157 void
00158 _dbus_g_value_types_init (void)
00159 {
00160 static gboolean types_initialized;
00161
00162 static const DBusGTypeMarshalVtable basic_vtable = {
00163 marshal_basic,
00164 demarshal_basic
00165 };
00166
00167 if (types_initialized)
00168 return;
00169
00170 dbus_g_type_specialized_init ();
00171 _dbus_g_type_specialized_builtins_init ();
00172
00173
00174 {
00175 static const DBusGTypeMarshalData typedata = {
00176 DBUS_TYPE_BOOLEAN_AS_STRING,
00177 &basic_vtable,
00178 };
00179 register_basic (DBUS_TYPE_BOOLEAN, &typedata);
00180 }
00181 {
00182 static const DBusGTypeMarshalData typedata = {
00183 DBUS_TYPE_BYTE_AS_STRING,
00184 &basic_vtable,
00185 };
00186 register_basic (DBUS_TYPE_BYTE, &typedata);
00187 }
00188 {
00189 static const DBusGTypeMarshalData typedata = {
00190 DBUS_TYPE_INT16_AS_STRING,
00191 &basic_vtable,
00192 };
00193 register_basic (DBUS_TYPE_INT16, &typedata);
00194 }
00195 {
00196 static const DBusGTypeMarshalData typedata = {
00197 DBUS_TYPE_UINT16_AS_STRING,
00198 &basic_vtable,
00199 };
00200 register_basic (DBUS_TYPE_UINT16, &typedata);
00201 }
00202 {
00203 static const DBusGTypeMarshalData typedata = {
00204 DBUS_TYPE_UINT32_AS_STRING,
00205 &basic_vtable,
00206 };
00207 register_basic (DBUS_TYPE_UINT32, &typedata);
00208 }
00209 {
00210 static const DBusGTypeMarshalData typedata = {
00211 DBUS_TYPE_INT32_AS_STRING,
00212 &basic_vtable,
00213 };
00214 register_basic (DBUS_TYPE_INT32, &typedata);
00215 }
00216 {
00217 static const DBusGTypeMarshalData typedata = {
00218 DBUS_TYPE_UINT64_AS_STRING,
00219 &basic_vtable,
00220 };
00221 register_basic (DBUS_TYPE_UINT64, &typedata);
00222 }
00223 {
00224 static const DBusGTypeMarshalData typedata = {
00225 DBUS_TYPE_INT64_AS_STRING,
00226 &basic_vtable,
00227 };
00228 register_basic (DBUS_TYPE_INT64, &typedata);
00229 }
00230 {
00231 static const DBusGTypeMarshalData typedata = {
00232 DBUS_TYPE_DOUBLE_AS_STRING,
00233 &basic_vtable,
00234 };
00235 register_basic (DBUS_TYPE_DOUBLE, &typedata);
00236 }
00237 {
00238 static const DBusGTypeMarshalData typedata = {
00239 DBUS_TYPE_STRING_AS_STRING,
00240 &basic_vtable,
00241 };
00242 register_basic (DBUS_TYPE_STRING, &typedata);
00243 }
00244
00245 {
00246 static const DBusGTypeMarshalData typedata = {
00247 DBUS_TYPE_BYTE_AS_STRING,
00248 &basic_vtable,
00249 };
00250 set_type_metadata (G_TYPE_CHAR, &typedata);
00251 }
00252 {
00253 static const DBusGTypeMarshalData typedata = {
00254 DBUS_TYPE_INT32_AS_STRING,
00255 &basic_vtable,
00256 };
00257 set_type_metadata (G_TYPE_LONG, &typedata);
00258 }
00259 {
00260 static const DBusGTypeMarshalData typedata = {
00261 DBUS_TYPE_UINT32_AS_STRING,
00262 &basic_vtable,
00263 };
00264 set_type_metadata (G_TYPE_ULONG, &typedata);
00265 }
00266 {
00267 static const DBusGTypeMarshalData typedata = {
00268 DBUS_TYPE_DOUBLE_AS_STRING,
00269 &basic_vtable,
00270 };
00271 set_type_metadata (G_TYPE_FLOAT, &typedata);
00272 }
00273
00274
00275 {
00276 static const DBusGTypeMarshalVtable vtable = {
00277 marshal_variant,
00278 demarshal_variant
00279 };
00280 static const DBusGTypeMarshalData typedata = {
00281 DBUS_TYPE_VARIANT_AS_STRING,
00282 &vtable
00283 };
00284 set_type_metadata (G_TYPE_VALUE, &typedata);
00285 };
00286 {
00287 static const DBusGTypeMarshalVtable vtable = {
00288 marshal_strv,
00289 demarshal_strv
00290 };
00291 static const DBusGTypeMarshalData typedata = {
00292 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
00293 &vtable
00294 };
00295 set_type_metadata (G_TYPE_STRV, &typedata);
00296 };
00297
00298
00299
00300 {
00301 static const DBusGTypeMarshalVtable vtable = {
00302 marshal_proxy,
00303 demarshal_proxy
00304 };
00305 static const DBusGTypeMarshalData typedata = {
00306 DBUS_TYPE_OBJECT_PATH_AS_STRING,
00307 &vtable
00308 };
00309 set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
00310 }
00311
00312 {
00313 static const DBusGTypeMarshalVtable vtable = {
00314 marshal_object_path,
00315 demarshal_object_path
00316 };
00317 static const DBusGTypeMarshalData typedata = {
00318 DBUS_TYPE_OBJECT_PATH_AS_STRING,
00319 &vtable
00320 };
00321 set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
00322 }
00323
00324 {
00325 static const DBusGTypeMarshalVtable vtable = {
00326 marshal_object,
00327 demarshal_object
00328 };
00329 static const DBusGTypeMarshalData typedata = {
00330 DBUS_TYPE_OBJECT_PATH_AS_STRING,
00331 &vtable
00332 };
00333 set_type_metadata (G_TYPE_OBJECT, &typedata);
00334 }
00335
00336 types_initialized = TRUE;
00337 }
00338
00344 GType
00345 dbus_g_object_path_get_g_type (void)
00346 {
00347 static GType type_id = 0;
00348
00349 if (!type_id)
00350 type_id = g_boxed_type_register_static ("DBusGObjectPath",
00351 (GBoxedCopyFunc) g_strdup,
00352 (GBoxedFreeFunc) g_free);
00353 return type_id;
00354 }
00355
00356
00357 char *
00358 _dbus_gtype_to_signature (GType gtype)
00359 {
00360 char *ret;
00361 DBusGTypeMarshalData *typedata;
00362
00363 if (dbus_g_type_is_collection (gtype))
00364 {
00365 GType elt_gtype;
00366 char *subsig;
00367
00368 elt_gtype = dbus_g_type_get_collection_specialization (gtype);
00369 subsig = _dbus_gtype_to_signature (elt_gtype);
00370 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
00371 g_free (subsig);
00372 }
00373 else if (dbus_g_type_is_map (gtype))
00374 {
00375 GType key_gtype;
00376 GType val_gtype;
00377 char *key_subsig;
00378 char *val_subsig;
00379
00380 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00381 val_gtype = dbus_g_type_get_map_value_specialization (gtype);
00382 key_subsig = _dbus_gtype_to_signature (key_gtype);
00383 val_subsig = _dbus_gtype_to_signature (val_gtype);
00384 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING, key_subsig, val_subsig, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, NULL);
00385 g_free (key_subsig);
00386 g_free (val_subsig);
00387 }
00388 else if (dbus_g_type_is_struct (gtype))
00389 {
00390 guint i, size;
00391 GString *sig;
00392 size = dbus_g_type_get_struct_size (gtype);
00393 sig = g_string_sized_new (size+2);
00394 g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
00395 for (i = 0; i < size; i++)
00396 {
00397 gchar *subsig;
00398 subsig = _dbus_gtype_to_signature (
00399 dbus_g_type_get_struct_member_type (gtype, i));
00400 g_string_append (sig, subsig);
00401 g_free (subsig);
00402 }
00403 g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
00404 ret = g_string_free (sig, FALSE);
00405 }
00406 else
00407 {
00408 typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
00409 if (typedata == NULL)
00410 return NULL;
00411 ret = g_strdup (typedata->sig);
00412 }
00413 return ret;
00414 }
00415
00416 char *
00417 _dbus_gvalue_to_signature (const GValue *val)
00418 {
00419 GType gtype;
00420
00421 gtype = G_VALUE_TYPE (val);
00422 if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
00423 {
00424 GString *str;
00425 guint i;
00426 GValueArray *array;
00427
00428 array = g_value_get_boxed (val);
00429
00430 str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
00431 for (i = 0; i < array->n_values; i++)
00432 {
00433 char *sig;
00434 sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
00435 g_string_append (str, sig);
00436 g_free (sig);
00437 }
00438 g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
00439
00440 return g_string_free (str, FALSE);
00441 }
00442 else
00443 return _dbus_gtype_to_signature (gtype);
00444 }
00445
00446 static gboolean
00447 demarshal_basic (DBusGValueMarshalCtx *context,
00448 DBusMessageIter *iter,
00449 GValue *value,
00450 GError **error)
00451 {
00452 int current_type;
00453
00454 current_type = dbus_message_iter_get_arg_type (iter);
00455 g_assert (dbus_type_is_basic (current_type));
00456
00457 switch (current_type)
00458 {
00459 case DBUS_TYPE_BOOLEAN:
00460 {
00461 dbus_bool_t bool;
00462 dbus_message_iter_get_basic (iter, &bool);
00463 g_value_set_boolean (value, bool);
00464 return TRUE;
00465 }
00466 case DBUS_TYPE_BYTE:
00467 {
00468 unsigned char byte;
00469 dbus_message_iter_get_basic (iter, &byte);
00470 g_value_set_uchar (value, byte);
00471 return TRUE;
00472 }
00473 case DBUS_TYPE_INT32:
00474 {
00475 dbus_int32_t intval;
00476 dbus_message_iter_get_basic (iter, &intval);
00477 g_value_set_int (value, intval);
00478 return TRUE;
00479 }
00480 case DBUS_TYPE_UINT32:
00481 {
00482 dbus_uint32_t intval;
00483 dbus_message_iter_get_basic (iter, &intval);
00484 g_value_set_uint (value, intval);
00485 return TRUE;
00486 }
00487 case DBUS_TYPE_INT64:
00488 {
00489 dbus_int64_t intval;
00490 dbus_message_iter_get_basic (iter, &intval);
00491 g_value_set_int64 (value, intval);
00492 return TRUE;
00493 }
00494 case DBUS_TYPE_UINT64:
00495 {
00496 dbus_uint64_t intval;
00497 dbus_message_iter_get_basic (iter, &intval);
00498 g_value_set_uint64 (value, intval);
00499 return TRUE;
00500 }
00501 case DBUS_TYPE_DOUBLE:
00502 {
00503 double dval;
00504 dbus_message_iter_get_basic (iter, &dval);
00505 g_value_set_double (value, dval);
00506 return TRUE;
00507 }
00508 case DBUS_TYPE_INT16:
00509 {
00510 dbus_int16_t v;
00511 dbus_message_iter_get_basic (iter, &v);
00512 g_value_set_int (value, v);
00513 return TRUE;
00514 }
00515 case DBUS_TYPE_UINT16:
00516 {
00517 dbus_uint16_t v;
00518 dbus_message_iter_get_basic (iter, &v);
00519 g_value_set_uint (value, v);
00520 return TRUE;
00521 }
00522 case DBUS_TYPE_STRING:
00523 {
00524 const char *s;
00525 dbus_message_iter_get_basic (iter, &s);
00526 g_value_set_string (value, s);
00527 return TRUE;
00528 }
00529 default:
00530 g_assert_not_reached ();
00531 return FALSE;
00532 }
00533 }
00534
00535 static gboolean
00536 demarshal_static_variant (DBusGValueMarshalCtx *context,
00537 DBusMessageIter *iter,
00538 GValue *value,
00539 GError **error)
00540 {
00541 char *sig;
00542 int current_type;
00543 DBusMessageIter subiter;
00544 GType variant_type;
00545
00546 current_type = dbus_message_iter_get_arg_type (iter);
00547 dbus_message_iter_recurse (iter, &subiter);
00548 sig = dbus_message_iter_get_signature (&subiter);
00549
00550 variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
00551 if (variant_type != G_TYPE_INVALID)
00552 {
00553 g_value_init (value, variant_type);
00554
00555 if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
00556 {
00557 dbus_free (sig);
00558 return FALSE;
00559 }
00560 }
00561 dbus_free (sig);
00562 return TRUE;
00563 }
00564
00565 static gboolean
00566 demarshal_variant (DBusGValueMarshalCtx *context,
00567 DBusMessageIter *iter,
00568 GValue *value,
00569 GError **error)
00570
00571 {
00572 GValue *variant_val;
00573 variant_val = g_new0 (GValue, 1);
00574
00575 if (!demarshal_static_variant (context, iter, variant_val, error))
00576 return FALSE;
00577
00578 g_value_set_boxed_take_ownership (value, variant_val);
00579 return TRUE;
00580 }
00581
00582 static gboolean
00583 demarshal_proxy (DBusGValueMarshalCtx *context,
00584 DBusMessageIter *iter,
00585 GValue *value,
00586 GError **error)
00587 {
00588 DBusGProxy *new_proxy;
00589 const char *objpath;
00590 int current_type;
00591
00592 current_type = dbus_message_iter_get_arg_type (iter);
00593 if (current_type != DBUS_TYPE_OBJECT_PATH)
00594 {
00595 g_set_error (error,
00596 DBUS_GERROR,
00597 DBUS_GERROR_INVALID_ARGS,
00598 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00599 return FALSE;
00600 }
00601
00602 g_assert (context->proxy != NULL);
00603
00604 dbus_message_iter_get_basic (iter, &objpath);
00605
00606 new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
00607 g_value_set_object_take_ownership (value, new_proxy);
00608
00609 return TRUE;
00610 }
00611
00612 static gboolean
00613 demarshal_object_path (DBusGValueMarshalCtx *context,
00614 DBusMessageIter *iter,
00615 GValue *value,
00616 GError **error)
00617 {
00618 const char *objpath;
00619 int current_type;
00620
00621 current_type = dbus_message_iter_get_arg_type (iter);
00622 if (current_type != DBUS_TYPE_OBJECT_PATH)
00623 {
00624 g_set_error (error,
00625 DBUS_GERROR,
00626 DBUS_GERROR_INVALID_ARGS,
00627 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00628 return FALSE;
00629 }
00630
00631 dbus_message_iter_get_basic (iter, &objpath);
00632
00633 g_value_set_boxed_take_ownership (value, g_strdup (objpath));
00634
00635 return TRUE;
00636 }
00637
00638 static gboolean
00639 demarshal_object (DBusGValueMarshalCtx *context,
00640 DBusMessageIter *iter,
00641 GValue *value,
00642 GError **error)
00643 {
00644 const char *objpath;
00645 int current_type;
00646 GObject *obj;
00647
00648 current_type = dbus_message_iter_get_arg_type (iter);
00649 if (current_type != DBUS_TYPE_OBJECT_PATH)
00650 {
00651 g_set_error (error,
00652 DBUS_GERROR,
00653 DBUS_GERROR_INVALID_ARGS,
00654 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00655 return FALSE;
00656 }
00657 g_assert (context->proxy == NULL);
00658
00659 dbus_message_iter_get_basic (iter, &objpath);
00660
00661 obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
00662 if (obj == NULL)
00663 {
00664 g_set_error (error,
00665 DBUS_GERROR,
00666 DBUS_GERROR_INVALID_ARGS,
00667 _("Unregistered object at path '%s'"),
00668 objpath);
00669 return FALSE;
00670 }
00671 g_value_set_object (value, obj);
00672
00673 return TRUE;
00674 }
00675
00676 static gboolean
00677 demarshal_strv (DBusGValueMarshalCtx *context,
00678 DBusMessageIter *iter,
00679 GValue *value,
00680 GError **error)
00681 {
00682 DBusMessageIter subiter;
00683 int current_type;
00684 char **ret;
00685 int len;
00686 int i;
00687
00688 current_type = dbus_message_iter_get_arg_type (iter);
00689 if (current_type != DBUS_TYPE_ARRAY)
00690 {
00691 g_set_error (error,
00692 DBUS_GERROR,
00693 DBUS_GERROR_INVALID_ARGS,
00694 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00695 return FALSE;
00696 }
00697
00698 dbus_message_iter_recurse (iter, &subiter);
00699
00700 current_type = dbus_message_iter_get_arg_type (&subiter);
00701 if (current_type != DBUS_TYPE_INVALID
00702 && current_type != DBUS_TYPE_STRING)
00703 {
00704 g_set_error (error,
00705 DBUS_GERROR,
00706 DBUS_GERROR_INVALID_ARGS,
00707 _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
00708 return FALSE;
00709 }
00710
00711 len = dbus_message_iter_get_array_len (&subiter);
00712 g_assert (len >= 0);
00713 ret = g_malloc (sizeof (char *) * (len + 1));
00714
00715 i = 0;
00716 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00717 {
00718 g_assert (i < len);
00719 g_assert (current_type == DBUS_TYPE_STRING);
00720
00721 dbus_message_iter_get_basic (&subiter, &(ret[i]));
00722 ret[i] = g_strdup (ret[i]);
00723
00724 dbus_message_iter_next (&subiter);
00725 i++;
00726 }
00727 ret[i] = NULL;
00728 g_value_set_boxed_take_ownership (value, ret);
00729
00730 return TRUE;
00731 }
00732
00733 static gboolean
00734 demarshal_valuearray (DBusGValueMarshalCtx *context,
00735 DBusMessageIter *iter,
00736 GValue *value,
00737 GError **error)
00738 {
00739 int current_type;
00740 GValueArray *ret;
00741 DBusMessageIter subiter;
00742
00743 current_type = dbus_message_iter_get_arg_type (iter);
00744 if (current_type != DBUS_TYPE_STRUCT)
00745 {
00746 g_set_error (error,
00747 DBUS_GERROR,
00748 DBUS_GERROR_INVALID_ARGS,
00749 _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00750 return FALSE;
00751 }
00752
00753 dbus_message_iter_recurse (iter, &subiter);
00754
00755 ret = g_value_array_new (12);
00756
00757 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00758 {
00759 GValue *val;
00760 GType elt_type;
00761 char *current_sig;
00762
00763 g_value_array_append (ret, NULL);
00764 val = g_value_array_get_nth (ret, ret->n_values - 1);
00765
00766 current_sig = dbus_message_iter_get_signature (&subiter);
00767 elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
00768
00769 if (elt_type == G_TYPE_INVALID)
00770 {
00771 g_value_array_free (ret);
00772 g_set_error (error,
00773 DBUS_GERROR,
00774 DBUS_GERROR_INVALID_ARGS,
00775 _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00776 dbus_free (current_sig);
00777 return FALSE;
00778 }
00779 dbus_free (current_sig);
00780
00781 g_value_init (val, elt_type);
00782
00783 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00784 {
00785 g_value_array_free (ret);
00786 return FALSE;
00787 }
00788
00789 dbus_message_iter_next (&subiter);
00790 }
00791
00792 g_value_set_boxed_take_ownership (value, ret);
00793
00794 return TRUE;
00795 }
00796
00797 static gboolean
00798 demarshal_map (DBusGValueMarshalCtx *context,
00799 DBusMessageIter *iter,
00800 GValue *value,
00801 GError **error)
00802 {
00803 GType gtype;
00804 DBusMessageIter subiter;
00805 int current_type;
00806 gpointer ret;
00807 GType key_gtype;
00808 GType value_gtype;
00809 DBusGTypeSpecializedAppendContext appendctx;
00810
00811 current_type = dbus_message_iter_get_arg_type (iter);
00812 if (current_type != DBUS_TYPE_ARRAY)
00813 {
00814 g_set_error (error,
00815 DBUS_GERROR,
00816 DBUS_GERROR_INVALID_ARGS,
00817 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00818 return FALSE;
00819 }
00820
00821 gtype = G_VALUE_TYPE (value);
00822
00823 dbus_message_iter_recurse (iter, &subiter);
00824
00825 current_type = dbus_message_iter_get_arg_type (&subiter);
00826 if (current_type != DBUS_TYPE_INVALID
00827 && current_type != DBUS_TYPE_DICT_ENTRY)
00828 {
00829 g_set_error (error,
00830 DBUS_GERROR,
00831 DBUS_GERROR_INVALID_ARGS,
00832 _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00833 return FALSE;
00834 }
00835
00836 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00837 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00838
00839 ret = dbus_g_type_specialized_construct (gtype);
00840 g_value_set_boxed_take_ownership (value, ret);
00841
00842 dbus_g_type_specialized_init_append (value, &appendctx);
00843
00844 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00845 {
00846 DBusMessageIter entry_iter;
00847 GValue key_value = {0,};
00848 GValue value_value = {0,};
00849
00850 current_type = dbus_message_iter_get_arg_type (&subiter);
00851 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00852
00853 dbus_message_iter_recurse (&subiter, &entry_iter);
00854
00855 g_value_init (&key_value, key_gtype);
00856 if (!_dbus_gvalue_demarshal (context,
00857 &entry_iter,
00858 &key_value,
00859 error))
00860 return FALSE;
00861
00862 dbus_message_iter_next (&entry_iter);
00863
00864 g_value_init (&value_value, value_gtype);
00865 if (!_dbus_gvalue_demarshal (context,
00866 &entry_iter,
00867 &value_value,
00868 error))
00869 return FALSE;
00870
00871 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00872
00873
00874 dbus_message_iter_next (&subiter);
00875 }
00876
00877 return TRUE;
00878 }
00879
00880 static gboolean
00881 demarshal_struct (DBusGValueMarshalCtx *context,
00882 DBusMessageIter *iter,
00883 GValue *value,
00884 GError **error)
00885 {
00886 int current_type;
00887 DBusMessageIter subiter;
00888 guint i, size;
00889 GValue val = {0,};
00890 GType elt_type;
00891
00892 current_type = dbus_message_iter_get_arg_type (iter);
00893 if (current_type != DBUS_TYPE_STRUCT)
00894 {
00895 g_set_error (error,
00896 DBUS_GERROR,
00897 DBUS_GERROR_INVALID_ARGS,
00898 _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00899 return FALSE;
00900 }
00901
00902 dbus_message_iter_recurse (iter, &subiter);
00903
00904 g_value_set_boxed_take_ownership (value,
00905 dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
00906
00907 size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
00908
00909 for (i=0; i < size; i++)
00910 {
00911
00912 elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
00913 if (elt_type == G_TYPE_INVALID)
00914 {
00915 g_value_unset (value);
00916 g_set_error (error,
00917 DBUS_GERROR,
00918 DBUS_GERROR_INVALID_ARGS,
00919 _("Couldn't demarshal argument, "
00920 "struct type %s has no member %d"),
00921 g_type_name (G_VALUE_TYPE(value)), i);
00922 return FALSE;
00923 }
00924
00925 g_value_init (&val, elt_type);
00926
00927 if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
00928 {
00929 g_value_unset (&val);
00930 g_value_unset (value);
00931 return FALSE;
00932 }
00933 if (!dbus_g_type_struct_set_member (value, i, &val))
00934 {
00935 g_value_unset (&val);
00936 g_value_unset (value);
00937 return FALSE;
00938 }
00939
00940 dbus_message_iter_next (&subiter);
00941 g_value_unset (&val);
00942 }
00943
00944 g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
00945
00946 return TRUE;
00947 }
00948
00949
00950 static DBusGValueDemarshalFunc
00951 get_type_demarshaller (GType type)
00952 {
00953 DBusGTypeMarshalData *typedata;
00954
00955 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00956 if (typedata == NULL)
00957 {
00958 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00959 return demarshal_valuearray;
00960 if (dbus_g_type_is_collection (type))
00961 return demarshal_collection;
00962 if (dbus_g_type_is_map (type))
00963 return demarshal_map;
00964 if (dbus_g_type_is_struct (type))
00965 return demarshal_struct;
00966
00967 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00968 return NULL;
00969 }
00970 g_assert (typedata->vtable);
00971 return typedata->vtable->demarshaller;
00972 }
00973
00974 static gboolean
00975 demarshal_collection (DBusGValueMarshalCtx *context,
00976 DBusMessageIter *iter,
00977 GValue *value,
00978 GError **error)
00979 {
00980 GType coltype;
00981 GType subtype;
00982
00983 coltype = G_VALUE_TYPE (value);
00984 subtype = dbus_g_type_get_collection_specialization (coltype);
00985
00986 if (_dbus_g_type_is_fixed (subtype))
00987 return demarshal_collection_array (context, iter, value, error);
00988 else
00989 return demarshal_collection_ptrarray (context, iter, value, error);
00990 }
00991
00992 static gboolean
00993 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
00994 DBusMessageIter *iter,
00995 GValue *value,
00996 GError **error)
00997 {
00998 GType coltype;
00999 GType subtype;
01000 gpointer instance;
01001 DBusGTypeSpecializedAppendContext ctx;
01002 DBusGValueDemarshalFunc demarshaller;
01003 DBusMessageIter subiter;
01004 int current_type;
01005
01006 current_type = dbus_message_iter_get_arg_type (iter);
01007
01008 if (current_type != DBUS_TYPE_ARRAY)
01009 {
01010 g_set_error (error,
01011 DBUS_GERROR,
01012 DBUS_GERROR_INVALID_ARGS,
01013 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
01014 return FALSE;
01015 }
01016
01017 dbus_message_iter_recurse (iter, &subiter);
01018
01019 coltype = G_VALUE_TYPE (value);
01020 subtype = dbus_g_type_get_collection_specialization (coltype);
01021
01022 demarshaller = get_type_demarshaller (subtype);
01023
01024 if (!demarshaller)
01025 {
01026 g_set_error (error,
01027 DBUS_GERROR,
01028 DBUS_GERROR_INVALID_ARGS,
01029 _("No demarshaller registered for type \"%s\" of collection \"%s\""),
01030 g_type_name (coltype),
01031 g_type_name (subtype));
01032 return FALSE;
01033 }
01034
01035 instance = dbus_g_type_specialized_construct (coltype);
01036 g_value_set_boxed_take_ownership (value, instance);
01037
01038 dbus_g_type_specialized_init_append (value, &ctx);
01039
01040 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
01041 {
01042 GValue eltval = {0, };
01043
01044 g_value_init (&eltval, subtype);
01045
01046 if (!demarshaller (context, &subiter, &eltval, error))
01047 {
01048 dbus_g_type_specialized_collection_end_append (&ctx);
01049 g_value_unset (value);
01050 return FALSE;
01051 }
01052 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01053
01054 dbus_message_iter_next (&subiter);
01055 }
01056 dbus_g_type_specialized_collection_end_append (&ctx);
01057
01058 return TRUE;
01059 }
01060
01061 static gboolean
01062 demarshal_collection_array (DBusGValueMarshalCtx *context,
01063 DBusMessageIter *iter,
01064 GValue *value,
01065 GError **error)
01066 {
01067 DBusMessageIter subiter;
01068 GArray *ret;
01069 GType elt_gtype;
01070 int elt_size;
01071 void *msgarray;
01072 int msgarray_len;
01073
01074 dbus_message_iter_recurse (iter, &subiter);
01075
01076 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01077 g_assert (elt_gtype != G_TYPE_INVALID);
01078 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01079
01080 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01081
01082 ret = g_array_new (FALSE, TRUE, elt_size);
01083
01084 msgarray = NULL;
01085 dbus_message_iter_get_fixed_array (&subiter,
01086 &msgarray,
01087 &msgarray_len);
01088 g_assert (msgarray != NULL || msgarray_len == 0);
01089
01090 if (msgarray_len)
01091 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
01092
01093 g_value_set_boxed_take_ownership (value, ret);
01094
01095 return TRUE;
01096 }
01097
01098 gboolean
01099 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
01100 DBusMessageIter *iter,
01101 GValue *value,
01102 GError **error)
01103 {
01104 GType gtype;
01105 DBusGValueDemarshalFunc demarshaller;
01106
01107 gtype = G_VALUE_TYPE (value);
01108
01109 demarshaller = get_type_demarshaller (gtype);
01110
01111 if (demarshaller == NULL)
01112 {
01113 g_set_error (error,
01114 DBUS_GERROR,
01115 DBUS_GERROR_INVALID_ARGS,
01116 _("No demarshaller registered for type \"%s\""),
01117 g_type_name (gtype));
01118 return FALSE;
01119 }
01120
01121 return demarshaller (context, iter, value, error);
01122 }
01123
01124 gboolean
01125 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
01126 DBusMessageIter *iter,
01127 GValue *value,
01128 GError **error)
01129 {
01130 return demarshal_static_variant (context, iter, value, error);
01131 }
01132
01133 GValueArray *
01134 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
01135 DBusMessage *message,
01136 guint n_types,
01137 const GType *types,
01138 GError **error)
01139 {
01140 GValueArray *ret;
01141 DBusMessageIter iter;
01142 int current_type;
01143 guint index_;
01144
01145 ret = g_value_array_new (6);
01146
01147 dbus_message_iter_init (message, &iter);
01148 index_ = 0;
01149 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01150 {
01151 GValue *value;
01152 GType gtype;
01153
01154 if (index_ >= n_types)
01155 {
01156 g_set_error (error, DBUS_GERROR,
01157 DBUS_GERROR_INVALID_ARGS,
01158 _("Too many arguments in message"));
01159 goto lose;
01160 }
01161
01162 g_value_array_append (ret, NULL);
01163 value = g_value_array_get_nth (ret, index_);
01164
01165 gtype = types[index_];
01166 g_value_init (value, gtype);
01167
01168 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01169 goto lose;
01170 dbus_message_iter_next (&iter);
01171 index_++;
01172 }
01173 if (index_ < n_types)
01174 {
01175 g_set_error (error, DBUS_GERROR,
01176 DBUS_GERROR_INVALID_ARGS,
01177 _("Too few arguments in message"));
01178 goto lose;
01179 }
01180
01181 return ret;
01182 lose:
01183 g_value_array_free (ret);
01184 return NULL;
01185 }
01186
01187 static gboolean
01188 marshal_basic (DBusMessageIter *iter, const GValue *value)
01189 {
01190 GType value_type;
01191
01192 value_type = G_VALUE_TYPE (value);
01193
01194 switch (value_type)
01195 {
01196 case G_TYPE_CHAR:
01197 {
01198 char b = g_value_get_char (value);
01199 if (!dbus_message_iter_append_basic (iter,
01200 DBUS_TYPE_BYTE,
01201 &b))
01202 goto nomem;
01203 }
01204 return TRUE;
01205 case G_TYPE_UCHAR:
01206 {
01207 unsigned char b = g_value_get_uchar (value);
01208 if (!dbus_message_iter_append_basic (iter,
01209 DBUS_TYPE_BYTE,
01210 &b))
01211 goto nomem;
01212 }
01213 return TRUE;
01214 case G_TYPE_BOOLEAN:
01215 {
01216 dbus_bool_t b = g_value_get_boolean (value);
01217 if (!dbus_message_iter_append_basic (iter,
01218 DBUS_TYPE_BOOLEAN,
01219 &b))
01220 goto nomem;
01221 }
01222 return TRUE;
01223 case G_TYPE_INT:
01224 {
01225 dbus_int32_t v = g_value_get_int (value);
01226 if (!dbus_message_iter_append_basic (iter,
01227 DBUS_TYPE_INT32,
01228 &v))
01229 goto nomem;
01230 }
01231 return TRUE;
01232 case G_TYPE_UINT:
01233 {
01234 dbus_uint32_t v = g_value_get_uint (value);
01235 if (!dbus_message_iter_append_basic (iter,
01236 DBUS_TYPE_UINT32,
01237 &v))
01238 goto nomem;
01239 }
01240 return TRUE;
01241 case G_TYPE_LONG:
01242 {
01243 dbus_int32_t v = g_value_get_long (value);
01244 if (!dbus_message_iter_append_basic (iter,
01245 DBUS_TYPE_INT32,
01246 &v))
01247 goto nomem;
01248 }
01249 return TRUE;
01250 case G_TYPE_ULONG:
01251 {
01252 dbus_uint32_t v = g_value_get_ulong (value);
01253 if (!dbus_message_iter_append_basic (iter,
01254 DBUS_TYPE_UINT32,
01255 &v))
01256 goto nomem;
01257 }
01258 return TRUE;
01259 case G_TYPE_INT64:
01260 {
01261 gint64 v = g_value_get_int64 (value);
01262 if (!dbus_message_iter_append_basic (iter,
01263 DBUS_TYPE_INT64,
01264 &v))
01265 goto nomem;
01266 }
01267 return TRUE;
01268 case G_TYPE_UINT64:
01269 {
01270 guint64 v = g_value_get_uint64 (value);
01271 if (!dbus_message_iter_append_basic (iter,
01272 DBUS_TYPE_UINT64,
01273 &v))
01274 goto nomem;
01275 }
01276 return TRUE;
01277 case G_TYPE_FLOAT:
01278 {
01279 double v = g_value_get_float (value);
01280
01281 if (!dbus_message_iter_append_basic (iter,
01282 DBUS_TYPE_DOUBLE,
01283 &v))
01284 goto nomem;
01285 }
01286 return TRUE;
01287 case G_TYPE_DOUBLE:
01288 {
01289 double v = g_value_get_double (value);
01290
01291 if (!dbus_message_iter_append_basic (iter,
01292 DBUS_TYPE_DOUBLE,
01293 &v))
01294 goto nomem;
01295 }
01296 return TRUE;
01297 case G_TYPE_STRING:
01298
01299 {
01300 const char *v = g_value_get_string (value);
01301 if (!v)
01302 v = "";
01303 if (!dbus_message_iter_append_basic (iter,
01304 DBUS_TYPE_STRING,
01305 &v))
01306 goto nomem;
01307 }
01308 return TRUE;
01309
01310 default:
01311 {
01312 g_assert_not_reached ();
01313 return FALSE;
01314 }
01315 }
01316
01317 nomem:
01318 g_error ("no memory");
01319 return FALSE;
01320 }
01321
01322 static gboolean
01323 marshal_strv (DBusMessageIter *iter,
01324 const GValue *value)
01325 {
01326 DBusMessageIter subiter;
01327 char **array;
01328 char **elt;
01329 gboolean ret = FALSE;
01330
01331 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01332
01333 array = g_value_get_boxed (value);
01334
01335 if (!dbus_message_iter_open_container (iter,
01336 DBUS_TYPE_ARRAY,
01337 "s",
01338 &subiter))
01339 goto out;
01340
01341 if (array)
01342 {
01343 for (elt = array; *elt; elt++)
01344 {
01345 if (!dbus_message_iter_append_basic (&subiter,
01346 DBUS_TYPE_STRING,
01347 elt))
01348 goto out;
01349 }
01350 }
01351
01352 if (!dbus_message_iter_close_container (iter, &subiter))
01353 goto out;
01354 ret = TRUE;
01355 out:
01356 return ret;
01357 }
01358
01359 static gboolean
01360 marshal_valuearray (DBusMessageIter *iter,
01361 const GValue *value)
01362 {
01363 GValueArray *array;
01364 guint i;
01365 DBusMessageIter subiter;
01366
01367 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01368
01369 array = g_value_get_boxed (value);
01370
01371 if (!dbus_message_iter_open_container (iter,
01372 DBUS_TYPE_STRUCT,
01373 NULL,
01374 &subiter))
01375 goto oom;
01376
01377 if (array)
01378 {
01379 for (i = 0; i < array->n_values; i++)
01380 {
01381 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01382 return FALSE;
01383 }
01384 }
01385
01386 if (!dbus_message_iter_close_container (iter, &subiter))
01387 goto oom;
01388
01389 return TRUE;
01390 oom:
01391 g_error ("out of memory");
01392 return FALSE;
01393 }
01394
01395 static gboolean
01396 marshal_proxy (DBusMessageIter *iter,
01397 const GValue *value)
01398 {
01399 const char *path;
01400 DBusGProxy *proxy;
01401
01402 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01403
01404 proxy = g_value_get_object (value);
01405 path = dbus_g_proxy_get_path (proxy);
01406
01407 if (!dbus_message_iter_append_basic (iter,
01408 DBUS_TYPE_OBJECT_PATH,
01409 &path))
01410 return FALSE;
01411 return TRUE;
01412 }
01413
01414 static gboolean
01415 marshal_object_path (DBusMessageIter *iter,
01416 const GValue *value)
01417 {
01418 const char *path;
01419
01420 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01421
01422 path = (const char*) g_value_get_boxed (value);
01423
01424 if (!dbus_message_iter_append_basic (iter,
01425 DBUS_TYPE_OBJECT_PATH,
01426 &path))
01427 return FALSE;
01428 return TRUE;
01429 }
01430
01431 static gboolean
01432 marshal_object (DBusMessageIter *iter,
01433 const GValue *value)
01434 {
01435 const char *path;
01436 GObject *obj;
01437
01438 obj = g_value_get_object (value);
01439 path = _dbus_gobject_get_path (obj);
01440
01441 if (path == NULL)
01442
01443 return FALSE;
01444
01445 if (!dbus_message_iter_append_basic (iter,
01446 DBUS_TYPE_OBJECT_PATH,
01447 &path))
01448 return FALSE;
01449 return TRUE;
01450 }
01451
01452 struct DBusGLibHashMarshalData
01453 {
01454 const char *entry_sig;
01455 DBusMessageIter *iter;
01456 gboolean err;
01457 };
01458
01459 static void
01460 marshal_map_entry (const GValue *key,
01461 const GValue *value,
01462 gpointer data)
01463 {
01464 struct DBusGLibHashMarshalData *hashdata = data;
01465 DBusMessageIter subiter;
01466
01467 if (hashdata->err)
01468 return;
01469
01470 if (!dbus_message_iter_open_container (hashdata->iter,
01471 DBUS_TYPE_DICT_ENTRY,
01472 NULL,
01473 &subiter))
01474 goto lose;
01475
01476 if (!_dbus_gvalue_marshal (&subiter, key))
01477 goto lose;
01478
01479 if (!_dbus_gvalue_marshal (&subiter, value))
01480 goto lose;
01481
01482 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01483 goto lose;
01484
01485 return;
01486 lose:
01487 hashdata->err = TRUE;
01488 }
01489
01490 static gboolean
01491 marshal_map (DBusMessageIter *iter,
01492 const GValue *value)
01493 {
01494 GType gtype;
01495 DBusMessageIter arr_iter;
01496 gboolean ret;
01497 struct DBusGLibHashMarshalData hashdata;
01498 char *key_sig;
01499 char *value_sig;
01500 GType key_type;
01501 GType value_type;
01502 char *entry_sig;
01503 char *array_sig;
01504
01505 gtype = G_VALUE_TYPE (value);
01506
01507 ret = FALSE;
01508
01509 key_type = dbus_g_type_get_map_key_specialization (gtype);
01510 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01511 value_type = dbus_g_type_get_map_value_specialization (gtype);
01512 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01513
01514 key_sig = _dbus_gtype_to_signature (key_type);
01515 if (!key_sig)
01516 {
01517 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01518 return FALSE;
01519 }
01520 value_sig = _dbus_gtype_to_signature (value_type);
01521 if (!value_sig)
01522 {
01523 g_free (key_sig);
01524 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01525 return FALSE;
01526 }
01527 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01528 g_free (key_sig);
01529 g_free (value_sig);
01530 array_sig = g_strdup_printf ("%c%s%c",
01531 DBUS_DICT_ENTRY_BEGIN_CHAR,
01532 entry_sig,
01533 DBUS_DICT_ENTRY_END_CHAR);
01534 if (!dbus_message_iter_open_container (iter,
01535 DBUS_TYPE_ARRAY,
01536 array_sig,
01537 &arr_iter))
01538 goto lose;
01539
01540 hashdata.iter = &arr_iter;
01541 hashdata.err = FALSE;
01542 hashdata.entry_sig = entry_sig;
01543
01544 dbus_g_type_map_value_iterate (value,
01545 marshal_map_entry,
01546 &hashdata);
01547
01548 if (!dbus_message_iter_close_container (iter, &arr_iter))
01549 goto lose;
01550
01551 out:
01552 g_free (entry_sig);
01553 g_free (array_sig);
01554 return !hashdata.err;
01555 lose:
01556 hashdata.err = TRUE;
01557 goto out;
01558 }
01559
01560 static gboolean
01561 marshal_struct (DBusMessageIter *iter,
01562 const GValue *value)
01563 {
01564 GType gtype;
01565 DBusMessageIter subiter;
01566 gboolean ret;
01567 guint size, i;
01568 GValue val = {0,};
01569
01570 gtype = G_VALUE_TYPE (value);
01571
01572 ret = FALSE;
01573
01574 size = dbus_g_type_get_struct_size (gtype);
01575
01576 if (!dbus_message_iter_open_container (iter,
01577 DBUS_TYPE_STRUCT,
01578 NULL,
01579 &subiter))
01580 goto oom;
01581
01582 for (i = 0; i < size; i++)
01583 {
01584 g_value_init (&val, dbus_g_type_get_struct_member_type
01585 (G_VALUE_TYPE(value), i));
01586 if (!dbus_g_type_struct_get_member (value, i, &val))
01587 return FALSE;
01588 if (!_dbus_gvalue_marshal (&subiter, &val))
01589 return FALSE;
01590 g_value_unset(&val);
01591 }
01592
01593 if (!dbus_message_iter_close_container (iter, &subiter))
01594 goto oom;
01595
01596 return TRUE;
01597 oom:
01598 g_error ("out of memory");
01599 return FALSE;
01600 }
01601
01602 static gboolean
01603 marshal_variant (DBusMessageIter *iter,
01604 const GValue *value)
01605 {
01606 GType value_gtype;
01607 DBusMessageIter subiter;
01608 char *variant_sig;
01609 GValue *real_value;
01610 gboolean ret = FALSE;
01611
01612 real_value = g_value_get_boxed (value);
01613 value_gtype = G_VALUE_TYPE (real_value);
01614
01615 variant_sig = _dbus_gvalue_to_signature (real_value);
01616 if (variant_sig == NULL)
01617 {
01618 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01619 return FALSE;
01620 }
01621
01622 if (!dbus_message_iter_open_container (iter,
01623 DBUS_TYPE_VARIANT,
01624 variant_sig,
01625 &subiter))
01626 goto out;
01627
01628 if (!_dbus_gvalue_marshal (&subiter, real_value))
01629 goto out;
01630
01631 if (!dbus_message_iter_close_container (iter, &subiter))
01632 goto out;
01633
01634 ret = TRUE;
01635 out:
01636 g_free (variant_sig);
01637 return ret;
01638 }
01639
01640 static DBusGValueMarshalFunc
01641 get_type_marshaller (GType type)
01642 {
01643 DBusGTypeMarshalData *typedata;
01644
01645 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01646 if (typedata == NULL)
01647 {
01648 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01649 return marshal_valuearray;
01650 if (dbus_g_type_is_collection (type))
01651 return marshal_collection;
01652 if (dbus_g_type_is_map (type))
01653 return marshal_map;
01654 if (dbus_g_type_is_struct (type))
01655 return marshal_struct;
01656
01657 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01658 return NULL;
01659 }
01660 g_assert (typedata->vtable);
01661 return typedata->vtable->marshaller;
01662 }
01663
01664 typedef struct
01665 {
01666 DBusMessageIter *iter;
01667 DBusGValueMarshalFunc marshaller;
01668 gboolean err;
01669 } DBusGValueCollectionMarshalData;
01670
01671 static void
01672 collection_marshal_iterator (const GValue *eltval,
01673 gpointer user_data)
01674 {
01675 DBusGValueCollectionMarshalData *data = user_data;
01676
01677 if (data->err)
01678 return;
01679
01680 if (!data->marshaller (data->iter, eltval))
01681 data->err = TRUE;
01682 }
01683
01684 static gboolean
01685 marshal_collection (DBusMessageIter *iter,
01686 const GValue *value)
01687 {
01688 GType coltype;
01689 GType subtype;
01690
01691 coltype = G_VALUE_TYPE (value);
01692 subtype = dbus_g_type_get_collection_specialization (coltype);
01693
01694 if (_dbus_g_type_is_fixed (subtype))
01695 return marshal_collection_array (iter, value);
01696 else
01697 return marshal_collection_ptrarray (iter, value);
01698 }
01699
01700 static gboolean
01701 marshal_collection_ptrarray (DBusMessageIter *iter,
01702 const GValue *value)
01703 {
01704 GType coltype;
01705 GType elt_gtype;
01706 DBusGValueCollectionMarshalData data;
01707 DBusMessageIter subiter;
01708 char *elt_sig;
01709
01710 coltype = G_VALUE_TYPE (value);
01711 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01712 data.marshaller = get_type_marshaller (elt_gtype);
01713 if (!data.marshaller)
01714 return FALSE;
01715
01716 elt_sig = _dbus_gtype_to_signature (elt_gtype);
01717 if (!elt_sig)
01718 {
01719 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01720 return FALSE;
01721 }
01722
01723 if (!dbus_message_iter_open_container (iter,
01724 DBUS_TYPE_ARRAY,
01725 elt_sig,
01726 &subiter))
01727 goto oom;
01728 g_free (elt_sig);
01729
01730 data.iter = &subiter;
01731 data.err = FALSE;
01732
01733 dbus_g_type_collection_value_iterate (value,
01734 collection_marshal_iterator,
01735 &data);
01736
01737 if (!dbus_message_iter_close_container (iter, &subiter))
01738 goto oom;
01739
01740 return !data.err;
01741 oom:
01742 g_error ("out of memory");
01743 return FALSE;
01744 }
01745
01746
01747 static gboolean
01748 marshal_collection_array (DBusMessageIter *iter,
01749 const GValue *value)
01750 {
01751 GType elt_gtype;
01752 DBusMessageIter subiter;
01753 GArray *array;
01754 guint elt_size;
01755 char *subsignature_str;
01756
01757 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01758 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01759 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01760 if (!subsignature_str)
01761 {
01762 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01763 return FALSE;
01764 }
01765
01766 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01767
01768 array = g_value_get_boxed (value);
01769
01770 if (!dbus_message_iter_open_container (iter,
01771 DBUS_TYPE_ARRAY,
01772 subsignature_str,
01773 &subiter))
01774 goto oom;
01775
01776
01777
01778
01779
01780 if (!array || !dbus_message_iter_append_fixed_array (&subiter,
01781 subsignature_str[0],
01782 &(array->data),
01783 array->len))
01784 goto oom;
01785
01786 if (!dbus_message_iter_close_container (iter, &subiter))
01787 goto oom;
01788 g_free (subsignature_str);
01789 return TRUE;
01790 oom:
01791 g_error ("out of memory");
01792 return FALSE;
01793 }
01794
01795 gboolean
01796 _dbus_gvalue_marshal (DBusMessageIter *iter,
01797 const GValue *value)
01798 {
01799 GType gtype;
01800 DBusGValueMarshalFunc marshaller;
01801
01802 gtype = G_VALUE_TYPE (value);
01803
01804 marshaller = get_type_marshaller (gtype);
01805 if (marshaller == NULL)
01806 return FALSE;
01807 return marshaller (iter, value);
01808 }
01809
01810 #ifdef DBUS_BUILD_TESTS
01811
01812 static void
01813 assert_type_maps_to (GType gtype, const char *expected_sig)
01814 {
01815 char *sig;
01816 sig = _dbus_gtype_to_signature (gtype);
01817 g_assert (sig != NULL);
01818 g_assert (!strcmp (expected_sig, sig));
01819 g_free (sig);
01820 }
01821
01822 static void
01823 assert_signature_maps_to (const char *sig, GType expected_gtype)
01824 {
01825 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01826 }
01827
01828 static void
01829 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01830 {
01831 assert_type_maps_to (gtype, expected_sig);
01832 assert_signature_maps_to (expected_sig, gtype);
01833 }
01834
01842 gboolean
01843 _dbus_gvalue_test (const char *test_data_dir)
01844 {
01845 _dbus_g_value_types_init ();
01846
01847 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01848 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01849 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01850
01851 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01852 DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
01853 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01854 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01855 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01856 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01857
01858 assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
01859 DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING );
01860 return TRUE;
01861 }
01862
01863 #endif