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 for (elt = array; *elt; elt++)
01341 {
01342 if (!dbus_message_iter_append_basic (&subiter,
01343 DBUS_TYPE_STRING,
01344 elt))
01345 goto out;
01346 }
01347
01348 if (!dbus_message_iter_close_container (iter, &subiter))
01349 goto out;
01350 ret = TRUE;
01351 out:
01352 return ret;
01353 }
01354
01355 static gboolean
01356 marshal_valuearray (DBusMessageIter *iter,
01357 const GValue *value)
01358 {
01359 GValueArray *array;
01360 guint i;
01361 DBusMessageIter subiter;
01362
01363 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01364
01365 array = g_value_get_boxed (value);
01366
01367 if (!dbus_message_iter_open_container (iter,
01368 DBUS_TYPE_STRUCT,
01369 NULL,
01370 &subiter))
01371 goto oom;
01372
01373 for (i = 0; i < array->n_values; i++)
01374 {
01375 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01376 return FALSE;
01377 }
01378
01379 if (!dbus_message_iter_close_container (iter, &subiter))
01380 goto oom;
01381
01382 return TRUE;
01383 oom:
01384 g_error ("out of memory");
01385 return FALSE;
01386 }
01387
01388 static gboolean
01389 marshal_proxy (DBusMessageIter *iter,
01390 const GValue *value)
01391 {
01392 const char *path;
01393 DBusGProxy *proxy;
01394
01395 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01396
01397 proxy = g_value_get_object (value);
01398 path = dbus_g_proxy_get_path (proxy);
01399
01400 if (!dbus_message_iter_append_basic (iter,
01401 DBUS_TYPE_OBJECT_PATH,
01402 &path))
01403 return FALSE;
01404 return TRUE;
01405 }
01406
01407 static gboolean
01408 marshal_object_path (DBusMessageIter *iter,
01409 const GValue *value)
01410 {
01411 const char *path;
01412
01413 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01414
01415 path = (const char*) g_value_get_boxed (value);
01416
01417 if (!dbus_message_iter_append_basic (iter,
01418 DBUS_TYPE_OBJECT_PATH,
01419 &path))
01420 return FALSE;
01421 return TRUE;
01422 }
01423
01424 static gboolean
01425 marshal_object (DBusMessageIter *iter,
01426 const GValue *value)
01427 {
01428 const char *path;
01429 GObject *obj;
01430
01431 obj = g_value_get_object (value);
01432 path = _dbus_gobject_get_path (obj);
01433
01434 if (path == NULL)
01435
01436 return FALSE;
01437
01438 if (!dbus_message_iter_append_basic (iter,
01439 DBUS_TYPE_OBJECT_PATH,
01440 &path))
01441 return FALSE;
01442 return TRUE;
01443 }
01444
01445 struct DBusGLibHashMarshalData
01446 {
01447 const char *entry_sig;
01448 DBusMessageIter *iter;
01449 gboolean err;
01450 };
01451
01452 static void
01453 marshal_map_entry (const GValue *key,
01454 const GValue *value,
01455 gpointer data)
01456 {
01457 struct DBusGLibHashMarshalData *hashdata = data;
01458 DBusMessageIter subiter;
01459
01460 if (hashdata->err)
01461 return;
01462
01463 if (!dbus_message_iter_open_container (hashdata->iter,
01464 DBUS_TYPE_DICT_ENTRY,
01465 NULL,
01466 &subiter))
01467 goto lose;
01468
01469 if (!_dbus_gvalue_marshal (&subiter, key))
01470 goto lose;
01471
01472 if (!_dbus_gvalue_marshal (&subiter, value))
01473 goto lose;
01474
01475 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01476 goto lose;
01477
01478 return;
01479 lose:
01480 hashdata->err = TRUE;
01481 }
01482
01483 static gboolean
01484 marshal_map (DBusMessageIter *iter,
01485 const GValue *value)
01486 {
01487 GType gtype;
01488 DBusMessageIter arr_iter;
01489 gboolean ret;
01490 struct DBusGLibHashMarshalData hashdata;
01491 char *key_sig;
01492 char *value_sig;
01493 GType key_type;
01494 GType value_type;
01495 char *entry_sig;
01496 char *array_sig;
01497
01498 gtype = G_VALUE_TYPE (value);
01499
01500 ret = FALSE;
01501
01502 key_type = dbus_g_type_get_map_key_specialization (gtype);
01503 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01504 value_type = dbus_g_type_get_map_value_specialization (gtype);
01505 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01506
01507 key_sig = _dbus_gtype_to_signature (key_type);
01508 if (!key_sig)
01509 {
01510 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01511 return FALSE;
01512 }
01513 value_sig = _dbus_gtype_to_signature (value_type);
01514 if (!value_sig)
01515 {
01516 g_free (key_sig);
01517 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01518 return FALSE;
01519 }
01520 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01521 g_free (key_sig);
01522 g_free (value_sig);
01523 array_sig = g_strdup_printf ("%c%s%c",
01524 DBUS_DICT_ENTRY_BEGIN_CHAR,
01525 entry_sig,
01526 DBUS_DICT_ENTRY_END_CHAR);
01527 if (!dbus_message_iter_open_container (iter,
01528 DBUS_TYPE_ARRAY,
01529 array_sig,
01530 &arr_iter))
01531 goto lose;
01532
01533 hashdata.iter = &arr_iter;
01534 hashdata.err = FALSE;
01535 hashdata.entry_sig = entry_sig;
01536
01537 dbus_g_type_map_value_iterate (value,
01538 marshal_map_entry,
01539 &hashdata);
01540
01541 if (!dbus_message_iter_close_container (iter, &arr_iter))
01542 goto lose;
01543
01544 out:
01545 g_free (entry_sig);
01546 g_free (array_sig);
01547 return !hashdata.err;
01548 lose:
01549 hashdata.err = TRUE;
01550 goto out;
01551 }
01552
01553 static gboolean
01554 marshal_struct (DBusMessageIter *iter,
01555 const GValue *value)
01556 {
01557 GType gtype;
01558 DBusMessageIter subiter;
01559 gboolean ret;
01560 guint size, i;
01561 GValue val = {0,};
01562
01563 gtype = G_VALUE_TYPE (value);
01564
01565 ret = FALSE;
01566
01567 size = dbus_g_type_get_struct_size (gtype);
01568
01569 if (!dbus_message_iter_open_container (iter,
01570 DBUS_TYPE_STRUCT,
01571 NULL,
01572 &subiter))
01573 goto oom;
01574
01575 for (i = 0; i < size; i++)
01576 {
01577 g_value_init (&val, dbus_g_type_get_struct_member_type
01578 (G_VALUE_TYPE(value), i));
01579 if (!dbus_g_type_struct_get_member (value, i, &val))
01580 return FALSE;
01581 if (!_dbus_gvalue_marshal (&subiter, &val))
01582 return FALSE;
01583 g_value_unset(&val);
01584 }
01585
01586 if (!dbus_message_iter_close_container (iter, &subiter))
01587 goto oom;
01588
01589 return TRUE;
01590 oom:
01591 g_error ("out of memory");
01592 return FALSE;
01593 }
01594
01595 static gboolean
01596 marshal_variant (DBusMessageIter *iter,
01597 const GValue *value)
01598 {
01599 GType value_gtype;
01600 DBusMessageIter subiter;
01601 char *variant_sig;
01602 GValue *real_value;
01603 gboolean ret = FALSE;
01604
01605 real_value = g_value_get_boxed (value);
01606 value_gtype = G_VALUE_TYPE (real_value);
01607
01608 variant_sig = _dbus_gvalue_to_signature (real_value);
01609 if (variant_sig == NULL)
01610 {
01611 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01612 return FALSE;
01613 }
01614
01615 if (!dbus_message_iter_open_container (iter,
01616 DBUS_TYPE_VARIANT,
01617 variant_sig,
01618 &subiter))
01619 goto out;
01620
01621 if (!_dbus_gvalue_marshal (&subiter, real_value))
01622 goto out;
01623
01624 if (!dbus_message_iter_close_container (iter, &subiter))
01625 goto out;
01626
01627 ret = TRUE;
01628 out:
01629 g_free (variant_sig);
01630 return ret;
01631 }
01632
01633 static DBusGValueMarshalFunc
01634 get_type_marshaller (GType type)
01635 {
01636 DBusGTypeMarshalData *typedata;
01637
01638 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01639 if (typedata == NULL)
01640 {
01641 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01642 return marshal_valuearray;
01643 if (dbus_g_type_is_collection (type))
01644 return marshal_collection;
01645 if (dbus_g_type_is_map (type))
01646 return marshal_map;
01647 if (dbus_g_type_is_struct (type))
01648 return marshal_struct;
01649
01650 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01651 return NULL;
01652 }
01653 g_assert (typedata->vtable);
01654 return typedata->vtable->marshaller;
01655 }
01656
01657 typedef struct
01658 {
01659 DBusMessageIter *iter;
01660 DBusGValueMarshalFunc marshaller;
01661 gboolean err;
01662 } DBusGValueCollectionMarshalData;
01663
01664 static void
01665 collection_marshal_iterator (const GValue *eltval,
01666 gpointer user_data)
01667 {
01668 DBusGValueCollectionMarshalData *data = user_data;
01669
01670 if (data->err)
01671 return;
01672
01673 if (!data->marshaller (data->iter, eltval))
01674 data->err = TRUE;
01675 }
01676
01677 static gboolean
01678 marshal_collection (DBusMessageIter *iter,
01679 const GValue *value)
01680 {
01681 GType coltype;
01682 GType subtype;
01683
01684 coltype = G_VALUE_TYPE (value);
01685 subtype = dbus_g_type_get_collection_specialization (coltype);
01686
01687 if (_dbus_g_type_is_fixed (subtype))
01688 return marshal_collection_array (iter, value);
01689 else
01690 return marshal_collection_ptrarray (iter, value);
01691 }
01692
01693 static gboolean
01694 marshal_collection_ptrarray (DBusMessageIter *iter,
01695 const GValue *value)
01696 {
01697 GType coltype;
01698 GType elt_gtype;
01699 DBusGValueCollectionMarshalData data;
01700 DBusMessageIter subiter;
01701 char *elt_sig;
01702
01703 coltype = G_VALUE_TYPE (value);
01704 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01705 data.marshaller = get_type_marshaller (elt_gtype);
01706 if (!data.marshaller)
01707 return FALSE;
01708
01709 elt_sig = _dbus_gtype_to_signature (elt_gtype);
01710 if (!elt_sig)
01711 {
01712 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01713 return FALSE;
01714 }
01715
01716 if (!dbus_message_iter_open_container (iter,
01717 DBUS_TYPE_ARRAY,
01718 elt_sig,
01719 &subiter))
01720 goto oom;
01721 g_free (elt_sig);
01722
01723 data.iter = &subiter;
01724 data.err = FALSE;
01725
01726 dbus_g_type_collection_value_iterate (value,
01727 collection_marshal_iterator,
01728 &data);
01729
01730 if (!dbus_message_iter_close_container (iter, &subiter))
01731 goto oom;
01732
01733 return !data.err;
01734 oom:
01735 g_error ("out of memory");
01736 return FALSE;
01737 }
01738
01739
01740 static gboolean
01741 marshal_collection_array (DBusMessageIter *iter,
01742 const GValue *value)
01743 {
01744 GType elt_gtype;
01745 DBusMessageIter subiter;
01746 GArray *array;
01747 guint elt_size;
01748 char *subsignature_str;
01749
01750 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01751 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01752 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01753 if (!subsignature_str)
01754 {
01755 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01756 return FALSE;
01757 }
01758
01759 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01760
01761 array = g_value_get_boxed (value);
01762
01763 if (!dbus_message_iter_open_container (iter,
01764 DBUS_TYPE_ARRAY,
01765 subsignature_str,
01766 &subiter))
01767 goto oom;
01768
01769
01770
01771
01772
01773 if (!dbus_message_iter_append_fixed_array (&subiter,
01774 subsignature_str[0],
01775 &(array->data),
01776 array->len))
01777 goto oom;
01778
01779 if (!dbus_message_iter_close_container (iter, &subiter))
01780 goto oom;
01781 g_free (subsignature_str);
01782 return TRUE;
01783 oom:
01784 g_error ("out of memory");
01785 return FALSE;
01786 }
01787
01788 gboolean
01789 _dbus_gvalue_marshal (DBusMessageIter *iter,
01790 const GValue *value)
01791 {
01792 GType gtype;
01793 DBusGValueMarshalFunc marshaller;
01794
01795 gtype = G_VALUE_TYPE (value);
01796
01797 marshaller = get_type_marshaller (gtype);
01798 if (marshaller == NULL)
01799 return FALSE;
01800 return marshaller (iter, value);
01801 }
01802
01803 #ifdef DBUS_BUILD_TESTS
01804
01805 static void
01806 assert_type_maps_to (GType gtype, const char *expected_sig)
01807 {
01808 char *sig;
01809 sig = _dbus_gtype_to_signature (gtype);
01810 g_assert (sig != NULL);
01811 g_assert (!strcmp (expected_sig, sig));
01812 g_free (sig);
01813 }
01814
01815 static void
01816 assert_signature_maps_to (const char *sig, GType expected_gtype)
01817 {
01818 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01819 }
01820
01821 static void
01822 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01823 {
01824 assert_type_maps_to (gtype, expected_sig);
01825 assert_signature_maps_to (expected_sig, gtype);
01826 }
01827
01835 gboolean
01836 _dbus_gvalue_test (const char *test_data_dir)
01837 {
01838 _dbus_g_value_types_init ();
01839
01840 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01841 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01842 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01843
01844 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01845 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);
01846 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01847 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01848 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01849 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01850
01851 assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
01852 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 );
01853 return TRUE;
01854 }
01855
01856 #endif