/** * json_gvariant_serialize: * @variant: A #GVariant to convert * * Converts @variant to a JSON tree. * * Return value: (transfer full): A #JsonNode representing the root of the * JSON data structure obtained from @variant * * Since: 0.14 */ JsonNode * json_gvariant_serialize (GVariant *variant) { JsonNode *json_node = NULL; GVariantClass class; g_return_val_if_fail (variant != NULL, NULL); class = g_variant_classify (variant); if (! g_variant_is_container (variant)) { json_node = json_node_new (JSON_NODE_VALUE); switch (class) { case G_VARIANT_CLASS_BOOLEAN: json_node_set_boolean (json_node, g_variant_get_boolean (variant)); break; case G_VARIANT_CLASS_BYTE: json_node_set_int (json_node, g_variant_get_byte (variant)); break; case G_VARIANT_CLASS_INT16: json_node_set_int (json_node, g_variant_get_int16 (variant)); break; case G_VARIANT_CLASS_UINT16: json_node_set_int (json_node, g_variant_get_uint16 (variant)); break; case G_VARIANT_CLASS_INT32: json_node_set_int (json_node, g_variant_get_int32 (variant)); break; case G_VARIANT_CLASS_UINT32: json_node_set_int (json_node, g_variant_get_uint32 (variant)); break; case G_VARIANT_CLASS_INT64: json_node_set_int (json_node, g_variant_get_int64 (variant)); break; case G_VARIANT_CLASS_UINT64: json_node_set_int (json_node, g_variant_get_uint64 (variant)); break; case G_VARIANT_CLASS_HANDLE: json_node_set_int (json_node, g_variant_get_handle (variant)); break; case G_VARIANT_CLASS_DOUBLE: json_node_set_double (json_node, g_variant_get_double (variant)); break; case G_VARIANT_CLASS_STRING: case G_VARIANT_CLASS_OBJECT_PATH: case G_VARIANT_CLASS_SIGNATURE: json_node_set_string (json_node, g_variant_get_string (variant, NULL)); break; default: break; } }
static GInputStream * g_vfs_icon_load (GLoadableIcon *icon, int size, char **type, GCancellable *cancellable, GError **error) { GVfsIcon *vfs_icon = G_VFS_ICON (icon); GVfsDBusMount *proxy; gboolean res; gboolean can_seek; GUnixFDList *fd_list; int fd; GVariant *fd_id_val = NULL; GError *local_error = NULL; proxy = create_proxy_for_icon (vfs_icon, cancellable, error); if (proxy == NULL) return NULL; res = gvfs_dbus_mount_call_open_icon_for_read_sync (proxy, vfs_icon->icon_id, NULL, &fd_id_val, &can_seek, &fd_list, cancellable, &local_error); if (! res) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy))); _g_propagate_error_stripped (error, local_error); } g_object_unref (proxy); if (! res) return NULL; if (fd_list == NULL || fd_id_val == NULL || g_unix_fd_list_get_length (fd_list) != 1 || (fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_id_val), NULL)) == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Didn't get stream file descriptor")); return NULL; } g_variant_unref (fd_id_val); g_object_unref (fd_list); return G_INPUT_STREAM (g_daemon_file_input_stream_new (fd, can_seek)); }
static gboolean g_settings_get_mapping_unsigned_int (GValue *value, GVariant *variant) { const GVariantType *type; guint64 u; type = g_variant_get_type (variant); if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16)) u = g_variant_get_uint16 (variant); else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) u = g_variant_get_uint32 (variant); else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64)) u = g_variant_get_uint64 (variant); else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE)) u = g_variant_get_handle (variant); else return FALSE; if (G_VALUE_HOLDS_INT (value)) { g_value_set_int (value, u); return (u <= G_MAXINT32); } else if (G_VALUE_HOLDS_UINT (value)) { g_value_set_uint (value, u); return (u <= G_MAXUINT32); } else if (G_VALUE_HOLDS_INT64 (value)) { g_value_set_int64 (value, u); return (u <= G_MAXINT64); } else if (G_VALUE_HOLDS_UINT64 (value)) { g_value_set_uint64 (value, u); return (u <= G_MAXUINT64); } else if (G_VALUE_HOLDS_DOUBLE (value)) { g_value_set_double (value, u); return TRUE; } return FALSE; }
static void open_icon_read_cb (GVfsDBusMount *proxy, GAsyncResult *res, gpointer user_data) { AsyncPathCall *data = user_data; GError *error = NULL; gboolean can_seek; GUnixFDList *fd_list; int fd; GVariant *fd_id_val; guint fd_id; GFileInputStream *stream; if (! gvfs_dbus_mount_call_open_icon_for_read_finish (proxy, &fd_id_val, &can_seek, &fd_list, res, &error)) { _g_simple_async_result_take_error_stripped (data->result, error); goto out; } fd_id = g_variant_get_handle (fd_id_val); g_variant_unref (fd_id_val); if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) { g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED, _("Couldn't get stream file descriptor")); } else { stream = g_daemon_file_input_stream_new (fd, can_seek); g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); g_object_unref (fd_list); } out: _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag); async_path_call_free (data); }
static JsonBuilder * _json_builder_add_gvariant (JsonBuilder *builder, GVariant *value) { g_return_val_if_fail (JSON_IS_BUILDER (builder), builder); g_variant_ref_sink (value); switch (g_variant_classify (value)) { case G_VARIANT_CLASS_BOOLEAN: json_builder_add_boolean_value (builder, g_variant_get_boolean (value)); break; case G_VARIANT_CLASS_BYTE: json_builder_add_int_value (builder, g_variant_get_byte (value)); break; case G_VARIANT_CLASS_INT16: json_builder_add_int_value (builder, g_variant_get_int16 (value)); break; case G_VARIANT_CLASS_UINT16: json_builder_add_int_value (builder, g_variant_get_uint16 (value)); break; case G_VARIANT_CLASS_INT32: json_builder_add_int_value (builder, g_variant_get_int32 (value)); break; case G_VARIANT_CLASS_UINT32: json_builder_add_int_value (builder, g_variant_get_uint32 (value)); break; case G_VARIANT_CLASS_INT64: json_builder_add_int_value (builder, g_variant_get_int64 (value)); break; case G_VARIANT_CLASS_UINT64: json_builder_add_int_value (builder, g_variant_get_uint64 (value)); break; case G_VARIANT_CLASS_HANDLE: json_builder_add_int_value (builder, g_variant_get_handle (value)); break; case G_VARIANT_CLASS_DOUBLE: json_builder_add_double_value (builder, g_variant_get_double (value)); break; case G_VARIANT_CLASS_STRING: /* explicit fall-through */ case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */ case G_VARIANT_CLASS_SIGNATURE: json_builder_add_string_value (builder, g_variant_get_string (value, NULL)); break; /* TODO: */ case G_VARIANT_CLASS_VARIANT: { GVariant *child; child = g_variant_get_variant (value); _json_builder_add_gvariant (builder, child); g_variant_unref (child); } break; case G_VARIANT_CLASS_MAYBE: g_assert_not_reached (); break; case G_VARIANT_CLASS_ARRAY: { const GVariantType *type; const GVariantType *element_type; type = g_variant_get_type (value); element_type = g_variant_type_element (type); if (g_variant_type_is_dict_entry (element_type)) { GVariantIter iter; GVariant *child; json_builder_begin_object (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_object (builder); } else { GVariantIter iter; GVariant *child; json_builder_begin_array (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_array (builder); } } break; case G_VARIANT_CLASS_TUPLE: { GVariantIter iter; GVariant *child; json_builder_begin_array (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_array (builder); } break; case G_VARIANT_CLASS_DICT_ENTRY: { GVariant *dict_key; GVariant *dict_value; gchar *dict_key_string; dict_key = g_variant_get_child_value (value, 0); dict_value = g_variant_get_child_value (value, 1); if (g_variant_is_of_type (dict_key, G_VARIANT_TYPE("s"))) dict_key_string = g_variant_dup_string (dict_key, NULL); else dict_key_string = g_variant_print (dict_key, FALSE); json_builder_set_member_name (builder, dict_key_string); _json_builder_add_gvariant (builder, dict_value); g_free (dict_key_string); g_variant_unref (dict_key); g_variant_unref (dict_value); } break; } g_variant_unref (value); return builder; }
/* runs in thread dedicated to handling @invocation */ static gboolean handle_loop_setup (StoragedManager *object, GDBusMethodInvocation *invocation, GUnixFDList *fd_list, GVariant *fd_index, GVariant *options) { StoragedLinuxManager *manager = STORAGED_LINUX_MANAGER (object); GError *error; gint fd_num; gint fd = -1; gchar proc_path[64]; gchar path[8192]; ssize_t path_len; gint loop_fd = -1; gint loop_control_fd = -1; gint allocated_loop_number = -1; gchar *loop_device = NULL; struct loop_info64 li64; StoragedObject *loop_object = NULL; gboolean option_read_only = FALSE; gboolean option_no_part_scan = FALSE; guint64 option_offset = 0; guint64 option_size = 0; uid_t caller_uid; struct stat fd_statbuf; gboolean fd_statbuf_valid = FALSE; WaitForLoopData wait_data; /* we need the uid of the caller for the loop file */ error = NULL; if (!storaged_daemon_util_get_caller_uid_sync (manager->daemon, invocation, NULL /* GCancellable */, &caller_uid, NULL, NULL, &error)) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); goto out; } /* Check if the user is authorized to create a loop device */ if (!storaged_daemon_util_check_authorization_sync (manager->daemon, NULL, "org.storaged.Storaged.loop-setup", options, /* Translators: Shown in authentication dialog when the user * requests setting up a loop device. */ N_("Authentication is required to set up a loop device"), invocation)) goto out; fd_num = g_variant_get_handle (fd_index); if (fd_list == NULL || fd_num >= g_unix_fd_list_get_length (fd_list)) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Expected to use fd at index %d, but message has only %d fds", fd_num, fd_list == NULL ? 0 : g_unix_fd_list_get_length (fd_list)); goto out; } error = NULL; fd = g_unix_fd_list_get (fd_list, fd_num, &error); if (fd == -1) { g_prefix_error (&error, "Error getting file descriptor %d from message: ", fd_num); g_dbus_method_invocation_take_error (invocation, error); goto out; } snprintf (proc_path, sizeof (proc_path), "/proc/%d/fd/%d", getpid (), fd); path_len = readlink (proc_path, path, sizeof (path) - 1); if (path_len < 1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error determing path: %m"); goto out; } path[path_len] = '\0'; g_variant_lookup (options, "read-only", "b", &option_read_only); g_variant_lookup (options, "offset", "t", &option_offset); g_variant_lookup (options, "size", "t", &option_size); g_variant_lookup (options, "no-part-scan", "b", &option_no_part_scan); /* it's not a problem if fstat fails... for example, this can happen if the user * passes a fd to a file on the GVfs fuse mount */ if (fstat (fd, &fd_statbuf) == 0) fd_statbuf_valid = TRUE; /* serialize access to /dev/loop-control */ g_mutex_lock (&(manager->lock)); loop_control_fd = open ("/dev/loop-control", O_RDWR); if (loop_control_fd == -1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error opening /dev/loop-control: %m"); g_mutex_unlock (&(manager->lock)); goto out; } allocated_loop_number = ioctl (loop_control_fd, LOOP_CTL_GET_FREE); if (allocated_loop_number < 0) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error allocating free loop device: %m"); g_mutex_unlock (&(manager->lock)); goto out; } loop_device = g_strdup_printf ("/dev/loop%d", allocated_loop_number); loop_fd = open (loop_device, option_read_only ? O_RDONLY : O_RDWR); if (loop_fd == -1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Cannot open %s: %m", loop_device); g_mutex_unlock (&(manager->lock)); goto out; } /* update the loop file - need to do this before getting the uevent for the device */ storaged_state_add_loop (storaged_daemon_get_state (manager->daemon), loop_device, path, fd_statbuf_valid ? fd_statbuf.st_dev : 0, caller_uid); memset (&li64, '\0', sizeof (li64)); strncpy ((char *) li64.lo_file_name, path, LO_NAME_SIZE - 1); if (option_read_only) li64.lo_flags |= LO_FLAGS_READ_ONLY; if (!option_no_part_scan) li64.lo_flags |= 8; /* Use LO_FLAGS_PARTSCAN when 3.2 has been out for a while */ li64.lo_offset = option_offset; li64.lo_sizelimit = option_size; if (ioctl (loop_fd, LOOP_SET_FD, fd) < 0 || ioctl (loop_fd, LOOP_SET_STATUS64, &li64) < 0) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error setting up loop device %s: %m", loop_device); g_mutex_unlock (&(manager->lock)); goto out; } g_mutex_unlock (&(manager->lock)); /* Determine the resulting object */ error = NULL; wait_data.loop_device = loop_device; wait_data.path = path; loop_object = storaged_daemon_wait_for_object_sync (manager->daemon, wait_for_loop_object, &wait_data, NULL, 10, /* timeout_seconds */ &error); if (loop_object == NULL) { g_prefix_error (&error, "Error waiting for loop object after creating %s", loop_device); g_dbus_method_invocation_take_error (invocation, error); goto out; } storaged_notice ("Set up loop device %s (backed by %s)", loop_device, path); storaged_manager_complete_loop_setup (object, invocation, NULL, /* fd_list */ g_dbus_object_get_object_path (G_DBUS_OBJECT (loop_object))); out: if (loop_object != NULL) g_object_unref (loop_object); g_free (loop_device); if (loop_control_fd != -1) close (loop_control_fd); if (loop_fd != -1) close (loop_fd); if (fd != -1) close (fd); return TRUE; /* returning TRUE means that we handled the method invocation */ }
static GConfValue * gconf_settings_backend_simple_gvariant_to_gconf_value (GVariant *value, const GVariantType *type) { GConfValue *gconf_value = NULL; if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) { gconf_value = gconf_value_new (GCONF_VALUE_BOOL); gconf_value_set_bool (gconf_value, g_variant_get_boolean (value)); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE)) { guchar i = g_variant_get_byte (value); gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16)) { gint16 i = g_variant_get_int16 (value); gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16)) { guint16 i = g_variant_get_uint16 (value); if (i > G_MAXINT) return NULL; gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32)) { gint32 i = g_variant_get_int32 (value); gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) { guint32 i = g_variant_get_uint32 (value); if (i > G_MAXINT) return NULL; gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64)) { gint64 i = g_variant_get_int64 (value); if (i < G_MININT || i > G_MAXINT) return NULL; gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64)) { guint64 i = g_variant_get_uint64 (value); if (i > G_MAXINT) return NULL; gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE)) { guint32 i = g_variant_get_handle (value); if (i > G_MAXINT) return NULL; gconf_value = gconf_value_new (GCONF_VALUE_INT); gconf_value_set_int (gconf_value, i); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE)) { gconf_value = gconf_value_new (GCONF_VALUE_FLOAT); gconf_value_set_float (gconf_value, g_variant_get_double (value)); } else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) || g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) || g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE)) { gconf_value = gconf_value_new (GCONF_VALUE_STRING); gconf_value_set_string (gconf_value, g_variant_get_string (value, NULL)); } return gconf_value; }
static void test_compare(CVariant *cv, GVariant *gv) { const GVariantType *gvt; GVariantIter gvi[C_VARIANT_MAX_VARG]; GVariant *gvig[C_VARIANT_MAX_VARG]; CVariantVarg varg; const char *s, *type; uint64_t val_64; uint32_t val_32; uint16_t val_16; uint8_t val_8; double val_f; size_t n, nest; GVariant *g; int r, c; type = c_variant_peek_type(cv, &n); gvt = g_variant_get_type(gv); assert(n == g_variant_type_get_string_length(gvt)); assert(!memcmp(type, g_variant_type_peek_string(gvt), n)); nest = 0; g = gv; for (c = c_variant_varg_init(&varg, type, n); c; c = c_variant_varg_next(&varg)) { if (c == -1) { r = c_variant_exit(cv, NULL); assert(r >= 0); assert(nest-- > 0); g_variant_unref(gvig[nest]); continue; } if (nest > 0) g = g_variant_iter_next_value(&gvi[nest - 1]); else g = g_variant_ref(gv); assert(g); switch (c) { case C_VARIANT_VARIANT: c_variant_enter(cv, "v"); type = c_variant_peek_type(cv, &n); c_variant_varg_push(&varg, type, n, -1); g_variant_iter_init(&gvi[nest], g); gvig[nest] = g_variant_ref(g); ++nest; break; case C_VARIANT_MAYBE: c_variant_enter(cv, "m"); n = c_variant_peek_count(cv); c_variant_varg_enter_bound(&varg, cv, n); g_variant_iter_init(&gvi[nest], g); gvig[nest] = g_variant_ref(g); ++nest; break; case C_VARIANT_ARRAY: c_variant_enter(cv, "a"); n = c_variant_peek_count(cv); c_variant_varg_enter_bound(&varg, cv, n); g_variant_iter_init(&gvi[nest], g); gvig[nest] = g_variant_ref(g); ++nest; break; case C_VARIANT_TUPLE_OPEN: c_variant_enter(cv, "("); c_variant_varg_enter_unbound(&varg, cv, ')'); g_variant_iter_init(&gvi[nest], g); gvig[nest] = g_variant_ref(g); ++nest; break; case C_VARIANT_PAIR_OPEN: c_variant_enter(cv, "{"); c_variant_varg_enter_unbound(&varg, cv, '}'); g_variant_iter_init(&gvi[nest], g); gvig[nest] = g_variant_ref(g); ++nest; break; case C_VARIANT_INT64: c_variant_read(cv, "x", &val_64); assert((int64_t)val_64 == g_variant_get_int64(g)); break; case C_VARIANT_UINT64: c_variant_read(cv, "t", &val_64); assert((uint64_t)val_64 == g_variant_get_uint64(g)); break; case C_VARIANT_DOUBLE: c_variant_read(cv, "d", &val_f); assert(!(val_f > g_variant_get_double(g)) && !(val_f < g_variant_get_double(g))); break; case C_VARIANT_INT32: c_variant_read(cv, "i", &val_32); assert((int32_t)val_32 == g_variant_get_int32(g)); break; case C_VARIANT_UINT32: c_variant_read(cv, "u", &val_32); assert((uint32_t)val_32 == g_variant_get_uint32(g)); break; case C_VARIANT_HANDLE: c_variant_read(cv, "h", &val_32); assert((int32_t)val_32 == g_variant_get_handle(g)); break; case C_VARIANT_INT16: c_variant_read(cv, "n", &val_16); assert((int16_t)val_16 == g_variant_get_int16(g)); break; case C_VARIANT_UINT16: c_variant_read(cv, "q", &val_16); assert((uint16_t)val_16 == g_variant_get_uint16(g)); break; case C_VARIANT_BOOL: c_variant_read(cv, "b", &val_8); assert((bool)val_8 == g_variant_get_boolean(g)); break; case C_VARIANT_BYTE: c_variant_read(cv, "y", &val_8); assert((guchar)val_8 == g_variant_get_byte(g)); break; case C_VARIANT_STRING: c_variant_read(cv, "s", &s); assert(!strcmp(s, g_variant_get_string(g, NULL))); break; case C_VARIANT_PATH: c_variant_read(cv, "o", &s); assert(!strcmp(s, g_variant_get_string(g, NULL))); break; case C_VARIANT_SIGNATURE: c_variant_read(cv, "g", &s); assert(!strcmp(s, g_variant_get_string(g, NULL))); break; default: assert(0); break; } r = c_variant_return_poison(cv); assert(r >= 0); g_variant_unref(g); } }
static gchar * gvariant_simple_to_string (GVariant *variant) { GVariantClass class; gchar *str; class = g_variant_classify (variant); switch (class) { case G_VARIANT_CLASS_BOOLEAN: if (g_variant_get_boolean (variant)) str = g_strdup ("true"); else str = g_strdup ("false"); break; case G_VARIANT_CLASS_BYTE: str = g_strdup_printf ("%u", g_variant_get_byte (variant)); break; case G_VARIANT_CLASS_INT16: str = g_strdup_printf ("%d", g_variant_get_int16 (variant)); break; case G_VARIANT_CLASS_UINT16: str = g_strdup_printf ("%u", g_variant_get_uint16 (variant)); break; case G_VARIANT_CLASS_INT32: str = g_strdup_printf ("%d", g_variant_get_int32 (variant)); break; case G_VARIANT_CLASS_UINT32: str = g_strdup_printf ("%u", g_variant_get_uint32 (variant)); break; case G_VARIANT_CLASS_INT64: str = g_strdup_printf ("%" G_GINT64_FORMAT, g_variant_get_int64 (variant)); break; case G_VARIANT_CLASS_UINT64: str = g_strdup_printf ("%" G_GUINT64_FORMAT, g_variant_get_uint64 (variant)); break; case G_VARIANT_CLASS_HANDLE: str = g_strdup_printf ("%d", g_variant_get_handle (variant)); break; case G_VARIANT_CLASS_DOUBLE: { gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", g_variant_get_double (variant)); str = g_strdup (buf); break; } case G_VARIANT_CLASS_STRING: case G_VARIANT_CLASS_OBJECT_PATH: case G_VARIANT_CLASS_SIGNATURE: str = g_strdup (g_variant_get_string (variant, NULL)); break; default: g_assert_not_reached (); break; } return str; }
static void build_json (JsonBuilder *builder, GVariant *value) { const GVariantType *type; const GVariantType *element_type; g_variant_ref_sink (value); switch (g_variant_classify (value)) { case G_VARIANT_CLASS_BOOLEAN: json_builder_add_boolean_value (builder, g_variant_get_boolean (value)); break; case G_VARIANT_CLASS_BYTE: json_builder_add_int_value (builder, g_variant_get_byte (value)); break; case G_VARIANT_CLASS_INT16: json_builder_add_int_value (builder, g_variant_get_int16 (value)); break; case G_VARIANT_CLASS_UINT16: json_builder_add_int_value (builder, g_variant_get_uint16 (value)); break; case G_VARIANT_CLASS_INT32: json_builder_add_int_value (builder, g_variant_get_int32 (value)); break; case G_VARIANT_CLASS_UINT32: json_builder_add_int_value (builder, g_variant_get_uint32 (value)); break; case G_VARIANT_CLASS_INT64: json_builder_add_int_value (builder, g_variant_get_int64 (value)); break; case G_VARIANT_CLASS_UINT64: json_builder_add_int_value (builder, g_variant_get_uint64 (value)); break; case G_VARIANT_CLASS_HANDLE: json_builder_add_int_value (builder, g_variant_get_handle (value)); break; case G_VARIANT_CLASS_DOUBLE: json_builder_add_double_value (builder, g_variant_get_double (value)); break; case G_VARIANT_CLASS_STRING: /* explicit fall-through */ case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */ case G_VARIANT_CLASS_SIGNATURE: { /* HACK: We can't use json_builder_add_string_value here since it turns empty strings into 'null' values inside arrays. https://bugzilla.gnome.org/show_bug.cgi?id=730803 */ JsonNode *string_element = json_node_alloc (); json_node_init_string (string_element, g_variant_get_string (value, NULL)); json_builder_add_value (builder, string_element); } break; case G_VARIANT_CLASS_VARIANT: build_json_variant (builder, value); break; case G_VARIANT_CLASS_ARRAY: type = g_variant_get_type (value); element_type = g_variant_type_element (type); if (g_variant_type_is_dict_entry (element_type)) build_json_dictionary (builder, element_type, value); else build_json_array_or_tuple (builder, value); break; case G_VARIANT_CLASS_TUPLE: build_json_array_or_tuple (builder, value); break; case G_VARIANT_CLASS_DICT_ENTRY: case G_VARIANT_CLASS_MAYBE: default: g_return_if_reached (); break; } g_variant_unref (value); }