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 dbus_free (current_sig);
00770 if (elt_type == G_TYPE_INVALID)
00771 {
00772 g_value_array_free (ret);
00773 g_set_error (error,
00774 DBUS_GERROR,
00775 DBUS_GERROR_INVALID_ARGS,
00776 _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00777 return FALSE;
00778 }
00779
00780 g_value_init (val, elt_type);
00781
00782 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00783 {
00784 g_value_array_free (ret);
00785 return FALSE;
00786 }
00787
00788 dbus_message_iter_next (&subiter);
00789 }
00790
00791 g_value_set_boxed_take_ownership (value, ret);
00792
00793 return TRUE;
00794 }
00795
00796 static gboolean
00797 demarshal_map (DBusGValueMarshalCtx *context,
00798 DBusMessageIter *iter,
00799 GValue *value,
00800 GError **error)
00801 {
00802 GType gtype;
00803 DBusMessageIter subiter;
00804 int current_type;
00805 gpointer ret;
00806 GType key_gtype;
00807 GType value_gtype;
00808 DBusGTypeSpecializedAppendContext appendctx;
00809
00810 current_type = dbus_message_iter_get_arg_type (iter);
00811 if (current_type != DBUS_TYPE_ARRAY)
00812 {
00813 g_set_error (error,
00814 DBUS_GERROR,
00815 DBUS_GERROR_INVALID_ARGS,
00816 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00817 return FALSE;
00818 }
00819
00820 gtype = G_VALUE_TYPE (value);
00821
00822 dbus_message_iter_recurse (iter, &subiter);
00823
00824 current_type = dbus_message_iter_get_arg_type (&subiter);
00825 if (current_type != DBUS_TYPE_INVALID
00826 && current_type != DBUS_TYPE_DICT_ENTRY)
00827 {
00828 g_set_error (error,
00829 DBUS_GERROR,
00830 DBUS_GERROR_INVALID_ARGS,
00831 _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00832 return FALSE;
00833 }
00834
00835 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00836 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00837
00838 ret = dbus_g_type_specialized_construct (gtype);
00839 g_value_set_boxed_take_ownership (value, ret);
00840
00841 dbus_g_type_specialized_init_append (value, &appendctx);
00842
00843 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00844 {
00845 DBusMessageIter entry_iter;
00846 GValue key_value = {0,};
00847 GValue value_value = {0,};
00848
00849 current_type = dbus_message_iter_get_arg_type (&subiter);
00850 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00851
00852 dbus_message_iter_recurse (&subiter, &entry_iter);
00853
00854 g_value_init (&key_value, key_gtype);
00855 if (!_dbus_gvalue_demarshal (context,
00856 &entry_iter,
00857 &key_value,
00858 error))
00859 return FALSE;
00860
00861 dbus_message_iter_next (&entry_iter);
00862
00863 g_value_init (&value_value, value_gtype);
00864 if (!_dbus_gvalue_demarshal (context,
00865 &entry_iter,
00866 &value_value,
00867 error))
00868 return FALSE;
00869
00870 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00871
00872
00873 dbus_message_iter_next (&subiter);
00874 }
00875
00876 return TRUE;
00877 }
00878
00879 static gboolean
00880 demarshal_struct (DBusGValueMarshalCtx *context,
00881 DBusMessageIter *iter,
00882 GValue *value,
00883 GError **error)
00884 {
00885 int current_type;
00886 DBusMessageIter subiter;
00887 guint i, size;
00888 GValue val = {0,};
00889 GType elt_type;
00890
00891 current_type = dbus_message_iter_get_arg_type (iter);
00892 if (current_type != DBUS_TYPE_STRUCT)
00893 {
00894 g_set_error (error,
00895 DBUS_GERROR,
00896 DBUS_GERROR_INVALID_ARGS,
00897 _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00898 return FALSE;
00899 }
00900
00901 dbus_message_iter_recurse (iter, &subiter);
00902
00903 g_value_set_boxed_take_ownership (value,
00904 dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
00905
00906 size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
00907
00908 for (i=0; i < size; i++)
00909 {
00910
00911 elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
00912 if (elt_type == G_TYPE_INVALID)
00913 {
00914 g_value_unset (value);
00915 g_set_error (error,
00916 DBUS_GERROR,
00917 DBUS_GERROR_INVALID_ARGS,
00918 _("Couldn't demarshal argument, "
00919 "struct type %s has no member %d"),
00920 g_type_name (G_VALUE_TYPE(value)), i);
00921 return FALSE;
00922 }
00923
00924 g_value_init (&val, elt_type);
00925
00926 if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
00927 {
00928 g_value_unset (&val);
00929 g_value_unset (value);
00930 return FALSE;
00931 }
00932 if (!dbus_g_type_struct_set_member (value, i, &val))
00933 {
00934 g_value_unset (&val);
00935 g_value_unset (value);
00936 return FALSE;
00937 }
00938
00939 dbus_message_iter_next (&subiter);
00940 g_value_unset (&val);
00941 }
00942
00943 g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
00944
00945 return TRUE;
00946 }
00947
00948
00949 static DBusGValueDemarshalFunc
00950 get_type_demarshaller (GType type)
00951 {
00952 DBusGTypeMarshalData *typedata;
00953
00954 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00955 if (typedata == NULL)
00956 {
00957 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00958 return demarshal_valuearray;
00959 if (dbus_g_type_is_collection (type))
00960 return demarshal_collection;
00961 if (dbus_g_type_is_map (type))
00962 return demarshal_map;
00963 if (dbus_g_type_is_struct (type))
00964 return demarshal_struct;
00965
00966 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00967 return NULL;
00968 }
00969 g_assert (typedata->vtable);
00970 return typedata->vtable->demarshaller;
00971 }
00972
00973 static gboolean
00974 demarshal_collection (DBusGValueMarshalCtx *context,
00975 DBusMessageIter *iter,
00976 GValue *value,
00977 GError **error)
00978 {
00979 GType coltype;
00980 GType subtype;
00981
00982 coltype = G_VALUE_TYPE (value);
00983 subtype = dbus_g_type_get_collection_specialization (coltype);
00984
00985 if (_dbus_g_type_is_fixed (subtype))
00986 return demarshal_collection_array (context, iter, value, error);
00987 else
00988 return demarshal_collection_ptrarray (context, iter, value, error);
00989 }
00990
00991 static gboolean
00992 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
00993 DBusMessageIter *iter,
00994 GValue *value,
00995 GError **error)
00996 {
00997 GType coltype;
00998 GType subtype;
00999 gpointer instance;
01000 DBusGTypeSpecializedAppendContext ctx;
01001 DBusGValueDemarshalFunc demarshaller;
01002 DBusMessageIter subiter;
01003 int current_type;
01004
01005 current_type = dbus_message_iter_get_arg_type (iter);
01006
01007 if (current_type != DBUS_TYPE_ARRAY)
01008 {
01009 g_set_error (error,
01010 DBUS_GERROR,
01011 DBUS_GERROR_INVALID_ARGS,
01012 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
01013 return FALSE;
01014 }
01015
01016 dbus_message_iter_recurse (iter, &subiter);
01017
01018 coltype = G_VALUE_TYPE (value);
01019 subtype = dbus_g_type_get_collection_specialization (coltype);
01020
01021 demarshaller = get_type_demarshaller (subtype);
01022
01023 if (!demarshaller)
01024 {
01025 g_set_error (error,
01026 DBUS_GERROR,
01027 DBUS_GERROR_INVALID_ARGS,
01028 _("No demarshaller registered for type \"%s\" of collection \"%s\""),
01029 g_type_name (coltype),
01030 g_type_name (subtype));
01031 return FALSE;
01032 }
01033
01034 instance = dbus_g_type_specialized_construct (coltype);
01035 g_value_set_boxed_take_ownership (value, instance);
01036
01037 dbus_g_type_specialized_init_append (value, &ctx);
01038
01039 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
01040 {
01041 GValue eltval = {0, };
01042
01043 g_value_init (&eltval, subtype);
01044
01045 if (!demarshaller (context, &subiter, &eltval, error))
01046 {
01047 dbus_g_type_specialized_collection_end_append (&ctx);
01048 g_value_unset (value);
01049 return FALSE;
01050 }
01051 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01052
01053 dbus_message_iter_next (&subiter);
01054 }
01055 dbus_g_type_specialized_collection_end_append (&ctx);
01056
01057 return TRUE;
01058 }
01059
01060 static gboolean
01061 demarshal_collection_array (DBusGValueMarshalCtx *context,
01062 DBusMessageIter *iter,
01063 GValue *value,
01064 GError **error)
01065 {
01066 DBusMessageIter subiter;
01067 GArray *ret;
01068 GType elt_gtype;
01069 int elt_size;
01070 void *msgarray;
01071 int msgarray_len;
01072
01073 dbus_message_iter_recurse (iter, &subiter);
01074
01075 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01076 g_assert (elt_gtype != G_TYPE_INVALID);
01077 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01078
01079 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01080
01081 ret = g_array_new (FALSE, TRUE, elt_size);
01082
01083 msgarray = NULL;
01084 dbus_message_iter_get_fixed_array (&subiter,
01085 &msgarray,
01086 &msgarray_len);
01087 g_assert (msgarray != NULL || msgarray_len == 0);
01088
01089 if (msgarray_len)
01090 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
01091
01092 g_value_set_boxed_take_ownership (value, ret);
01093
01094 return TRUE;
01095 }
01096
01097 gboolean
01098 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
01099 DBusMessageIter *iter,
01100 GValue *value,
01101 GError **error)
01102 {
01103 GType gtype;
01104 DBusGValueDemarshalFunc demarshaller;
01105
01106 gtype = G_VALUE_TYPE (value);
01107
01108 demarshaller = get_type_demarshaller (gtype);
01109
01110 if (demarshaller == NULL)
01111 {
01112 g_set_error (error,
01113 DBUS_GERROR,
01114 DBUS_GERROR_INVALID_ARGS,
01115 _("No demarshaller registered for type \"%s\""),
01116 g_type_name (gtype));
01117 return FALSE;
01118 }
01119
01120 return demarshaller (context, iter, value, error);
01121 }
01122
01123 gboolean
01124 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
01125 DBusMessageIter *iter,
01126 GValue *value,
01127 GError **error)
01128 {
01129 return demarshal_static_variant (context, iter, value, error);
01130 }
01131
01132 GValueArray *
01133 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
01134 DBusMessage *message,
01135 guint n_types,
01136 const GType *types,
01137 GError **error)
01138 {
01139 GValueArray *ret;
01140 DBusMessageIter iter;
01141 int current_type;
01142 guint index_;
01143
01144 ret = g_value_array_new (6);
01145
01146 dbus_message_iter_init (message, &iter);
01147 index_ = 0;
01148 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01149 {
01150 GValue *value;
01151 GType gtype;
01152
01153 if (index_ >= n_types)
01154 {
01155 g_set_error (error, DBUS_GERROR,
01156 DBUS_GERROR_INVALID_ARGS,
01157 _("Too many arguments in message"));
01158 goto lose;
01159 }
01160
01161 g_value_array_append (ret, NULL);
01162 value = g_value_array_get_nth (ret, index_);
01163
01164 gtype = types[index_];
01165 g_value_init (value, gtype);
01166
01167 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01168 goto lose;
01169 dbus_message_iter_next (&iter);
01170 index_++;
01171 }
01172 if (index_ < n_types)
01173 {
01174 g_set_error (error, DBUS_GERROR,
01175 DBUS_GERROR_INVALID_ARGS,
01176 _("Too few arguments in message"));
01177 goto lose;
01178 }
01179
01180 return ret;
01181 lose:
01182 g_value_array_free (ret);
01183 return NULL;
01184 }
01185
01186 static gboolean
01187 marshal_basic (DBusMessageIter *iter, const GValue *value)
01188 {
01189 GType value_type;
01190
01191 value_type = G_VALUE_TYPE (value);
01192
01193 switch (value_type)
01194 {
01195 case G_TYPE_CHAR:
01196 {
01197 char b = g_value_get_char (value);
01198 if (!dbus_message_iter_append_basic (iter,
01199 DBUS_TYPE_BYTE,
01200 &b))
01201 goto nomem;
01202 }
01203 return TRUE;
01204 case G_TYPE_UCHAR:
01205 {
01206 unsigned char b = g_value_get_uchar (value);
01207 if (!dbus_message_iter_append_basic (iter,
01208 DBUS_TYPE_BYTE,
01209 &b))
01210 goto nomem;
01211 }
01212 return TRUE;
01213 case G_TYPE_BOOLEAN:
01214 {
01215 dbus_bool_t b = g_value_get_boolean (value);
01216 if (!dbus_message_iter_append_basic (iter,
01217 DBUS_TYPE_BOOLEAN,
01218 &b))
01219 goto nomem;
01220 }
01221 return TRUE;
01222 case G_TYPE_INT:
01223 {
01224 dbus_int32_t v = g_value_get_int (value);
01225 if (!dbus_message_iter_append_basic (iter,
01226 DBUS_TYPE_INT32,
01227 &v))
01228 goto nomem;
01229 }
01230 return TRUE;
01231 case G_TYPE_UINT:
01232 {
01233 dbus_uint32_t v = g_value_get_uint (value);
01234 if (!dbus_message_iter_append_basic (iter,
01235 DBUS_TYPE_UINT32,
01236 &v))
01237 goto nomem;
01238 }
01239 return TRUE;
01240 case G_TYPE_LONG:
01241 {
01242 dbus_int32_t v = g_value_get_long (value);
01243 if (!dbus_message_iter_append_basic (iter,
01244 DBUS_TYPE_INT32,
01245 &v))
01246 goto nomem;
01247 }
01248 return TRUE;
01249 case G_TYPE_ULONG:
01250 {
01251 dbus_uint32_t v = g_value_get_ulong (value);
01252 if (!dbus_message_iter_append_basic (iter,
01253 DBUS_TYPE_UINT32,
01254 &v))
01255 goto nomem;
01256 }
01257 return TRUE;
01258 case G_TYPE_INT64:
01259 {
01260 gint64 v = g_value_get_int64 (value);
01261 if (!dbus_message_iter_append_basic (iter,
01262 DBUS_TYPE_INT64,
01263 &v))
01264 goto nomem;
01265 }
01266 return TRUE;
01267 case G_TYPE_UINT64:
01268 {
01269 guint64 v = g_value_get_uint64 (value);
01270 if (!dbus_message_iter_append_basic (iter,
01271 DBUS_TYPE_UINT64,
01272 &v))
01273 goto nomem;
01274 }
01275 return TRUE;
01276 case G_TYPE_FLOAT:
01277 {
01278 double v = g_value_get_float (value);
01279
01280 if (!dbus_message_iter_append_basic (iter,
01281 DBUS_TYPE_DOUBLE,
01282 &v))
01283 goto nomem;
01284 }
01285 return TRUE;
01286 case G_TYPE_DOUBLE:
01287 {
01288 double v = g_value_get_double (value);
01289
01290 if (!dbus_message_iter_append_basic (iter,
01291 DBUS_TYPE_DOUBLE,
01292 &v))
01293 goto nomem;
01294 }
01295 return TRUE;
01296 case G_TYPE_STRING:
01297
01298 {
01299 const char *v = g_value_get_string (value);
01300 if (!v)
01301 v = "";
01302 if (!dbus_message_iter_append_basic (iter,
01303 DBUS_TYPE_STRING,
01304 &v))
01305 goto nomem;
01306 }
01307 return TRUE;
01308
01309 default:
01310 {
01311 g_assert_not_reached ();
01312 return FALSE;
01313 }
01314 }
01315
01316 nomem:
01317 g_error ("no memory");
01318 return FALSE;
01319 }
01320
01321 static gboolean
01322 marshal_strv (DBusMessageIter *iter,
01323 const GValue *value)
01324 {
01325 DBusMessageIter subiter;
01326 char **array;
01327 char **elt;
01328 gboolean ret = FALSE;
01329
01330 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01331
01332 array = g_value_get_boxed (value);
01333
01334 if (!dbus_message_iter_open_container (iter,
01335 DBUS_TYPE_ARRAY,
01336 "s",
01337 &subiter))
01338 goto out;
01339
01340 if (array)
01341 {
01342 for (elt = array; *elt; elt++)
01343 {
01344 if (!dbus_message_iter_append_basic (&subiter,
01345 DBUS_TYPE_STRING,
01346 elt))
01347 goto out;
01348 }
01349 }
01350
01351 if (!dbus_message_iter_close_container (iter, &subiter))
01352 goto out;
01353 ret = TRUE;
01354 out:
01355 return ret;
01356 }
01357
01358 static gboolean
01359 marshal_valuearray (DBusMessageIter *iter,
01360 const GValue *value)
01361 {
01362 GValueArray *array;
01363 guint i;
01364 DBusMessageIter subiter;
01365
01366 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01367
01368 array = g_value_get_boxed (value);
01369
01370 if (!dbus_message_iter_open_container (iter,
01371 DBUS_TYPE_STRUCT,
01372 NULL,
01373 &subiter))
01374 goto oom;
01375
01376 if (array)
01377 {
01378 for (i = 0; i < array->n_values; i++)
01379 {
01380 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01381 return FALSE;
01382 }
01383 }
01384
01385 if (!dbus_message_iter_close_container (iter, &subiter))
01386 goto oom;
01387
01388 return TRUE;
01389 oom:
01390 g_error ("out of memory");
01391 return FALSE;
01392 }
01393
01394 static gboolean
01395 marshal_proxy (DBusMessageIter *iter,
01396 const GValue *value)
01397 {
01398 const char *path;
01399 DBusGProxy *proxy;
01400
01401 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01402
01403 proxy = g_value_get_object (value);
01404 path = dbus_g_proxy_get_path (proxy);
01405
01406 if (!dbus_message_iter_append_basic (iter,
01407 DBUS_TYPE_OBJECT_PATH,
01408 &path))
01409 return FALSE;
01410 return TRUE;
01411 }
01412
01413 static gboolean
01414 marshal_object_path (DBusMessageIter *iter,
01415 const GValue *value)
01416 {
01417 const char *path;
01418
01419 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01420
01421 path = (const char*) g_value_get_boxed (value);
01422
01423 if (!dbus_message_iter_append_basic (iter,
01424 DBUS_TYPE_OBJECT_PATH,
01425 &path))
01426 return FALSE;
01427 return TRUE;
01428 }
01429
01430 static gboolean
01431 marshal_object (DBusMessageIter *iter,
01432 const GValue *value)
01433 {
01434 const char *path;
01435 GObject *obj;
01436
01437 obj = g_value_get_object (value);
01438 path = _dbus_gobject_get_path (obj);
01439
01440 if (path == NULL)
01441
01442 return FALSE;
01443
01444 if (!dbus_message_iter_append_basic (iter,
01445 DBUS_TYPE_OBJECT_PATH,
01446 &path))
01447 return FALSE;
01448 return TRUE;
01449 }
01450
01451 struct DBusGLibHashMarshalData
01452 {
01453 const char *entry_sig;
01454 DBusMessageIter *iter;
01455 gboolean err;
01456 };
01457
01458 static void
01459 marshal_map_entry (const GValue *key,
01460 const GValue *value,
01461 gpointer data)
01462 {
01463 struct DBusGLibHashMarshalData *hashdata = data;
01464 DBusMessageIter subiter;
01465
01466 if (hashdata->err)
01467 return;
01468
01469 if (!dbus_message_iter_open_container (hashdata->iter,
01470 DBUS_TYPE_DICT_ENTRY,
01471 NULL,
01472 &subiter))
01473 goto lose;
01474
01475 if (!_dbus_gvalue_marshal (&subiter, key))
01476 goto lose;
01477
01478 if (!_dbus_gvalue_marshal (&subiter, value))
01479 goto lose;
01480
01481 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01482 goto lose;
01483
01484 return;
01485 lose:
01486 hashdata->err = TRUE;
01487 }
01488
01489 static gboolean
01490 marshal_map (DBusMessageIter *iter,
01491 const GValue *value)
01492 {
01493 GType gtype;
01494 DBusMessageIter arr_iter;
01495 gboolean ret;
01496 struct DBusGLibHashMarshalData hashdata;
01497 char *key_sig;
01498 char *value_sig;
01499 GType key_type;
01500 GType value_type;
01501 char *entry_sig;
01502 char *array_sig;
01503
01504 gtype = G_VALUE_TYPE (value);
01505
01506 ret = FALSE;
01507
01508 key_type = dbus_g_type_get_map_key_specialization (gtype);
01509 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01510 value_type = dbus_g_type_get_map_value_specialization (gtype);
01511 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01512
01513 key_sig = _dbus_gtype_to_signature (key_type);
01514 if (!key_sig)
01515 {
01516 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01517 return FALSE;
01518 }
01519 value_sig = _dbus_gtype_to_signature (value_type);
01520 if (!value_sig)
01521 {
01522 g_free (key_sig);
01523 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01524 return FALSE;
01525 }
01526 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01527 g_free (key_sig);
01528 g_free (value_sig);
01529 array_sig = g_strdup_printf ("%c%s%c",
01530 DBUS_DICT_ENTRY_BEGIN_CHAR,
01531 entry_sig,
01532 DBUS_DICT_ENTRY_END_CHAR);
01533 if (!dbus_message_iter_open_container (iter,
01534 DBUS_TYPE_ARRAY,
01535 array_sig,
01536 &arr_iter))
01537 goto lose;
01538
01539 hashdata.iter = &arr_iter;
01540 hashdata.err = FALSE;
01541 hashdata.entry_sig = entry_sig;
01542
01543 dbus_g_type_map_value_iterate (value,
01544 marshal_map_entry,
01545 &hashdata);
01546
01547 if (!dbus_message_iter_close_container (iter, &arr_iter))
01548 goto lose;
01549
01550 out:
01551 g_free (entry_sig);
01552 g_free (array_sig);
01553 return !hashdata.err;
01554 lose:
01555 hashdata.err = TRUE;
01556 goto out;
01557 }
01558
01559 static gboolean
01560 marshal_struct (DBusMessageIter *iter,
01561 const GValue *value)
01562 {
01563 GType gtype;
01564 DBusMessageIter subiter;
01565 gboolean ret;
01566 guint size, i;
01567 GValue val = {0,};
01568
01569 gtype = G_VALUE_TYPE (value);
01570
01571 ret = FALSE;
01572
01573 size = dbus_g_type_get_struct_size (gtype);
01574
01575 if (!dbus_message_iter_open_container (iter,
01576 DBUS_TYPE_STRUCT,
01577 NULL,
01578 &subiter))
01579 goto oom;
01580
01581 for (i = 0; i < size; i++)
01582 {
01583 g_value_init (&val, dbus_g_type_get_struct_member_type
01584 (G_VALUE_TYPE(value), i));
01585 if (!dbus_g_type_struct_get_member (value, i, &val))
01586 return FALSE;
01587 if (!_dbus_gvalue_marshal (&subiter, &val))
01588 return FALSE;
01589 g_value_unset(&val);
01590 }
01591
01592 if (!dbus_message_iter_close_container (iter, &subiter))
01593 goto oom;
01594
01595 return TRUE;
01596 oom:
01597 g_error ("out of memory");
01598 return FALSE;
01599 }
01600
01601 static gboolean
01602 marshal_variant (DBusMessageIter *iter,
01603 const GValue *value)
01604 {
01605 GType value_gtype;
01606 DBusMessageIter subiter;
01607 char *variant_sig;
01608 GValue *real_value;
01609 gboolean ret = FALSE;
01610
01611 real_value = g_value_get_boxed (value);
01612 value_gtype = G_VALUE_TYPE (real_value);
01613
01614 variant_sig = _dbus_gvalue_to_signature (real_value);
01615 if (variant_sig == NULL)
01616 {
01617 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01618 return FALSE;
01619 }
01620
01621 if (!dbus_message_iter_open_container (iter,
01622 DBUS_TYPE_VARIANT,
01623 variant_sig,
01624 &subiter))
01625 goto out;
01626
01627 if (!_dbus_gvalue_marshal (&subiter, real_value))
01628 goto out;
01629
01630 if (!dbus_message_iter_close_container (iter, &subiter))
01631 goto out;
01632
01633 ret = TRUE;
01634 out:
01635 g_free (variant_sig);
01636 return ret;
01637 }
01638
01639 static DBusGValueMarshalFunc
01640 get_type_marshaller (GType type)
01641 {
01642 DBusGTypeMarshalData *typedata;
01643
01644 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01645 if (typedata == NULL)
01646 {
01647 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01648 return marshal_valuearray;
01649 if (dbus_g_type_is_collection (type))
01650 return marshal_collection;
01651 if (dbus_g_type_is_map (type))
01652 return marshal_map;
01653 if (dbus_g_type_is_struct (type))
01654 return marshal_struct;
01655
01656 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01657 return NULL;
01658 }
01659 g_assert (typedata->vtable);
01660 return typedata->vtable->marshaller;
01661 }
01662
01663 typedef struct
01664 {
01665 DBusMessageIter *iter;
01666 DBusGValueMarshalFunc marshaller;
01667 gboolean err;
01668 } DBusGValueCollectionMarshalData;
01669
01670 static void
01671 collection_marshal_iterator (const GValue *eltval,
01672 gpointer user_data)
01673 {
01674 DBusGValueCollectionMarshalData *data = user_data;
01675
01676 if (data->err)
01677 return;
01678
01679 if (!data->marshaller (data->iter, eltval))
01680 data->err = TRUE;
01681 }
01682
01683 static gboolean
01684 marshal_collection (DBusMessageIter *iter,
01685 const GValue *value)
01686 {
01687 GType coltype;
01688 GType subtype;
01689
01690 coltype = G_VALUE_TYPE (value);
01691 subtype = dbus_g_type_get_collection_specialization (coltype);
01692
01693 if (_dbus_g_type_is_fixed (subtype))
01694 return marshal_collection_array (iter, value);
01695 else
01696 return marshal_collection_ptrarray (iter, value);
01697 }
01698
01699 static gboolean
01700 marshal_collection_ptrarray (DBusMessageIter *iter,
01701 const GValue *value)
01702 {
01703 GType coltype;
01704 GType elt_gtype;
01705 DBusGValueCollectionMarshalData data;
01706 DBusMessageIter subiter;
01707 char *elt_sig;
01708
01709 coltype = G_VALUE_TYPE (value);
01710 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01711 data.marshaller = get_type_marshaller (elt_gtype);
01712 if (!data.marshaller)
01713 return FALSE;
01714
01715 elt_sig = _dbus_gtype_to_signature (elt_gtype);
01716 if (!elt_sig)
01717 {
01718 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01719 return FALSE;
01720 }
01721
01722 if (!dbus_message_iter_open_container (iter,
01723 DBUS_TYPE_ARRAY,
01724 elt_sig,
01725 &subiter))
01726 goto oom;
01727 g_free (elt_sig);
01728
01729 data.iter = &subiter;
01730 data.err = FALSE;
01731
01732 dbus_g_type_collection_value_iterate (value,
01733 collection_marshal_iterator,
01734 &data);
01735
01736 if (!dbus_message_iter_close_container (iter, &subiter))
01737 goto oom;
01738
01739 return !data.err;
01740 oom:
01741 g_error ("out of memory");
01742 return FALSE;
01743 }
01744
01745
01746 static gboolean
01747 marshal_collection_array (DBusMessageIter *iter,
01748 const GValue *value)
01749 {
01750 GType elt_gtype;
01751 DBusMessageIter subiter;
01752 GArray *array;
01753 guint elt_size;
01754 char *subsignature_str;
01755
01756 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01757 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01758 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01759 if (!subsignature_str)
01760 {
01761 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01762 return FALSE;
01763 }
01764
01765 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01766
01767 array = g_value_get_boxed (value);
01768
01769 if (!dbus_message_iter_open_container (iter,
01770 DBUS_TYPE_ARRAY,
01771 subsignature_str,
01772 &subiter))
01773 goto oom;
01774
01775
01776
01777
01778
01779 if (!array || !dbus_message_iter_append_fixed_array (&subiter,
01780 subsignature_str[0],
01781 &(array->data),
01782 array->len))
01783 goto oom;
01784
01785 if (!dbus_message_iter_close_container (iter, &subiter))
01786 goto oom;
01787 g_free (subsignature_str);
01788 return TRUE;
01789 oom:
01790 g_error ("out of memory");
01791 return FALSE;
01792 }
01793
01794 gboolean
01795 _dbus_gvalue_marshal (DBusMessageIter *iter,
01796 const GValue *value)
01797 {
01798 GType gtype;
01799 DBusGValueMarshalFunc marshaller;
01800
01801 gtype = G_VALUE_TYPE (value);
01802
01803 marshaller = get_type_marshaller (gtype);
01804 if (marshaller == NULL)
01805 return FALSE;
01806 return marshaller (iter, value);
01807 }
01808
01809 #ifdef DBUS_BUILD_TESTS
01810
01811 static void
01812 assert_type_maps_to (GType gtype, const char *expected_sig)
01813 {
01814 char *sig;
01815 sig = _dbus_gtype_to_signature (gtype);
01816 g_assert (sig != NULL);
01817 g_assert (!strcmp (expected_sig, sig));
01818 g_free (sig);
01819 }
01820
01821 static void
01822 assert_signature_maps_to (const char *sig, GType expected_gtype)
01823 {
01824 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01825 }
01826
01827 static void
01828 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01829 {
01830 assert_type_maps_to (gtype, expected_sig);
01831 assert_signature_maps_to (expected_sig, gtype);
01832 }
01833
01841 gboolean
01842 _dbus_gvalue_test (const char *test_data_dir)
01843 {
01844 _dbus_g_value_types_init ();
01845
01846 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01847 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01848 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01849
01850 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01851 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);
01852 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01853 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01854 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01855 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01856
01857 assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
01858 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 );
01859 return TRUE;
01860 }
01861
01862 #endif