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