/*
* dbus.c - Source for D-Bus utilities
*
* Copyright (C) 2005-2008 Collabora Ltd.
* Copyright (C) 2005-2008 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* SECTION:dbus
* @title: D-Bus utilities
* @short_description: some D-Bus utility functions
*
* D-Bus utility functions used in telepathy-glib.
*/
/**
* SECTION:asv
* @title: Manipulating a{sv} mappings
* @short_description: Functions to manipulate mappings from string to
* variant, as represented in dbus-glib by a #GHashTable from string
* to #GValue
*
* Mappings from string to variant (D-Bus signature a{sv}) are commonly used
* to provide extensibility, but in dbus-glib they're somewhat awkward to deal
* with.
*
* These functions provide convenient access to the values in such
* a mapping.
*
* They also work around the fact that none of the #GHashTable public API
* takes a const pointer to a #GHashTable, even the read-only methods that
* logically ought to.
*
* Parts of telepathy-glib return const pointers to #GHashTable, to encourage
* the use of this API.
*
* Since: 0.7.9
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEBUG_FLAG TP_DEBUG_MISC
#include "debug-internal.h"
/**
* tp_asv_size: (skip)
* @asv: a GHashTable
*
* Return the size of @asv as if via g_hash_table_size().
*
* The only difference is that this version takes a const #GHashTable and
* casts it.
*
* Since: 0.7.12
*/
/* (#define + static inline in dbus.h) */
/**
* tp_dbus_g_method_return_not_implemented: (skip)
* @context: The D-Bus method invocation context
*
* Return the Telepathy error NotImplemented from the method invocation
* given by @context.
*/
void
tp_dbus_g_method_return_not_implemented (DBusGMethodInvocation *context)
{
GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Not implemented" };
dbus_g_method_return_error (context, &e);
}
DBusGConnection *
_tp_dbus_starter_bus_conn (GError **error)
{
static DBusGConnection *starter_bus = NULL;
if (starter_bus == NULL)
{
starter_bus = dbus_g_bus_get (DBUS_BUS_STARTER, error);
}
return starter_bus;
}
/**
* tp_get_bus: (skip)
*
* Returns a connection to the D-Bus daemon on which this process was
* activated if it was launched by D-Bus service activation, or the session
* bus otherwise.
*
* If dbus_g_bus_get() fails, exit with error code 1.
*
* Note that this function is not suitable for use in applications which can
* be useful even in the absence of D-Bus - it is designed for use in
* connection managers, which are not at all useful without a D-Bus
* connection. See <https://bugs.freedesktop.org/show_bug.cgi?id=18832>.
* Most processes should use tp_dbus_daemon_dup() instead.
*
* Returns: a connection to the starter or session D-Bus daemon.
*/
DBusGConnection *
tp_get_bus (void)
{
GError *error = NULL;
DBusGConnection *bus = _tp_dbus_starter_bus_conn (&error);
if (bus == NULL)
{
WARNING ("Failed to connect to starter bus: %s", error->message);
exit (1);
}
return bus;
}
/**
* tp_get_bus_proxy: (skip)
*
* Return a #DBusGProxy for the bus daemon object. The same caveats as for
* tp_get_bus() apply.
*
* Returns: a proxy for the bus daemon object on the starter or session bus.
*
* Deprecated: 0.7.26: Use tp_dbus_daemon_dup() in new code.
*/
DBusGProxy *
tp_get_bus_proxy (void)
{
static DBusGProxy *bus_proxy = NULL;
if (bus_proxy == NULL)
{
GError *error = NULL;
DBusGConnection *bus = _tp_dbus_starter_bus_conn (&error);
if (bus == NULL)
{
WARNING ("Failed to connect to starter bus: %s", error->message);
exit (1);
}
bus_proxy = dbus_g_proxy_new_for_name (bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus");
if (bus_proxy == NULL)
ERROR ("Failed to get proxy object for bus.");
}
return bus_proxy;
}
/**
* TpDBusNameType:
* @TP_DBUS_NAME_TYPE_UNIQUE: accept unique names like :1.123
* (not including the name of the bus daemon itself)
* @TP_DBUS_NAME_TYPE_WELL_KNOWN: accept well-known names like
* com.example.Service (not including the name of the bus daemon itself)
* @TP_DBUS_NAME_TYPE_BUS_DAEMON: accept the name of the bus daemon
* itself, which has the syntax of a well-known name, but behaves like a
* unique name
* @TP_DBUS_NAME_TYPE_NOT_BUS_DAEMON: accept either unique or well-known
* names, but not the bus daemon
* @TP_DBUS_NAME_TYPE_ANY: accept any of the above
*
* A set of flags indicating which D-Bus bus names are acceptable.
* They can be combined with the bitwise-or operator to accept multiple
* types. %TP_DBUS_NAME_TYPE_NOT_BUS_DAEMON and %TP_DBUS_NAME_TYPE_ANY are
* the bitwise-or of other appropriate types, for convenience.
*
* Since 0.11.5, there is a corresponding #GFlagsClass type,
* %TP_TYPE_DBUS_NAME_TYPE.
*
* Since: 0.7.1
*/
/**
* TP_TYPE_DBUS_NAME_TYPE:
*
* The #GFlagsClass type of a #TpDBusNameType or a set of name types.
*
* Since: 0.11.5
*/
/**
* tp_dbus_check_valid_bus_name:
* @name: a possible bus name
* @allow_types: some combination of %TP_DBUS_NAME_TYPE_UNIQUE,
* %TP_DBUS_NAME_TYPE_WELL_KNOWN or %TP_DBUS_NAME_TYPE_BUS_DAEMON
* (often this will be %TP_DBUS_NAME_TYPE_NOT_BUS_DAEMON or
* %TP_DBUS_NAME_TYPE_ANY)
* @error: used to raise %TP_DBUS_ERROR_INVALID_BUS_NAME if %FALSE is returned
*
* Check that the given string is a valid D-Bus bus name of an appropriate
* type.
*
* Returns: %TRUE if @name is valid
*
* Since: 0.7.1
*/
gboolean
tp_dbus_check_valid_bus_name (const gchar *name,
TpDBusNameType allow_types,
GError **error)
{
gboolean dot = FALSE;
gboolean unique;
gchar last;
const gchar *ptr;
g_return_val_if_fail (name != NULL, FALSE);
if (name[0] == '\0')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"The empty string is not a valid bus name");
return FALSE;
}
if (!tp_strdiff (name, DBUS_SERVICE_DBUS))
{
if (allow_types & TP_DBUS_NAME_TYPE_BUS_DAEMON)
return TRUE;
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"The D-Bus daemon's bus name is not acceptable here");
return FALSE;
}
unique = (name[0] == ':');
if (unique && (allow_types & TP_DBUS_NAME_TYPE_UNIQUE) == 0)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"A well-known bus name not starting with ':'%s is required",
allow_types & TP_DBUS_NAME_TYPE_BUS_DAEMON
? " (or the bus daemon itself)"
: "");
return FALSE;
}
if (!unique && (allow_types & TP_DBUS_NAME_TYPE_WELL_KNOWN) == 0)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"A unique bus name starting with ':'%s is required",
allow_types & TP_DBUS_NAME_TYPE_BUS_DAEMON
? " (or the bus daemon itself)"
: "");
return FALSE;
}
if (strlen (name) > 255)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name: too long (> 255 characters)");
return FALSE;
}
last = '\0';
for (ptr = name + (unique ? 1 : 0); *ptr != '\0'; ptr++)
{
if (*ptr == '.')
{
dot = TRUE;
if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': contains '..'", name);
return FALSE;
}
else if (last == '\0')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': must not start with '.'", name);
return FALSE;
}
}
else if (g_ascii_isdigit (*ptr))
{
if (!unique)
{
if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': a digit may not follow '.' "
"except in a unique name starting with ':'", name);
return FALSE;
}
else if (last == '\0')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': must not start with a digit",
name);
return FALSE;
}
}
}
else if (!g_ascii_isalpha (*ptr) && *ptr != '_' && *ptr != '-')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': contains invalid character '%c'",
name, *ptr);
return FALSE;
}
last = *ptr;
}
if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': must not end with '.'", name);
return FALSE;
}
if (!dot)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_BUS_NAME,
"Invalid bus name '%s': must contain '.'", name);
return FALSE;
}
return TRUE;
}
/**
* tp_dbus_check_valid_interface_name:
* @name: a possible interface name
* @error: used to raise %TP_DBUS_ERROR_INVALID_INTERFACE_NAME if %FALSE is
* returned
*
* Check that the given string is a valid D-Bus interface name. This is
* also appropriate to use to check for valid error names.
*
* Since GIO 2.26, g_dbus_is_interface_name() should always return the same
* thing, although the GLib function does not raise an error explaining why
* the interface name is incorrect.
*
* Returns: %TRUE if @name is valid
*
* Since: 0.7.1
*/
gboolean
tp_dbus_check_valid_interface_name (const gchar *name,
GError **error)
{
gboolean dot = FALSE;
gchar last;
const gchar *ptr;
g_return_val_if_fail (name != NULL, FALSE);
if (name[0] == '\0')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"The empty string is not a valid interface name");
return FALSE;
}
if (strlen (name) > 255)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name: too long (> 255 characters)");
return FALSE;
}
last = '\0';
for (ptr = name; *ptr != '\0'; ptr++)
{
if (*ptr == '.')
{
dot = TRUE;
if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': contains '..'", name);
return FALSE;
}
else if (last == '\0')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': must not start with '.'",
name);
return FALSE;
}
}
else if (g_ascii_isdigit (*ptr))
{
if (last == '\0')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': must not start with a digit",
name);
return FALSE;
}
else if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': a digit must not follow '.'",
name);
return FALSE;
}
}
else if (!g_ascii_isalpha (*ptr) && *ptr != '_')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': contains invalid character '%c'",
name, *ptr);
return FALSE;
}
last = *ptr;
}
if (last == '.')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': must not end with '.'", name);
return FALSE;
}
if (!dot)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_INTERFACE_NAME,
"Invalid interface name '%s': must contain '.'", name);
return FALSE;
}
return TRUE;
}
/**
* tp_dbus_check_valid_member_name:
* @name: a possible member name
* @error: used to raise %TP_DBUS_ERROR_INVALID_MEMBER_NAME if %FALSE is
* returned
*
* Check that the given string is a valid D-Bus member (method or signal) name.
*
* Since GIO 2.26, g_dbus_is_member_name() should always return the same
* thing, although the GLib function does not raise an error explaining why
* the interface name is incorrect.
*
* Returns: %TRUE if @name is valid
*
* Since: 0.7.1
*/
gboolean
tp_dbus_check_valid_member_name (const gchar *name,
GError **error)
{
const gchar *ptr;
g_return_val_if_fail (name != NULL, FALSE);
if (name[0] == '\0')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_MEMBER_NAME,
"The empty string is not a valid method or signal name");
return FALSE;
}
if (strlen (name) > 255)
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_MEMBER_NAME,
"Invalid method or signal name: too long (> 255 characters)");
return FALSE;
}
for (ptr = name; *ptr != '\0'; ptr++)
{
if (g_ascii_isdigit (*ptr))
{
if (ptr == name)
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_MEMBER_NAME,
"Invalid method or signal name '%s': must not start with "
"a digit", name);
return FALSE;
}
}
else if (!g_ascii_isalpha (*ptr) && *ptr != '_')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_MEMBER_NAME,
"Invalid method or signal name '%s': contains invalid "
"character '%c'",
name, *ptr);
return FALSE;
}
}
return TRUE;
}
/**
* tp_dbus_check_valid_object_path:
* @path: a possible object path
* @error: used to raise %TP_DBUS_ERROR_INVALID_OBJECT_PATH if %FALSE is
* returned
*
* Check that the given string is a valid D-Bus object path. Since GLib 2.24,
* g_variant_is_object_path() should always return the same thing as this
* function, although it doesn't provide an error explaining why the object
* path is invalid.
*
* Returns: %TRUE if @path is valid
*
* Since: 0.7.1
*/
gboolean
tp_dbus_check_valid_object_path (const gchar *path, GError **error)
{
const gchar *ptr;
g_return_val_if_fail (path != NULL, FALSE);
if (path[0] != '/')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_OBJECT_PATH,
"Invalid object path '%s': must start with '/'",
path);
return FALSE;
}
if (path[1] == '\0')
return TRUE;
for (ptr = path + 1; *ptr != '\0'; ptr++)
{
if (*ptr == '/')
{
if (ptr[-1] == '/')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_OBJECT_PATH,
"Invalid object path '%s': contains '//'", path);
return FALSE;
}
}
else if (!g_ascii_isalnum (*ptr) && *ptr != '_')
{
g_set_error (error, TP_DBUS_ERRORS,
TP_DBUS_ERROR_INVALID_OBJECT_PATH,
"Invalid object path '%s': contains invalid character '%c'",
path, *ptr);
return FALSE;
}
}
if (ptr[-1] == '/')
{
g_set_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_OBJECT_PATH,
"Invalid object path '%s': is not '/' but does end with '/'",
path);
return FALSE;
}
return TRUE;
}
/**
* tp_g_value_slice_new_bytes: (skip)
* @length: number of bytes to copy
* @bytes: location of an array of bytes to be copied (this may be %NULL
* if and only if length is 0)
*
* Slice-allocate a #GValue containing a byte-array, using
* tp_g_value_slice_new_boxed(). This function is convenient to use when
* constructing hash tables from string to #GValue, for example.
*
* Returns: a #GValue of type %DBUS_TYPE_G_UCHAR_ARRAY whose value is a copy
* of @length bytes from @bytes, to be freed with tp_g_value_slice_free() or
* g_slice_free()
*
* Since: 0.7.27
*/
GValue *
tp_g_value_slice_new_bytes (guint length,
gconstpointer bytes)
{
GArray *arr;
g_return_val_if_fail (length == 0 || bytes != NULL, NULL);
arr = g_array_sized_new (FALSE, FALSE, 1, length);
if (length > 0)
g_array_append_vals (arr, bytes, length);
return tp_g_value_slice_new_take_boxed (DBUS_TYPE_G_UCHAR_ARRAY, arr);
}
/**
* tp_g_value_slice_new_take_bytes: (skip)
* @bytes: a non-NULL #GArray of guchar, ownership of which will be taken by
* the #GValue
*
* Slice-allocate a #GValue containing @bytes, using
* tp_g_value_slice_new_boxed(). This function is convenient to use when
* constructing hash tables from string to #GValue, for example.
*
* Returns: a #GValue of type %DBUS_TYPE_G_UCHAR_ARRAY whose value is
* @bytes, to be freed with tp_g_value_slice_free() or
* g_slice_free()
*
* Since: 0.7.27
*/
GValue *
tp_g_value_slice_new_take_bytes (GArray *bytes)
{
g_return_val_if_fail (bytes != NULL, NULL);
return tp_g_value_slice_new_take_boxed (DBUS_TYPE_G_UCHAR_ARRAY, bytes);
}
/**
* tp_g_value_slice_new_object_path: (skip)
* @path: a valid D-Bus object path which will be copied
*
* Slice-allocate a #GValue containing an object path, using
* tp_g_value_slice_new_boxed(). This function is convenient to use when
* constructing hash tables from string to #GValue, for example.
*
* Returns: a #GValue of type %DBUS_TYPE_G_OBJECT_PATH whose value is a copy
* of @path, to be freed with tp_g_value_slice_free() or g_slice_free()
*
* Since: 0.7.27
*/
GValue *
tp_g_value_slice_new_object_path (const gchar *path)
{
g_return_val_if_fail (tp_dbus_check_valid_object_path (path, NULL), NULL);
return tp_g_value_slice_new_boxed (DBUS_TYPE_G_OBJECT_PATH, path);
}
/**
* tp_g_value_slice_new_static_object_path: (skip)
* @path: a valid D-Bus object path which must remain valid forever
*
* Slice-allocate a #GValue containing an object path, using
* tp_g_value_slice_new_static_boxed(). This function is convenient to use when
* constructing hash tables from string to #GValue, for example.
*
* Returns: a #GValue of type %DBUS_TYPE_G_OBJECT_PATH whose value is @path,
* to be freed with tp_g_value_slice_free() or g_slice_free()
*
* Since: 0.7.27
*/
GValue *
tp_g_value_slice_new_static_object_path (const gchar *path)
{
g_return_val_if_fail (tp_dbus_check_valid_object_path (path, NULL), NULL);
return tp_g_value_slice_new_static_boxed (DBUS_TYPE_G_OBJECT_PATH, path);
}
/**
* tp_g_value_slice_new_take_object_path: (skip)
* @path: a valid D-Bus object path which will be freed with g_free() by the
* returned #GValue (the caller must own it before calling this function, but
* no longer owns it after this function returns)
*
* Slice-allocate a #GValue containing an object path, using
* tp_g_value_slice_new_take_boxed(). This function is convenient to use when
* constructing hash tables from string to #GValue, for example.
*
* Returns: a #GValue of type %DBUS_TYPE_G_OBJECT_PATH whose value is @path,
* to be freed with tp_g_value_slice_free() or g_slice_free()
*
* Since: 0.7.27
*/
GValue *
tp_g_value_slice_new_take_object_path (gchar *path)
{
g_return_val_if_fail (tp_dbus_check_valid_object_path (path, NULL), NULL);
return tp_g_value_slice_new_take_boxed (DBUS_TYPE_G_OBJECT_PATH, path);
}
/**
* tp_asv_new: (skip)
* @first_key: the name of the first key (or NULL)
* @...: type and value for the first key, followed by a NULL-terminated list
* of (key, type, value) tuples
*
* Creates a new #GHashTable for use with a{sv} maps, containing the values
* passed in as parameters.
*
* The #GHashTable is synonymous with:
*
* GHashTable *asv = g_hash_table_new_full (g_str_hash, g_str_equal,
* NULL, (GDestroyNotify) tp_g_value_slice_free);
*
* Followed by manual insertion of each of the parameters.
*
* Parameters are stored in slice-allocated GValues and should be set using
* tp_asv_set_*() and retrieved using tp_asv_get_*().
*
* tp_g_value_slice_new() and tp_g_value_slice_dup() may also be used to insert
* into the map if required.
*
* g_hash_table_insert (parameters, "account",
* tp_g_value_slice_new_string ("bob@mcbadgers.com"));
*
*
*
* Using tp_asv_new()
*
* GHashTable *parameters = tp_asv_new (
* "answer", G_TYPE_INT, 42,
* "question", G_TYPE_STRING, "We just don't know",
* NULL);
*
*
* Allocated values will be automatically free'd when overwritten, removed or
* the hash table destroyed with g_hash_table_unref().
*
* Returns: a newly created #GHashTable for storing a{sv} maps, free with
* g_hash_table_unref().
* Since: 0.7.29
*/
GHashTable *
tp_asv_new (const gchar *first_key, ...)
{
va_list var_args;
char *key;
GType type;
GValue *value;
char *error = NULL; /* NB: not a GError! */
/* create a GHashTable */
GHashTable *asv = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) tp_g_value_slice_free);
va_start (var_args, first_key);
for (key = (char *) first_key; key != NULL; key = va_arg (var_args, char *))
{
type = va_arg (var_args, GType);
value = tp_g_value_slice_new (type);
G_VALUE_COLLECT (value, var_args, 0, &error);
if (error != NULL)
{
CRITICAL ("key %s: %s", key, error);
g_free (error);
error = NULL;
tp_g_value_slice_free (value);
continue;
}
g_hash_table_insert (asv, key, value);
}
va_end (var_args);
return asv;
}
/**
* tp_asv_get_boolean:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location to store %TRUE if the key actually
* exists and has a boolean value
*
* If a value for @key in @asv is present and boolean, return it,
* and set *@valid to %TRUE if @valid is not %NULL.
*
* Otherwise return %FALSE, and set *@valid to %FALSE if @valid is not %NULL.
*
* Returns: a boolean value for @key
* Since: 0.7.9
*/
gboolean
tp_asv_get_boolean (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
GValue *value;
g_return_val_if_fail (asv != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS_BOOLEAN (value))
{
if (valid != NULL)
*valid = FALSE;
return FALSE;
}
if (valid != NULL)
*valid = TRUE;
return g_value_get_boolean (value);
}
/**
* tp_asv_set_boolean: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_boolean(), tp_g_value_slice_new_boolean()
* Since: 0.7.29
*/
void
tp_asv_set_boolean (GHashTable *asv,
const gchar *key,
gboolean value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_boolean (value));
}
/**
* tp_asv_get_bytes:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
*
* If a value for @key in @asv is present and is an array of bytes
* (its GType is %DBUS_TYPE_G_UCHAR_ARRAY), return it.
*
* Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it with
* g_boxed_copy (DBUS_TYPE_G_UCHAR_ARRAY, ...) if you need to keep
* it for longer.
*
* Returns: (transfer none) (allow-none) (element-type guint8): the string value
* of @key, or %NULL
* Since: 0.7.9
*/
const GArray *
tp_asv_get_bytes (const GHashTable *asv,
const gchar *key)
{
GValue *value;
g_return_val_if_fail (asv != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY))
return NULL;
return g_value_get_boxed (value);
}
/**
* tp_asv_set_bytes: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @length: the number of bytes to copy
* @bytes: location of an array of bytes to be copied (this may be %NULL
* if and only if length is 0)
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_bytes(), tp_g_value_slice_new_bytes()
* Since: 0.7.29
*/
void
tp_asv_set_bytes (GHashTable *asv,
const gchar *key,
guint length,
gconstpointer bytes)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (!(length > 0 && bytes == NULL));
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_bytes (length, bytes));
}
/**
* tp_asv_take_bytes: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: a non-NULL #GArray of %guchar, ownership of which will be taken by
* the #GValue
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_bytes(), tp_g_value_slice_new_take_bytes()
* Since: 0.7.29
*/
void
tp_asv_take_bytes (GHashTable *asv,
const gchar *key,
GArray *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_take_bytes (value));
}
/**
* tp_asv_get_string:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
*
* If a value for @key in @asv is present and is a string, return it.
*
* Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it with g_strdup() if you
* need to keep it for longer.
*
* Returns: (transfer none) (allow-none): the string value of @key, or %NULL
* Since: 0.7.9
*/
const gchar *
tp_asv_get_string (const GHashTable *asv,
const gchar *key)
{
GValue *value;
g_return_val_if_fail (asv != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS_STRING (value))
return NULL;
return g_value_get_string (value);
}
/**
* tp_asv_set_string: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_string(), tp_g_value_slice_new_string()
* Since: 0.7.29
*/
void
tp_asv_set_string (GHashTable *asv,
const gchar *key,
const gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_string (value));
}
/**
* tp_asv_take_string: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_string(),
* tp_g_value_slice_new_take_string()
* Since: 0.7.29
*/
void
tp_asv_take_string (GHashTable *asv,
const gchar *key,
gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_take_string (value));
}
/**
* tp_asv_set_static_string: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_string(),
* tp_g_value_slice_new_static_string()
* Since: 0.7.29
*/
void
tp_asv_set_static_string (GHashTable *asv,
const gchar *key,
const gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_static_string (value));
}
/**
* tp_asv_get_int32:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location in which to store %TRUE on success
* or %FALSE on failure
*
* If a value for @key in @asv is present, has an integer type used by
* dbus-glib (guchar, gint, guint, gint64 or guint64) and fits in the
* range of a gint32, return it, and if @valid is not %NULL, set *@valid to
* %TRUE.
*
* Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
*
* Returns: the 32-bit signed integer value of @key, or 0
* Since: 0.7.9
*/
gint32
tp_asv_get_int32 (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
gint64 i;
guint64 u;
gint32 ret;
GValue *value;
g_return_val_if_fail (asv != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL)
goto return_invalid;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_UCHAR:
ret = g_value_get_uchar (value);
break;
case G_TYPE_UINT:
u = g_value_get_uint (value);
if (G_UNLIKELY (u > G_MAXINT32))
goto return_invalid;
ret = u;
break;
case G_TYPE_INT:
ret = g_value_get_int (value);
break;
case G_TYPE_INT64:
i = g_value_get_int64 (value);
if (G_UNLIKELY (i < G_MININT32 || i > G_MAXINT32))
goto return_invalid;
ret = i;
break;
case G_TYPE_UINT64:
u = g_value_get_uint64 (value);
if (G_UNLIKELY (u > G_MAXINT32))
goto return_invalid;
ret = u;
break;
default:
goto return_invalid;
}
if (valid != NULL)
*valid = TRUE;
return ret;
return_invalid:
if (valid != NULL)
*valid = FALSE;
return 0;
}
/**
* tp_asv_set_int32: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_int32(), tp_g_value_slice_new_int()
* Since: 0.7.29
*/
void
tp_asv_set_int32 (GHashTable *asv,
const gchar *key,
gint32 value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_int (value));
}
/**
* tp_asv_get_uint32:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location in which to store %TRUE on success
* or %FALSE on failure
*
* If a value for @key in @asv is present, has an integer type used by
* dbus-glib (guchar, gint, guint, gint64 or guint64) and fits in the
* range of a guint32, return it, and if @valid is not %NULL, set *@valid to
* %TRUE.
*
* Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
*
* Returns: the 32-bit unsigned integer value of @key, or 0
* Since: 0.7.9
*/
guint32
tp_asv_get_uint32 (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
gint64 i;
guint64 u;
guint32 ret;
GValue *value;
g_return_val_if_fail (asv != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL)
goto return_invalid;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_UCHAR:
ret = g_value_get_uchar (value);
break;
case G_TYPE_UINT:
ret = g_value_get_uint (value);
break;
case G_TYPE_INT:
i = g_value_get_int (value);
if (G_UNLIKELY (i < 0))
goto return_invalid;
ret = i;
break;
case G_TYPE_INT64:
i = g_value_get_int64 (value);
if (G_UNLIKELY (i < 0 || i > G_MAXUINT32))
goto return_invalid;
ret = i;
break;
case G_TYPE_UINT64:
u = g_value_get_uint64 (value);
if (G_UNLIKELY (u > G_MAXUINT32))
goto return_invalid;
ret = u;
break;
default:
goto return_invalid;
}
if (valid != NULL)
*valid = TRUE;
return ret;
return_invalid:
if (valid != NULL)
*valid = FALSE;
return 0;
}
/**
* tp_asv_set_uint32: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_uint32(), tp_g_value_slice_new_uint()
* Since: 0.7.29
*/
void
tp_asv_set_uint32 (GHashTable *asv,
const gchar *key,
guint32 value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_uint (value));
}
/**
* tp_asv_get_int64:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location in which to store %TRUE on success
* or %FALSE on failure
*
* If a value for @key in @asv is present, has an integer type used by
* dbus-glib (guchar, gint, guint, gint64 or guint64) and fits in the
* range of a gint64, return it, and if @valid is not %NULL, set *@valid to
* %TRUE.
*
* Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
*
* Returns: the 64-bit signed integer value of @key, or 0
* Since: 0.7.9
*/
gint64
tp_asv_get_int64 (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
gint64 ret;
guint64 u;
GValue *value;
g_return_val_if_fail (asv != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL)
goto return_invalid;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_UCHAR:
ret = g_value_get_uchar (value);
break;
case G_TYPE_UINT:
ret = g_value_get_uint (value);
break;
case G_TYPE_INT:
ret = g_value_get_int (value);
break;
case G_TYPE_INT64:
ret = g_value_get_int64 (value);
break;
case G_TYPE_UINT64:
u = g_value_get_uint64 (value);
if (G_UNLIKELY (u > G_MAXINT64))
goto return_invalid;
ret = u;
break;
default:
goto return_invalid;
}
if (valid != NULL)
*valid = TRUE;
return ret;
return_invalid:
if (valid != NULL)
*valid = FALSE;
return 0;
}
/**
* tp_asv_set_int64: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_int64(), tp_g_value_slice_new_int64()
* Since: 0.7.29
*/
void
tp_asv_set_int64 (GHashTable *asv,
const gchar *key,
gint64 value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_int64 (value));
}
/**
* tp_asv_get_uint64:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location in which to store %TRUE on success
* or %FALSE on failure
*
* If a value for @key in @asv is present, has an integer type used by
* dbus-glib (guchar, gint, guint, gint64 or guint64) and is non-negative,
* return it, and if @valid is not %NULL, set *@valid to %TRUE.
*
* Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
*
* Returns: the 64-bit unsigned integer value of @key, or 0
* Since: 0.7.9
*/
guint64
tp_asv_get_uint64 (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
gint64 tmp;
guint64 ret;
GValue *value;
g_return_val_if_fail (asv != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL)
goto return_invalid;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_UCHAR:
ret = g_value_get_uchar (value);
break;
case G_TYPE_UINT:
ret = g_value_get_uint (value);
break;
case G_TYPE_INT:
tmp = g_value_get_int (value);
if (G_UNLIKELY (tmp < 0))
goto return_invalid;
ret = tmp;
break;
case G_TYPE_INT64:
tmp = g_value_get_int64 (value);
if (G_UNLIKELY (tmp < 0))
goto return_invalid;
ret = tmp;
break;
case G_TYPE_UINT64:
ret = g_value_get_uint64 (value);
break;
default:
goto return_invalid;
}
if (valid != NULL)
*valid = TRUE;
return ret;
return_invalid:
if (valid != NULL)
*valid = FALSE;
return 0;
}
/**
* tp_asv_set_uint64: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_uint64(), tp_g_value_slice_new_uint64()
* Since: 0.7.29
*/
void
tp_asv_set_uint64 (GHashTable *asv,
const gchar *key,
guint64 value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_uint64 (value));
}
/**
* tp_asv_get_double:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @valid: (out): Either %NULL, or a location in which to store %TRUE on success
* or %FALSE on failure
*
* If a value for @key in @asv is present and has any numeric type used by
* dbus-glib (guchar, gint, guint, gint64, guint64 or gdouble),
* return it as a double, and if @valid is not %NULL, set *@valid to %TRUE.
*
* Otherwise, return 0.0, and if @valid is not %NULL, set *@valid to %FALSE.
*
* Returns: the double precision floating-point value of @key, or 0.0
* Since: 0.7.9
*/
gdouble
tp_asv_get_double (const GHashTable *asv,
const gchar *key,
gboolean *valid)
{
gdouble ret;
GValue *value;
g_return_val_if_fail (asv != NULL, 0.0);
g_return_val_if_fail (key != NULL, 0.0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL)
goto return_invalid;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_DOUBLE:
ret = g_value_get_double (value);
break;
case G_TYPE_UCHAR:
ret = g_value_get_uchar (value);
break;
case G_TYPE_UINT:
ret = g_value_get_uint (value);
break;
case G_TYPE_INT:
ret = g_value_get_int (value);
break;
case G_TYPE_INT64:
ret = g_value_get_int64 (value);
break;
case G_TYPE_UINT64:
ret = g_value_get_uint64 (value);
break;
default:
goto return_invalid;
}
if (valid != NULL)
*valid = TRUE;
return ret;
return_invalid:
if (valid != NULL)
*valid = FALSE;
return 0;
}
/**
* tp_asv_set_double: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_double(), tp_g_value_slice_new_double()
* Since: 0.7.29
*/
void
tp_asv_set_double (GHashTable *asv,
const gchar *key,
gdouble value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key, tp_g_value_slice_new_double (value));
}
/**
* tp_asv_get_object_path:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
*
* If a value for @key in @asv is present and is an object path, return it.
*
* Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it with g_strdup() if you
* need to keep it for longer.
*
* Returns: (transfer none) (allow-none): the object-path value of @key, or
* %NULL
* Since: 0.7.9
*/
const gchar *
tp_asv_get_object_path (const GHashTable *asv,
const gchar *key)
{
GValue *value;
g_return_val_if_fail (asv != NULL, 0);
g_return_val_if_fail (key != NULL, 0);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
return NULL;
return g_value_get_boxed (value);
}
/**
* tp_asv_set_object_path: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_object_path(),
* tp_g_value_slice_new_object_path()
* Since: 0.7.29
*/
void
tp_asv_set_object_path (GHashTable *asv,
const gchar *key,
const gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_object_path (value));
}
/**
* tp_asv_take_object_path: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_object_path(),
* tp_g_value_slice_new_take_object_path()
* Since: 0.7.29
*/
void
tp_asv_take_object_path (GHashTable *asv,
const gchar *key,
gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_take_object_path (value));
}
/**
* tp_asv_set_static_object_path: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_object_path(),
* tp_g_value_slice_new_static_object_path()
* Since: 0.7.29
*/
void
tp_asv_set_static_object_path (GHashTable *asv,
const gchar *key,
const gchar *value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_static_object_path (value));
}
/**
* tp_asv_get_boxed:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
* @type: The type that the key's value should have, which must be derived
* from %G_TYPE_BOXED
*
* If a value for @key in @asv is present and is of the desired type,
* return it.
*
* Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it, for instance with
* g_boxed_copy(), if you need to keep it for longer.
*
* Returns: (transfer none) (allow-none): the value of @key, or %NULL
* Since: 0.7.9
*/
gpointer
tp_asv_get_boxed (const GHashTable *asv,
const gchar *key,
GType type)
{
GValue *value;
g_return_val_if_fail (asv != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS (value, type))
return NULL;
return g_value_get_boxed (value);
}
/**
* tp_asv_set_boxed: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @type: the type of the key's value, which must be derived from %G_TYPE_BOXED
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_boxed(), tp_g_value_slice_new_boxed()
* Since: 0.7.29
*/
void
tp_asv_set_boxed (GHashTable *asv,
const gchar *key,
GType type,
gconstpointer value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_boxed (type, value));
}
/**
* tp_asv_take_boxed: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @type: the type of the key's value, which must be derived from %G_TYPE_BOXED
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_boxed(), tp_g_value_slice_new_take_boxed()
* Since: 0.7.29
*/
void
tp_asv_take_boxed (GHashTable *asv,
const gchar *key,
GType type,
gpointer value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_take_boxed (type, value));
}
/**
* tp_asv_set_static_boxed: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @type: the type of the key's value, which must be derived from %G_TYPE_BOXED
* @value: value
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_boxed(),
* tp_g_value_slice_new_static_boxed()
* Since: 0.7.29
*/
void
tp_asv_set_static_boxed (GHashTable *asv,
const gchar *key,
GType type,
gconstpointer value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_static_boxed (type, value));
}
/**
* tp_asv_get_strv:
* @asv: (element-type utf8 GObject.Value): A GHashTable where the keys are
* strings and the values are GValues
* @key: The key to look up
*
* If a value for @key in @asv is present and is an array of strings (strv),
* return it.
*
* Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it with g_strdupv() if you
* need to keep it for longer.
*
* Returns: (transfer none) (allow-none): the %NULL-terminated string-array
* value of @key, or %NULL
* Since: 0.7.9
*/
const gchar * const *
tp_asv_get_strv (const GHashTable *asv,
const gchar *key)
{
GValue *value;
g_return_val_if_fail (asv != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
value = g_hash_table_lookup ((GHashTable *) asv, key);
if (value == NULL || !G_VALUE_HOLDS (value, G_TYPE_STRV))
return NULL;
return g_value_get_boxed (value);
}
/**
* tp_asv_set_strv: (skip)
* @asv: a #GHashTable created with tp_asv_new()
* @key: string key
* @value: a %NULL-terminated string array
*
* Stores the value in the map.
*
* The value is stored as a slice-allocated GValue.
*
* See Also: tp_asv_new(), tp_asv_get_strv()
* Since: 0.7.29
*/
void
tp_asv_set_strv (GHashTable *asv,
const gchar *key,
gchar **value)
{
g_return_if_fail (asv != NULL);
g_return_if_fail (key != NULL);
g_hash_table_insert (asv, (char *) key,
tp_g_value_slice_new_boxed (G_TYPE_STRV, value));
}
/**
* tp_asv_lookup: (skip)
* @asv: A GHashTable where the keys are strings and the values are GValues
* @key: The key to look up
*
* If a value for @key in @asv is present, return it. Otherwise return %NULL.
*
* The returned value is not copied, and is only valid as long as the value
* for @key in @asv is not removed or altered. Copy it with (for instance)
* g_value_copy() if you need to keep it for longer.
*
* Returns: the value of @key, or %NULL
* Since: 0.7.9
*/
const GValue *
tp_asv_lookup (const GHashTable *asv,
const gchar *key)
{
g_return_val_if_fail (asv != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
return g_hash_table_lookup ((GHashTable *) asv, key);
}
/**
* tp_asv_dump: (skip)
* @asv: a #GHashTable created with tp_asv_new()
*
* Dumps the a{sv} map to the debugging console.
*
* The purpose of this function is give the programmer the ability to easily
* inspect the contents of an a{sv} map for debugging purposes.
*/
void
tp_asv_dump (GHashTable *asv)
{
GHashTableIter iter;
char *key;
GValue *value;
g_return_if_fail (asv != NULL);
g_debug ("{");
g_hash_table_iter_init (&iter, asv);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
{
char *str = g_strdup_value_contents (value);
g_debug (" '%s' : %s", key, str);
g_free (str);
}
g_debug ("}");
}