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 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 (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
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 g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
00414
00415 return g_string_free (str, FALSE);
00416 }
00417 else
00418 return _dbus_gtype_to_signature (gtype);
00419 }
00420
00421 static gboolean
00422 demarshal_basic (DBusGValueMarshalCtx *context,
00423 DBusMessageIter *iter,
00424 GValue *value,
00425 GError **error)
00426 {
00427 int current_type;
00428
00429 current_type = dbus_message_iter_get_arg_type (iter);
00430 g_assert (dbus_type_is_basic (current_type));
00431
00432 switch (current_type)
00433 {
00434 case DBUS_TYPE_BOOLEAN:
00435 {
00436 dbus_bool_t bool;
00437 dbus_message_iter_get_basic (iter, &bool);
00438 g_value_set_boolean (value, bool);
00439 return TRUE;
00440 }
00441 case DBUS_TYPE_BYTE:
00442 {
00443 unsigned char byte;
00444 dbus_message_iter_get_basic (iter, &byte);
00445 g_value_set_uchar (value, byte);
00446 return TRUE;
00447 }
00448 case DBUS_TYPE_INT32:
00449 {
00450 dbus_int32_t intval;
00451 dbus_message_iter_get_basic (iter, &intval);
00452 g_value_set_int (value, intval);
00453 return TRUE;
00454 }
00455 case DBUS_TYPE_UINT32:
00456 {
00457 dbus_uint32_t intval;
00458 dbus_message_iter_get_basic (iter, &intval);
00459 g_value_set_uint (value, intval);
00460 return TRUE;
00461 }
00462 case DBUS_TYPE_INT64:
00463 {
00464 dbus_int64_t intval;
00465 dbus_message_iter_get_basic (iter, &intval);
00466 g_value_set_int64 (value, intval);
00467 return TRUE;
00468 }
00469 case DBUS_TYPE_UINT64:
00470 {
00471 dbus_uint64_t intval;
00472 dbus_message_iter_get_basic (iter, &intval);
00473 g_value_set_uint64 (value, intval);
00474 return TRUE;
00475 }
00476 case DBUS_TYPE_DOUBLE:
00477 {
00478 double dval;
00479 dbus_message_iter_get_basic (iter, &dval);
00480 g_value_set_double (value, dval);
00481 return TRUE;
00482 }
00483 case DBUS_TYPE_INT16:
00484 {
00485 dbus_int16_t v;
00486 dbus_message_iter_get_basic (iter, &v);
00487 g_value_set_int (value, v);
00488 return TRUE;
00489 }
00490 case DBUS_TYPE_UINT16:
00491 {
00492 dbus_uint16_t v;
00493 dbus_message_iter_get_basic (iter, &v);
00494 g_value_set_uint (value, v);
00495 return TRUE;
00496 }
00497 case DBUS_TYPE_STRING:
00498 {
00499 const char *s;
00500 dbus_message_iter_get_basic (iter, &s);
00501 g_value_set_string (value, s);
00502 return TRUE;
00503 }
00504 default:
00505 g_assert_not_reached ();
00506 return FALSE;
00507 }
00508 }
00509
00510 static gboolean
00511 demarshal_static_variant (DBusGValueMarshalCtx *context,
00512 DBusMessageIter *iter,
00513 GValue *value,
00514 GError **error)
00515 {
00516 char *sig;
00517 int current_type;
00518 DBusMessageIter subiter;
00519 GType variant_type;
00520
00521 current_type = dbus_message_iter_get_arg_type (iter);
00522 dbus_message_iter_recurse (iter, &subiter);
00523 sig = dbus_message_iter_get_signature (&subiter);
00524
00525 variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
00526 if (variant_type != G_TYPE_INVALID)
00527 {
00528 g_value_init (value, variant_type);
00529
00530 if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
00531 {
00532 dbus_free (sig);
00533 return FALSE;
00534 }
00535 }
00536 dbus_free (sig);
00537 return TRUE;
00538 }
00539
00540 static gboolean
00541 demarshal_variant (DBusGValueMarshalCtx *context,
00542 DBusMessageIter *iter,
00543 GValue *value,
00544 GError **error)
00545
00546 {
00547 GValue *variant_val;
00548 variant_val = g_new0 (GValue, 1);
00549
00550 if (!demarshal_static_variant (context, iter, variant_val, error))
00551 return FALSE;
00552
00553 g_value_set_boxed_take_ownership (value, variant_val);
00554 return TRUE;
00555 }
00556
00557 static gboolean
00558 demarshal_proxy (DBusGValueMarshalCtx *context,
00559 DBusMessageIter *iter,
00560 GValue *value,
00561 GError **error)
00562 {
00563 DBusGProxy *new_proxy;
00564 const char *objpath;
00565 int current_type;
00566
00567 current_type = dbus_message_iter_get_arg_type (iter);
00568 if (current_type != DBUS_TYPE_OBJECT_PATH)
00569 {
00570 g_set_error (error,
00571 DBUS_GERROR,
00572 DBUS_GERROR_INVALID_ARGS,
00573 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00574 return FALSE;
00575 }
00576
00577 g_assert (context->proxy != NULL);
00578
00579 dbus_message_iter_get_basic (iter, &objpath);
00580
00581 new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
00582 g_value_set_object_take_ownership (value, new_proxy);
00583
00584 return TRUE;
00585 }
00586
00587 static gboolean
00588 demarshal_object_path (DBusGValueMarshalCtx *context,
00589 DBusMessageIter *iter,
00590 GValue *value,
00591 GError **error)
00592 {
00593 const char *objpath;
00594 int current_type;
00595
00596 current_type = dbus_message_iter_get_arg_type (iter);
00597 if (current_type != DBUS_TYPE_OBJECT_PATH)
00598 {
00599 g_set_error (error,
00600 DBUS_GERROR,
00601 DBUS_GERROR_INVALID_ARGS,
00602 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00603 return FALSE;
00604 }
00605
00606 dbus_message_iter_get_basic (iter, &objpath);
00607
00608 g_value_set_boxed_take_ownership (value, g_strdup (objpath));
00609
00610 return TRUE;
00611 }
00612
00613 static gboolean
00614 demarshal_object (DBusGValueMarshalCtx *context,
00615 DBusMessageIter *iter,
00616 GValue *value,
00617 GError **error)
00618 {
00619 const char *objpath;
00620 int current_type;
00621 GObject *obj;
00622
00623 current_type = dbus_message_iter_get_arg_type (iter);
00624 if (current_type != DBUS_TYPE_OBJECT_PATH)
00625 {
00626 g_set_error (error,
00627 DBUS_GERROR,
00628 DBUS_GERROR_INVALID_ARGS,
00629 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00630 return FALSE;
00631 }
00632 g_assert (context->proxy == NULL);
00633
00634 dbus_message_iter_get_basic (iter, &objpath);
00635
00636 obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
00637 if (obj == NULL)
00638 {
00639 g_set_error (error,
00640 DBUS_GERROR,
00641 DBUS_GERROR_INVALID_ARGS,
00642 _("Unregistered object at path '%s'"),
00643 objpath);
00644 return FALSE;
00645 }
00646 g_value_set_object (value, obj);
00647
00648 return TRUE;
00649 }
00650
00651 static gboolean
00652 demarshal_strv (DBusGValueMarshalCtx *context,
00653 DBusMessageIter *iter,
00654 GValue *value,
00655 GError **error)
00656 {
00657 DBusMessageIter subiter;
00658 int current_type;
00659 char **ret;
00660 int len;
00661 int i;
00662
00663 current_type = dbus_message_iter_get_arg_type (iter);
00664 if (current_type != DBUS_TYPE_ARRAY)
00665 {
00666 g_set_error (error,
00667 DBUS_GERROR,
00668 DBUS_GERROR_INVALID_ARGS,
00669 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00670 return FALSE;
00671 }
00672
00673 dbus_message_iter_recurse (iter, &subiter);
00674
00675 current_type = dbus_message_iter_get_arg_type (&subiter);
00676 if (current_type != DBUS_TYPE_INVALID
00677 && current_type != DBUS_TYPE_STRING)
00678 {
00679 g_set_error (error,
00680 DBUS_GERROR,
00681 DBUS_GERROR_INVALID_ARGS,
00682 _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
00683 return FALSE;
00684 }
00685
00686 len = dbus_message_iter_get_array_len (&subiter);
00687 g_assert (len >= 0);
00688 ret = g_malloc (sizeof (char *) * (len + 1));
00689
00690 i = 0;
00691 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00692 {
00693 g_assert (i < len);
00694 g_assert (current_type == DBUS_TYPE_STRING);
00695
00696 dbus_message_iter_get_basic (&subiter, &(ret[i]));
00697 ret[i] = g_strdup (ret[i]);
00698
00699 dbus_message_iter_next (&subiter);
00700 i++;
00701 }
00702 ret[i] = NULL;
00703 g_value_set_boxed_take_ownership (value, ret);
00704
00705 return TRUE;
00706 }
00707
00708 static gboolean
00709 demarshal_valuearray (DBusGValueMarshalCtx *context,
00710 DBusMessageIter *iter,
00711 GValue *value,
00712 GError **error)
00713 {
00714 int current_type;
00715 GValueArray *ret;
00716 DBusMessageIter subiter;
00717
00718 current_type = dbus_message_iter_get_arg_type (iter);
00719 if (current_type != DBUS_TYPE_STRUCT)
00720 {
00721 g_set_error (error,
00722 DBUS_GERROR,
00723 DBUS_GERROR_INVALID_ARGS,
00724 _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00725 return FALSE;
00726 }
00727
00728 dbus_message_iter_recurse (iter, &subiter);
00729
00730 ret = g_value_array_new (12);
00731
00732 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00733 {
00734 GValue *val;
00735 GType elt_type;
00736 char *current_sig;
00737
00738 g_value_array_append (ret, NULL);
00739 val = g_value_array_get_nth (ret, ret->n_values - 1);
00740
00741 current_sig = dbus_message_iter_get_signature (&subiter);
00742 elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
00743
00744 g_free (current_sig);
00745 if (elt_type == G_TYPE_INVALID)
00746 {
00747 g_value_array_free (ret);
00748 g_set_error (error,
00749 DBUS_GERROR,
00750 DBUS_GERROR_INVALID_ARGS,
00751 _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00752 return FALSE;
00753 }
00754
00755 g_value_init (val, elt_type);
00756
00757 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00758 {
00759 g_value_array_free (ret);
00760 return FALSE;
00761 }
00762
00763 dbus_message_iter_next (&subiter);
00764 }
00765
00766 g_value_set_boxed_take_ownership (value, ret);
00767
00768 return TRUE;
00769 }
00770
00771 static gboolean
00772 demarshal_map (DBusGValueMarshalCtx *context,
00773 DBusMessageIter *iter,
00774 GValue *value,
00775 GError **error)
00776 {
00777 GType gtype;
00778 DBusMessageIter subiter;
00779 int current_type;
00780 gpointer ret;
00781 GType key_gtype;
00782 GType value_gtype;
00783 DBusGTypeSpecializedAppendContext appendctx;
00784
00785 current_type = dbus_message_iter_get_arg_type (iter);
00786 if (current_type != DBUS_TYPE_ARRAY)
00787 {
00788 g_set_error (error,
00789 DBUS_GERROR,
00790 DBUS_GERROR_INVALID_ARGS,
00791 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00792 return FALSE;
00793 }
00794
00795 gtype = G_VALUE_TYPE (value);
00796
00797 dbus_message_iter_recurse (iter, &subiter);
00798
00799 current_type = dbus_message_iter_get_arg_type (&subiter);
00800 if (current_type != DBUS_TYPE_INVALID
00801 && current_type != DBUS_TYPE_DICT_ENTRY)
00802 {
00803 g_set_error (error,
00804 DBUS_GERROR,
00805 DBUS_GERROR_INVALID_ARGS,
00806 _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00807 return FALSE;
00808 }
00809
00810 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00811 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00812
00813 ret = dbus_g_type_specialized_construct (gtype);
00814 g_value_set_boxed_take_ownership (value, ret);
00815
00816 dbus_g_type_specialized_init_append (value, &appendctx);
00817
00818 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00819 {
00820 DBusMessageIter entry_iter;
00821 GValue key_value = {0,};
00822 GValue value_value = {0,};
00823
00824 current_type = dbus_message_iter_get_arg_type (&subiter);
00825 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00826
00827 dbus_message_iter_recurse (&subiter, &entry_iter);
00828
00829 g_value_init (&key_value, key_gtype);
00830 if (!_dbus_gvalue_demarshal (context,
00831 &entry_iter,
00832 &key_value,
00833 error))
00834 return FALSE;
00835
00836 dbus_message_iter_next (&entry_iter);
00837
00838 g_value_init (&value_value, value_gtype);
00839 if (!_dbus_gvalue_demarshal (context,
00840 &entry_iter,
00841 &value_value,
00842 error))
00843 return FALSE;
00844
00845 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00846
00847
00848 dbus_message_iter_next (&subiter);
00849 }
00850
00851 return TRUE;
00852 }
00853
00854 static DBusGValueDemarshalFunc
00855 get_type_demarshaller (GType type)
00856 {
00857 DBusGTypeMarshalData *typedata;
00858
00859 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00860 if (typedata == NULL)
00861 {
00862 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00863 return demarshal_valuearray;
00864 if (dbus_g_type_is_collection (type))
00865 return demarshal_collection;
00866 if (dbus_g_type_is_map (type))
00867 return demarshal_map;
00868
00869 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00870 return NULL;
00871 }
00872 g_assert (typedata->vtable);
00873 return typedata->vtable->demarshaller;
00874 }
00875
00876 static gboolean
00877 demarshal_collection (DBusGValueMarshalCtx *context,
00878 DBusMessageIter *iter,
00879 GValue *value,
00880 GError **error)
00881 {
00882 GType coltype;
00883 GType subtype;
00884
00885 coltype = G_VALUE_TYPE (value);
00886 subtype = dbus_g_type_get_collection_specialization (coltype);
00887
00888 if (_dbus_g_type_is_fixed (subtype))
00889 return demarshal_collection_array (context, iter, value, error);
00890 else
00891 return demarshal_collection_ptrarray (context, iter, value, error);
00892 }
00893
00894 static gboolean
00895 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
00896 DBusMessageIter *iter,
00897 GValue *value,
00898 GError **error)
00899 {
00900 GType coltype;
00901 GType subtype;
00902 gpointer instance;
00903 DBusGTypeSpecializedAppendContext ctx;
00904 DBusGValueDemarshalFunc demarshaller;
00905 DBusMessageIter subiter;
00906 int current_type;
00907
00908 current_type = dbus_message_iter_get_arg_type (iter);
00909
00910 if (current_type != DBUS_TYPE_ARRAY)
00911 {
00912 g_set_error (error,
00913 DBUS_GERROR,
00914 DBUS_GERROR_INVALID_ARGS,
00915 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00916 return FALSE;
00917 }
00918
00919 dbus_message_iter_recurse (iter, &subiter);
00920
00921 coltype = G_VALUE_TYPE (value);
00922 subtype = dbus_g_type_get_collection_specialization (coltype);
00923
00924 demarshaller = get_type_demarshaller (subtype);
00925
00926 if (!demarshaller)
00927 {
00928 g_set_error (error,
00929 DBUS_GERROR,
00930 DBUS_GERROR_INVALID_ARGS,
00931 _("No demarshaller registered for type \"%s\" of collection \"%s\""),
00932 g_type_name (coltype),
00933 g_type_name (subtype));
00934 return FALSE;
00935 }
00936
00937 instance = dbus_g_type_specialized_construct (coltype);
00938 g_value_set_boxed_take_ownership (value, instance);
00939
00940 dbus_g_type_specialized_init_append (value, &ctx);
00941
00942 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00943 {
00944 GValue eltval = {0, };
00945
00946 g_value_init (&eltval, subtype);
00947
00948 if (!demarshaller (context, &subiter, &eltval, error))
00949 {
00950 dbus_g_type_specialized_collection_end_append (&ctx);
00951 g_value_unset (value);
00952 return FALSE;
00953 }
00954 dbus_g_type_specialized_collection_append (&ctx, &eltval);
00955
00956 dbus_message_iter_next (&subiter);
00957 }
00958 dbus_g_type_specialized_collection_end_append (&ctx);
00959
00960 return TRUE;
00961 }
00962
00963 static gboolean
00964 demarshal_collection_array (DBusGValueMarshalCtx *context,
00965 DBusMessageIter *iter,
00966 GValue *value,
00967 GError **error)
00968 {
00969 DBusMessageIter subiter;
00970 GArray *ret;
00971 GType elt_gtype;
00972 int elt_size;
00973 void *msgarray;
00974 int msgarray_len;
00975
00976 dbus_message_iter_recurse (iter, &subiter);
00977
00978 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
00979 g_assert (elt_gtype != G_TYPE_INVALID);
00980 g_assert (_dbus_g_type_is_fixed (elt_gtype));
00981
00982 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
00983
00984 ret = g_array_new (FALSE, TRUE, elt_size);
00985
00986 msgarray = NULL;
00987 dbus_message_iter_get_fixed_array (&subiter,
00988 &msgarray,
00989 &msgarray_len);
00990 g_assert (msgarray != NULL);
00991 g_assert (msgarray_len >= 0);
00992 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
00993
00994 g_value_set_boxed_take_ownership (value, ret);
00995
00996 return TRUE;
00997 }
00998
00999 gboolean
01000 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
01001 DBusMessageIter *iter,
01002 GValue *value,
01003 GError **error)
01004 {
01005 GType gtype;
01006 DBusGValueDemarshalFunc demarshaller;
01007
01008 gtype = G_VALUE_TYPE (value);
01009
01010 demarshaller = get_type_demarshaller (gtype);
01011
01012 if (demarshaller == NULL)
01013 {
01014 g_set_error (error,
01015 DBUS_GERROR,
01016 DBUS_GERROR_INVALID_ARGS,
01017 _("No demarshaller registered for type \"%s\""),
01018 g_type_name (gtype));
01019 return FALSE;
01020 }
01021
01022 return demarshaller (context, iter, value, error);
01023 }
01024
01025 gboolean
01026 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
01027 DBusMessageIter *iter,
01028 GValue *value,
01029 GError **error)
01030 {
01031 return demarshal_static_variant (context, iter, value, error);
01032 }
01033
01034 GValueArray *
01035 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
01036 DBusMessage *message,
01037 guint n_types,
01038 const GType *types,
01039 GError **error)
01040 {
01041 GValueArray *ret;
01042 DBusMessageIter iter;
01043 int current_type;
01044 guint index;
01045
01046 ret = g_value_array_new (6);
01047
01048 dbus_message_iter_init (message, &iter);
01049 index = 0;
01050 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01051 {
01052 GValue *value;
01053 GType gtype;
01054
01055 if (index >= n_types)
01056 {
01057 g_set_error (error, DBUS_GERROR,
01058 DBUS_GERROR_INVALID_ARGS,
01059 _("Too many arguments in message"));
01060 goto lose;
01061 }
01062
01063 g_value_array_append (ret, NULL);
01064 value = g_value_array_get_nth (ret, index);
01065
01066 gtype = types[index];
01067 g_value_init (value, gtype);
01068
01069 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01070 goto lose;
01071 dbus_message_iter_next (&iter);
01072 index++;
01073 }
01074 if (index < n_types)
01075 {
01076 g_set_error (error, DBUS_GERROR,
01077 DBUS_GERROR_INVALID_ARGS,
01078 _("Too few arguments in message"));
01079 goto lose;
01080 }
01081
01082 return ret;
01083 lose:
01084 g_value_array_free (ret);
01085 return NULL;
01086 }
01087
01088 static gboolean
01089 marshal_basic (DBusMessageIter *iter, const GValue *value)
01090 {
01091 GType value_type;
01092
01093 value_type = G_VALUE_TYPE (value);
01094
01095 switch (value_type)
01096 {
01097 case G_TYPE_CHAR:
01098 {
01099 char b = g_value_get_char (value);
01100 if (!dbus_message_iter_append_basic (iter,
01101 DBUS_TYPE_BYTE,
01102 &b))
01103 goto nomem;
01104 }
01105 return TRUE;
01106 case G_TYPE_UCHAR:
01107 {
01108 unsigned char b = g_value_get_uchar (value);
01109 if (!dbus_message_iter_append_basic (iter,
01110 DBUS_TYPE_BYTE,
01111 &b))
01112 goto nomem;
01113 }
01114 return TRUE;
01115 case G_TYPE_BOOLEAN:
01116 {
01117 dbus_bool_t b = g_value_get_boolean (value);
01118 if (!dbus_message_iter_append_basic (iter,
01119 DBUS_TYPE_BOOLEAN,
01120 &b))
01121 goto nomem;
01122 }
01123 return TRUE;
01124 case G_TYPE_INT:
01125 {
01126 dbus_int32_t v = g_value_get_int (value);
01127 if (!dbus_message_iter_append_basic (iter,
01128 DBUS_TYPE_INT32,
01129 &v))
01130 goto nomem;
01131 }
01132 return TRUE;
01133 case G_TYPE_UINT:
01134 {
01135 dbus_uint32_t v = g_value_get_uint (value);
01136 if (!dbus_message_iter_append_basic (iter,
01137 DBUS_TYPE_UINT32,
01138 &v))
01139 goto nomem;
01140 }
01141 return TRUE;
01142 case G_TYPE_LONG:
01143 {
01144 dbus_int32_t v = g_value_get_long (value);
01145 if (!dbus_message_iter_append_basic (iter,
01146 DBUS_TYPE_INT32,
01147 &v))
01148 goto nomem;
01149 }
01150 return TRUE;
01151 case G_TYPE_ULONG:
01152 {
01153 dbus_uint32_t v = g_value_get_ulong (value);
01154 if (!dbus_message_iter_append_basic (iter,
01155 DBUS_TYPE_UINT32,
01156 &v))
01157 goto nomem;
01158 }
01159 return TRUE;
01160 case G_TYPE_INT64:
01161 {
01162 gint64 v = g_value_get_int64 (value);
01163 if (!dbus_message_iter_append_basic (iter,
01164 DBUS_TYPE_INT64,
01165 &v))
01166 goto nomem;
01167 }
01168 return TRUE;
01169 case G_TYPE_UINT64:
01170 {
01171 guint64 v = g_value_get_uint64 (value);
01172 if (!dbus_message_iter_append_basic (iter,
01173 DBUS_TYPE_UINT64,
01174 &v))
01175 goto nomem;
01176 }
01177 return TRUE;
01178 case G_TYPE_FLOAT:
01179 {
01180 double v = g_value_get_float (value);
01181
01182 if (!dbus_message_iter_append_basic (iter,
01183 DBUS_TYPE_DOUBLE,
01184 &v))
01185 goto nomem;
01186 }
01187 return TRUE;
01188 case G_TYPE_DOUBLE:
01189 {
01190 double v = g_value_get_double (value);
01191
01192 if (!dbus_message_iter_append_basic (iter,
01193 DBUS_TYPE_DOUBLE,
01194 &v))
01195 goto nomem;
01196 }
01197 return TRUE;
01198 case G_TYPE_STRING:
01199
01200 {
01201 const char *v = g_value_get_string (value);
01202 if (!v)
01203 v = "";
01204 if (!dbus_message_iter_append_basic (iter,
01205 DBUS_TYPE_STRING,
01206 &v))
01207 goto nomem;
01208 }
01209 return TRUE;
01210
01211 default:
01212 {
01213 g_assert_not_reached ();
01214 return FALSE;
01215 }
01216 }
01217
01218 nomem:
01219 g_error ("no memory");
01220 return FALSE;
01221 }
01222
01223 static gboolean
01224 marshal_strv (DBusMessageIter *iter,
01225 const GValue *value)
01226 {
01227 DBusMessageIter subiter;
01228 char **array;
01229 char **elt;
01230 gboolean ret = FALSE;
01231
01232 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01233
01234 array = g_value_get_boxed (value);
01235
01236 if (!dbus_message_iter_open_container (iter,
01237 DBUS_TYPE_ARRAY,
01238 "s",
01239 &subiter))
01240 goto out;
01241
01242 for (elt = array; *elt; elt++)
01243 {
01244 if (!dbus_message_iter_append_basic (&subiter,
01245 DBUS_TYPE_STRING,
01246 elt))
01247 goto out;
01248 }
01249
01250 if (!dbus_message_iter_close_container (iter, &subiter))
01251 goto out;
01252 ret = TRUE;
01253 out:
01254 return ret;
01255 }
01256
01257 static gboolean
01258 marshal_valuearray (DBusMessageIter *iter,
01259 const GValue *value)
01260 {
01261 GValueArray *array;
01262 guint i;
01263 DBusMessageIter subiter;
01264
01265 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01266
01267 array = g_value_get_boxed (value);
01268
01269 if (!dbus_message_iter_open_container (iter,
01270 DBUS_TYPE_STRUCT,
01271 NULL,
01272 &subiter))
01273 goto oom;
01274
01275 for (i = 0; i < array->n_values; i++)
01276 {
01277 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01278 return FALSE;
01279 }
01280
01281 if (!dbus_message_iter_close_container (iter, &subiter))
01282 goto oom;
01283
01284 return TRUE;
01285 oom:
01286 g_error ("out of memory");
01287 return FALSE;
01288 }
01289
01290 static gboolean
01291 marshal_proxy (DBusMessageIter *iter,
01292 const GValue *value)
01293 {
01294 const char *path;
01295 DBusGProxy *proxy;
01296
01297 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01298
01299 proxy = g_value_get_object (value);
01300 path = dbus_g_proxy_get_path (proxy);
01301
01302 if (!dbus_message_iter_append_basic (iter,
01303 DBUS_TYPE_OBJECT_PATH,
01304 &path))
01305 return FALSE;
01306 return TRUE;
01307 }
01308
01309 static gboolean
01310 marshal_object_path (DBusMessageIter *iter,
01311 const GValue *value)
01312 {
01313 const char *path;
01314
01315 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01316
01317 path = (const char*) g_value_get_boxed (value);
01318
01319 if (!dbus_message_iter_append_basic (iter,
01320 DBUS_TYPE_OBJECT_PATH,
01321 &path))
01322 return FALSE;
01323 return TRUE;
01324 }
01325
01326 static gboolean
01327 marshal_object (DBusMessageIter *iter,
01328 const GValue *value)
01329 {
01330 const char *path;
01331 GObject *obj;
01332
01333 obj = g_value_get_object (value);
01334 path = _dbus_gobject_get_path (obj);
01335
01336 if (path == NULL)
01337
01338 return FALSE;
01339
01340 if (!dbus_message_iter_append_basic (iter,
01341 DBUS_TYPE_OBJECT_PATH,
01342 &path))
01343 return FALSE;
01344 return TRUE;
01345 }
01346
01347 struct DBusGLibHashMarshalData
01348 {
01349 const char *entry_sig;
01350 DBusMessageIter *iter;
01351 gboolean err;
01352 };
01353
01354 static void
01355 marshal_map_entry (const GValue *key,
01356 const GValue *value,
01357 gpointer data)
01358 {
01359 struct DBusGLibHashMarshalData *hashdata = data;
01360 DBusMessageIter subiter;
01361
01362 if (hashdata->err)
01363 return;
01364
01365 if (!dbus_message_iter_open_container (hashdata->iter,
01366 DBUS_TYPE_DICT_ENTRY,
01367 NULL,
01368 &subiter))
01369 goto lose;
01370
01371 if (!_dbus_gvalue_marshal (&subiter, key))
01372 goto lose;
01373
01374 if (!_dbus_gvalue_marshal (&subiter, value))
01375 goto lose;
01376
01377 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01378 goto lose;
01379
01380 return;
01381 lose:
01382 hashdata->err = TRUE;
01383 }
01384
01385 static gboolean
01386 marshal_map (DBusMessageIter *iter,
01387 const GValue *value)
01388 {
01389 GType gtype;
01390 DBusMessageIter arr_iter;
01391 gboolean ret;
01392 struct DBusGLibHashMarshalData hashdata;
01393 char *key_sig;
01394 char *value_sig;
01395 GType key_type;
01396 GType value_type;
01397 char *entry_sig;
01398 char *array_sig;
01399
01400 gtype = G_VALUE_TYPE (value);
01401
01402 ret = FALSE;
01403
01404 key_type = dbus_g_type_get_map_key_specialization (gtype);
01405 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01406 value_type = dbus_g_type_get_map_value_specialization (gtype);
01407 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01408
01409 key_sig = _dbus_gtype_to_signature (key_type);
01410 if (!key_sig)
01411 {
01412 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01413 return FALSE;
01414 }
01415 value_sig = _dbus_gtype_to_signature (value_type);
01416 if (!value_sig)
01417 {
01418 g_free (key_sig);
01419 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01420 return FALSE;
01421 }
01422 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01423 g_free (key_sig);
01424 g_free (value_sig);
01425 array_sig = g_strdup_printf ("%c%s%c",
01426 DBUS_DICT_ENTRY_BEGIN_CHAR,
01427 entry_sig,
01428 DBUS_DICT_ENTRY_END_CHAR);
01429 if (!dbus_message_iter_open_container (iter,
01430 DBUS_TYPE_ARRAY,
01431 array_sig,
01432 &arr_iter))
01433 goto lose;
01434
01435 hashdata.iter = &arr_iter;
01436 hashdata.err = FALSE;
01437 hashdata.entry_sig = entry_sig;
01438
01439 dbus_g_type_map_value_iterate (value,
01440 marshal_map_entry,
01441 &hashdata);
01442
01443 if (!dbus_message_iter_close_container (iter, &arr_iter))
01444 goto lose;
01445
01446 out:
01447 g_free (entry_sig);
01448 g_free (array_sig);
01449 return !hashdata.err;
01450 lose:
01451 hashdata.err = TRUE;
01452 goto out;
01453 }
01454
01455 static gboolean
01456 marshal_variant (DBusMessageIter *iter,
01457 const GValue *value)
01458 {
01459 GType value_gtype;
01460 DBusMessageIter subiter;
01461 char *variant_sig;
01462 GValue *real_value;
01463 gboolean ret = FALSE;
01464
01465 real_value = g_value_get_boxed (value);
01466 value_gtype = G_VALUE_TYPE (real_value);
01467
01468 variant_sig = _dbus_gvalue_to_signature (real_value);
01469 if (variant_sig == NULL)
01470 {
01471 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01472 return FALSE;
01473 }
01474
01475 if (!dbus_message_iter_open_container (iter,
01476 DBUS_TYPE_VARIANT,
01477 variant_sig,
01478 &subiter))
01479 goto out;
01480
01481 if (!_dbus_gvalue_marshal (&subiter, real_value))
01482 goto out;
01483
01484 if (!dbus_message_iter_close_container (iter, &subiter))
01485 goto out;
01486
01487 ret = TRUE;
01488 out:
01489 g_free (variant_sig);
01490 return ret;
01491 }
01492
01493 static DBusGValueMarshalFunc
01494 get_type_marshaller (GType type)
01495 {
01496 DBusGTypeMarshalData *typedata;
01497
01498 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01499 if (typedata == NULL)
01500 {
01501 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01502 return marshal_valuearray;
01503 if (dbus_g_type_is_collection (type))
01504 return marshal_collection;
01505 if (dbus_g_type_is_map (type))
01506 return marshal_map;
01507
01508 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01509 return NULL;
01510 }
01511 g_assert (typedata->vtable);
01512 return typedata->vtable->marshaller;
01513 }
01514
01515 typedef struct
01516 {
01517 DBusMessageIter *iter;
01518 DBusGValueMarshalFunc marshaller;
01519 gboolean err;
01520 } DBusGValueCollectionMarshalData;
01521
01522 static void
01523 collection_marshal_iterator (const GValue *eltval,
01524 gpointer user_data)
01525 {
01526 DBusGValueCollectionMarshalData *data = user_data;
01527
01528 if (data->err)
01529 return;
01530
01531 if (!data->marshaller (data->iter, eltval))
01532 data->err = TRUE;
01533 }
01534
01535 static gboolean
01536 marshal_collection (DBusMessageIter *iter,
01537 const GValue *value)
01538 {
01539 GType coltype;
01540 GType subtype;
01541
01542 coltype = G_VALUE_TYPE (value);
01543 subtype = dbus_g_type_get_collection_specialization (coltype);
01544
01545 if (_dbus_g_type_is_fixed (subtype))
01546 return marshal_collection_array (iter, value);
01547 else
01548 return marshal_collection_ptrarray (iter, value);
01549 }
01550
01551 static gboolean
01552 marshal_collection_ptrarray (DBusMessageIter *iter,
01553 const GValue *value)
01554 {
01555 GType coltype;
01556 GType elt_gtype;
01557 DBusGValueCollectionMarshalData data;
01558 DBusMessageIter subiter;
01559 char *elt_sig;
01560
01561 coltype = G_VALUE_TYPE (value);
01562 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01563 data.marshaller = get_type_marshaller (elt_gtype);
01564 if (!data.marshaller)
01565 return FALSE;
01566
01567 elt_sig = _dbus_gtype_to_signature (elt_gtype);
01568 if (!elt_sig)
01569 {
01570 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01571 return FALSE;
01572 }
01573
01574 if (!dbus_message_iter_open_container (iter,
01575 DBUS_TYPE_ARRAY,
01576 elt_sig,
01577 &subiter))
01578 goto oom;
01579 g_free (elt_sig);
01580
01581 data.iter = &subiter;
01582 data.err = FALSE;
01583
01584 dbus_g_type_collection_value_iterate (value,
01585 collection_marshal_iterator,
01586 &data);
01587
01588 if (!dbus_message_iter_close_container (iter, &subiter))
01589 goto oom;
01590
01591 return !data.err;
01592 oom:
01593 g_error ("out of memory");
01594 return FALSE;
01595 }
01596
01597
01598 static gboolean
01599 marshal_collection_array (DBusMessageIter *iter,
01600 const GValue *value)
01601 {
01602 GType elt_gtype;
01603 DBusMessageIter subiter;
01604 GArray *array;
01605 guint elt_size;
01606 char *subsignature_str;
01607
01608 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01609 g_assert (_dbus_g_type_is_fixed (elt_gtype));
01610 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01611 if (!subsignature_str)
01612 {
01613 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01614 return FALSE;
01615 }
01616
01617 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01618
01619 array = g_value_get_boxed (value);
01620
01621 if (!dbus_message_iter_open_container (iter,
01622 DBUS_TYPE_ARRAY,
01623 subsignature_str,
01624 &subiter))
01625 goto oom;
01626
01627
01628
01629
01630
01631 if (!dbus_message_iter_append_fixed_array (&subiter,
01632 subsignature_str[0],
01633 &(array->data),
01634 array->len))
01635 goto oom;
01636
01637 if (!dbus_message_iter_close_container (iter, &subiter))
01638 goto oom;
01639 g_free (subsignature_str);
01640 return TRUE;
01641 oom:
01642 g_error ("out of memory");
01643 return FALSE;
01644 }
01645
01646 gboolean
01647 _dbus_gvalue_marshal (DBusMessageIter *iter,
01648 const GValue *value)
01649 {
01650 GType gtype;
01651 DBusGValueMarshalFunc marshaller;
01652
01653 gtype = G_VALUE_TYPE (value);
01654
01655 marshaller = get_type_marshaller (gtype);
01656 if (marshaller == NULL)
01657 return FALSE;
01658 return marshaller (iter, value);
01659 }
01660
01661 #ifdef DBUS_BUILD_TESTS
01662
01663 static void
01664 assert_type_maps_to (GType gtype, const char *expected_sig)
01665 {
01666 char *sig;
01667 sig = _dbus_gtype_to_signature (gtype);
01668 g_assert (sig != NULL);
01669 g_assert (!strcmp (expected_sig, sig));
01670 g_free (sig);
01671 }
01672
01673 static void
01674 assert_signature_maps_to (const char *sig, GType expected_gtype)
01675 {
01676 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01677 }
01678
01679 static void
01680 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01681 {
01682 assert_type_maps_to (gtype, expected_sig);
01683 assert_signature_maps_to (expected_sig, gtype);
01684 }
01685
01691 gboolean
01692 _dbus_gvalue_test (const char *test_data_dir)
01693 {
01694 _dbus_g_value_types_init ();
01695
01696 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01697 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01698 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01699
01700 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);
01701 assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
01702 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);
01703
01704 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01705 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);
01706 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01707 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01708 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01709 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01710
01711 return TRUE;
01712 }
01713
01714 #endif