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