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