[glib/gvariant] GVariant: add support for file descriptor handles
- From: Ryan Lortie <ryanl src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [glib/gvariant] GVariant: add support for file descriptor handles
- Date: Tue, 10 Nov 2009 03:47:38 +0000 (UTC)
commit bccce3e8fff965ff6a0740b17c7e358f8c7d9ad2
Author: Ryan Lortie <desrt desrt ca>
Date: Mon Nov 9 22:47:13 2009 -0500
GVariant: add support for file descriptor handles
docs/reference/glib/glib-sections.txt | 2 +
glib/gvariant-markup.c | 10 +++++
glib/gvariant-parser.c | 29 +++++++++++----
glib/gvariant-printer.c | 14 ++++++-
glib/gvariant-serialiser.c | 1 +
glib/gvariant-util.c | 49 +++++++++++++++++++++++---
glib/gvariant-valist.c | 26 ++++++++++++--
glib/gvariant.h | 2 +
glib/gvarianttype.c | 8 +++--
glib/gvarianttype.h | 14 +++++++-
glib/gvarianttypeinfo.c | 1 +
glib/tests/.gitignore | 1 +
glib/tests/Makefile.am | 3 ++
glib/tests/gvariant-handle.c | 63 +++++++++++++++++++++++++++++++++
14 files changed, 202 insertions(+), 21 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index b6edbf3..cb52127 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2798,6 +2798,7 @@ g_variant_new_signature
g_variant_is_signature
g_variant_new_variant
g_variant_new_strv
+g_variant_new_handle
<SUBSECTION>
g_variant_get_boolean
@@ -2814,6 +2815,7 @@ g_variant_dup_string
g_variant_get_variant
g_variant_get_strv
g_variant_dup_strv
+g_variant_get_handle
<SUBSECTION>
g_variant_n_children
diff --git a/glib/gvariant-markup.c b/glib/gvariant-markup.c
index a1f7aa0..0d8090a 100644
--- a/glib/gvariant-markup.c
+++ b/glib/gvariant-markup.c
@@ -293,6 +293,11 @@ g_variant_markup_print_string (GVariant *value,
g_variant_get_int32 (value));
break;
+ case G_VARIANT_TYPE_CLASS_HANDLE:
+ g_string_append_printf (string, "<handle>%"G_GINT32_FORMAT"</handle>",
+ g_variant_get_handle (value));
+ break;
+
case G_VARIANT_TYPE_CLASS_UINT32:
g_string_append_printf (string, "<uint32>%"G_GUINT32_FORMAT"</uint32>",
g_variant_get_uint32 (value));
@@ -410,6 +415,7 @@ type_class_from_keyword (const char *keyword)
{ G_VARIANT_TYPE_CLASS_INT16, "int16" },
{ G_VARIANT_TYPE_CLASS_UINT16, "uint16" },
{ G_VARIANT_TYPE_CLASS_INT32, "int32" },
+ { G_VARIANT_TYPE_CLASS_HANDLE, "handle" },
{ G_VARIANT_TYPE_CLASS_UINT32, "uint32" },
{ G_VARIANT_TYPE_CLASS_INT64, "int64" },
{ G_VARIANT_TYPE_CLASS_UINT64, "uint64" },
@@ -628,6 +634,10 @@ g_variant_markup_parser_end_element (GMarkupParseContext *context,
value = g_variant_new_int32 (g_ascii_strtoll (string, &end, 0));
break;
+ case G_VARIANT_TYPE_CLASS_HANDLE:
+ value = g_variant_new_handle (g_ascii_strtoll (string, &end, 0));
+ break;
+
case G_VARIANT_TYPE_CLASS_UINT32:
value = g_variant_new_uint32 (g_ascii_strtoull (string, &end, 0));
break;
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
index f4a0331..5927108 100644
--- a/glib/gvariant-parser.c
+++ b/glib/gvariant-parser.c
@@ -238,7 +238,7 @@ type_from_constraints (Constraints constraints)
if (constraints & (CONSTRAINT_IS_NUMBER | CONSTRAINT_IS_BOOLEAN))
return 0;
- return 's';
+ return G_VARIANT_TYPE_CLASS_STRING;
}
if (constraints & CONSTRAINT_IS_BOOLEAN)
@@ -246,13 +246,13 @@ type_from_constraints (Constraints constraints)
if (constraints & CONSTRAINT_IS_NUMBER)
return 0;
- return 'b';
+ return G_VARIANT_TYPE_CLASS_BOOLEAN;
}
if (constraints & CONSTRAINT_HAS_POINT)
- return 'd';
+ return G_VARIANT_TYPE_CLASS_DOUBLE;
- return 'i';
+ return G_VARIANT_TYPE_CLASS_INT32;
}
typedef struct
@@ -321,11 +321,11 @@ pattern_coalesce (Pattern *dest,
dest->constraints[i] |= src->constraints[i];
else if (dest->type_string[i] == '?' &&
- strchr ("bynqiuxtdsog", src->type_string[i]))
+ strchr ("bynqihuxtdsog", src->type_string[i]))
dest->type_string[i] = src->type_string[i];
else if (src->type_string[i] != '?' ||
- !strchr ("bynqiuxtdsog", dest->type_string[i]))
+ !strchr ("bynqihuxtdsog", dest->type_string[i]))
return FALSE;
}
@@ -995,7 +995,7 @@ dictionary_get_pattern (AST *ast,
if (other_pattern == NULL)
break;
- if (!strchr ("bynqiuxtdsog?", other_pattern->type_string[0]))
+ if (!strchr ("bynqihuxtdsog?", other_pattern->type_string[0]))
{
ast_set_error (ast, error, "dictionary keys must have basic types");
pattern_free (other_pattern);
@@ -1509,6 +1509,18 @@ terminal_get_value (AST *ast,
return g_variant_new_int32 (value);
}
+ case G_VARIANT_TYPE_CLASS_HANDLE:
+ {
+ gint64 value;
+
+ if (!parse_signed (terminal->token,
+ G_MININT32, G_MAXINT32,
+ &value, ast, error))
+ return NULL;
+
+ return g_variant_new_handle (value);
+ }
+
case G_VARIANT_TYPE_CLASS_UINT32:
{
guint64 value;
@@ -1912,6 +1924,9 @@ typedecl_parse (TokenStream *stream,
else if (token_stream_consume (stream, "int32"))
type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
+ else if (token_stream_consume (stream, "handle"))
+ type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
+
else if (token_stream_consume (stream, "uint32"))
type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
diff --git a/glib/gvariant-printer.c b/glib/gvariant-printer.c
index 63d6967..90e5fbd 100644
--- a/glib/gvariant-printer.c
+++ b/glib/gvariant-printer.c
@@ -1,6 +1,6 @@
/*
- * Copyright © 2009, Sam Thursfield
- *
+ * Copyright © 2009 Sam Thursfield
+ * Copyright © 2009 Codethink Limited
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,6 +16,9 @@
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
+ *
+ * Authors: Sam Thursfield
+ * Ryan Lortie <desrt desrt ca>
*/
#include <math.h>
@@ -241,6 +244,13 @@ g_variant_print_string (GVariant *value,
g_variant_get_int32 (value));
break;
+ case G_VARIANT_TYPE_CLASS_HANDLE:
+ if (type_annotate)
+ g_string_append (string, "handle ");
+ g_string_append_printf (string, "%"G_GINT32_FORMAT,
+ g_variant_get_handle (value));
+ break;
+
case G_VARIANT_TYPE_CLASS_UINT32:
if (type_annotate)
g_string_append (string, "uint32 ");
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index 82f394b..0f28a01 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -925,6 +925,7 @@ g_variant_serialised_is_normal (GVariantSerialised value)
case G_VARIANT_TYPE_CLASS_INT16:
case G_VARIANT_TYPE_CLASS_UINT16:
case G_VARIANT_TYPE_CLASS_INT32:
+ case G_VARIANT_TYPE_CLASS_HANDLE:
case G_VARIANT_TYPE_CLASS_UINT32:
case G_VARIANT_TYPE_CLASS_INT64:
case G_VARIANT_TYPE_CLASS_UINT64:
diff --git a/glib/gvariant-util.c b/glib/gvariant-util.c
index c963c93..88e5428 100644
--- a/glib/gvariant-util.c
+++ b/glib/gvariant-util.c
@@ -257,7 +257,7 @@ g_variant_new_byte (guint8 byte)
/**
* g_variant_new_int16:
* @int16: a #gint16 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int16 #GVariant instance
*
* Creates a new int16 #GVariant instance.
**/
@@ -271,7 +271,7 @@ g_variant_new_int16 (gint16 int16)
/**
* g_variant_new_uint16:
* @uint16: a #guint16 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new uint16 #GVariant instance
*
* Creates a new uint16 #GVariant instance.
**/
@@ -285,7 +285,7 @@ g_variant_new_uint16 (guint16 uint16)
/**
* g_variant_new_int32:
* @int32: a #gint32 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int32 #GVariant instance
*
* Creates a new int32 #GVariant instance.
**/
@@ -297,6 +297,20 @@ g_variant_new_int32 (gint32 int32)
}
/**
+ * g_variant_new_handle:
+ * @handle: a #gint32 value
+ * @returns: a new handle #GVariant instance
+ *
+ * Creates a new int32 #GVariant instance.
+ **/
+GVariant *
+g_variant_new_handle (gint32 handle)
+{
+ return g_variant_load (G_VARIANT_TYPE_HANDLE,
+ &handle, 4, G_VARIANT_TRUSTED);
+}
+
+/**
* g_variant_new_uint32:
* @uint32: a #guint32 value
* @returns: a new uint32 #GVariant instance
@@ -313,7 +327,7 @@ g_variant_new_uint32 (guint32 uint32)
/**
* g_variant_new_int64:
* @int64: a #gint64 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int64 #GVariant instance
*
* Creates a new int64 #GVariant instance.
**/
@@ -478,7 +492,7 @@ g_variant_is_signature (const gchar *string)
g_return_val_if_fail (string != NULL, FALSE);
/* make sure no non-concrete characters appear */
- first_invalid = strspn (string, "ybnqiuxtdvmasog(){}");
+ first_invalid = strspn (string, "ybnqihuxtdvmasog(){}");
if (string[first_invalid])
return FALSE;
@@ -624,6 +638,28 @@ g_variant_get_int32 (GVariant *value)
}
/**
+ * g_variant_get_handle:
+ * @value: a handle #GVariant instance
+ * @returns: a #gint32
+ *
+ * Returns the 32-bit signed integer value of @value.
+ *
+ * It is an error to call this function with a @value of any type
+ * other than %G_VARIANT_TYPE_HANDLE.
+ **/
+gint32
+g_variant_get_handle (GVariant *value)
+{
+ gint32 int32;
+
+ g_return_val_if_fail (value != NULL, 0);
+ g_assert (g_variant_matches (value, G_VARIANT_TYPE_HANDLE));
+ g_variant_store (value, &int32);
+
+ return int32;
+}
+
+/**
* g_variant_get_uint32:
* @value: a uint32 #GVariant instance
* @returns: a #guint32
@@ -1795,6 +1831,9 @@ g_variant_deep_copy (GVariant *value)
return new;
}
+ case G_VARIANT_TYPE_CLASS_HANDLE:
+ return g_variant_new_handle (g_variant_get_handle (value));
+
case G_VARIANT_TYPE_CLASS_MAYBE:
case G_VARIANT_TYPE_CLASS_ARRAY:
case G_VARIANT_TYPE_CLASS_TUPLE:
diff --git a/glib/gvariant-valist.c b/glib/gvariant-valist.c
index 0e302ab..747b577 100644
--- a/glib/gvariant-valist.c
+++ b/glib/gvariant-valist.c
@@ -97,7 +97,7 @@ g_variant_format_string_scan (const gchar *string,
string++;
if (string == limit || *string == '\0' || /* { */
- !strchr ("bynqiuxtdsog?", *string++) || /* key */
+ !strchr ("bynqihuxtdsog?", *string++) || /* key */
!g_variant_format_string_scan (string, limit, &string) ||/* value */
string == limit || *string++ != '}') /* } */
return FALSE;
@@ -124,7 +124,7 @@ g_variant_format_string_scan (const gchar *string,
start++;
while (start != string)
- if (!strchr ("bynqiuxtd(){}", *start++))
+ if (!strchr ("bynqihuxtd(){}", *start++))
return FALSE;
break;
@@ -143,7 +143,7 @@ g_variant_format_string_scan (const gchar *string,
case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
case 'x': case 't': case 'd': case 's': case 'o': case 'g':
- case 'v': case '*': case '?': case 'r':
+ case 'v': case '*': case '?': case 'r': case 'h':
break;
default:
@@ -230,6 +230,10 @@ g_variant_valist_new (const gchar **format_string,
(*format_string)++;
return g_variant_new_int32 (va_arg (*app, gint));
+ case 'h':
+ (*format_string)++;
+ return g_variant_new_handle (va_arg (*app, gint));
+
case 'u':
(*format_string)++;
return g_variant_new_uint32 (va_arg (*app, guint));
@@ -555,6 +559,22 @@ g_variant_valist_get (GVariant *value,
return;
}
+ case 'h':
+ {
+ gint32 *ptr = va_arg (*app, gint32 *);
+
+ if (ptr)
+ {
+ if (value)
+ *ptr = g_variant_get_handle (value);
+ else
+ *ptr = 0;
+ }
+
+ (*format_string)++;
+ return;
+ }
+
case 'u':
{
guint32 *ptr = va_arg (*app, guint32 *);
diff --git a/glib/gvariant.h b/glib/gvariant.h
index 01f3cca..83ec437 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -90,6 +90,7 @@ gboolean g_variant_is_object_path (const g
GVariant * g_variant_new_signature (const gchar *string);
gboolean g_variant_is_signature (const gchar *string);
GVariant * g_variant_new_variant (GVariant *value);
+GVariant * g_variant_new_handle (gint32 handle);
GVariant * g_variant_new_strv (const gchar * const *strv,
gint length);
@@ -112,6 +113,7 @@ const gchar ** g_variant_get_strv (GVarian
gchar ** g_variant_dup_strv (GVariant *value,
gint *length);
GVariant * g_variant_get_variant (GVariant *value);
+gint32 g_variant_get_handle (GVariant *value);
gconstpointer g_variant_get_fixed (GVariant *value,
gsize size);
gconstpointer g_variant_get_fixed_array (GVariant *value,
diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c
index 4651647..50f33f3 100644
--- a/glib/gvarianttype.c
+++ b/glib/gvarianttype.c
@@ -48,7 +48,7 @@
* | 'r' | '{' + base + type + '}' | '(' + types + ')'
*
* base = 'b' | 'y' | 'n' | 'q' | 'i' | 'u' | 'x'
- * | 't' | 'd' | 's' | 'o' | 'g' | '?'
+ * | 't' | 'd' | 's' | 'o' | 'g' | 'h' | '?'
*
* types = '' | type + types
* </programlisting>
@@ -152,7 +152,7 @@ g_variant_type_string_scan (const gchar *string,
case '{':
if (string == limit || *string == '\0' || /* { */
- !strchr ("bynqiuxtdsog?", *string++) || /* key */
+ !strchr ("bynqihuxtdsog?", *string++) || /* key */
!g_variant_type_string_scan (string, limit, &string) || /* value */
string == limit || *string++ != '}') /* } */
return FALSE;
@@ -164,7 +164,7 @@ g_variant_type_string_scan (const gchar *string,
case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
case 'x': case 't': case 'd': case 's': case 'o': case 'g':
- case 'v': case 'r': case '*': case '?':
+ case 'v': case 'r': case '*': case '?': case 'h':
break;
default:
@@ -415,6 +415,7 @@ g_variant_type_is_basic (const GVariantType *type)
case 'n':
case 'q':
case 'i':
+ case 'h':
case 'u':
case 't':
case 'x':
@@ -669,6 +670,7 @@ g_variant_type_class_is_basic (GVariantTypeClass tclass)
case G_VARIANT_TYPE_CLASS_INT16:
case G_VARIANT_TYPE_CLASS_UINT16:
case G_VARIANT_TYPE_CLASS_INT32:
+ case G_VARIANT_TYPE_CLASS_HANDLE:
case G_VARIANT_TYPE_CLASS_UINT32:
case G_VARIANT_TYPE_CLASS_INT64:
case G_VARIANT_TYPE_CLASS_UINT64:
diff --git a/glib/gvarianttype.h b/glib/gvarianttype.h
index dcb0f49..80ed2f8 100644
--- a/glib/gvarianttype.h
+++ b/glib/gvarianttype.h
@@ -41,6 +41,7 @@ typedef struct OPAQUE_TYPE_GVariantType GVariantType;
* @G_VARIANT_TYPE_CLASS_OBJECT_PATH: the class containing the type %G_VARIANT_TYPE_OBJECT_PATH
* @G_VARIANT_TYPE_CLASS_SIGNATURE: the class containing the type %G_VARIANT_TYPE_SIGNATURE
* @G_VARIANT_TYPE_CLASS_VARIANT: the class containing the type %G_VARIANT_TYPE_VARIANT
+ * @G_VARIANT_TYPE_CLASS_HANDLE: the class containing the type %G_VARIANT_TYPE_HANDLE
* @G_VARIANT_TYPE_CLASS_MAYBE: the class containing all maybe types
* @G_VARIANT_TYPE_CLASS_ARRAY: the class containing all array types
* @G_VARIANT_TYPE_CLASS_TUPLE: the class containing all tuple types
@@ -82,9 +83,11 @@ typedef enum
G_VARIANT_TYPE_CLASS_VARIANT = 'v',
+ G_VARIANT_TYPE_CLASS_HANDLE = 'h',
+
G_VARIANT_TYPE_CLASS_MAYBE = 'm',
G_VARIANT_TYPE_CLASS_ARRAY = 'a',
- G_VARIANT_TYPE_CLASS_TUPLE = 'r',
+ G_VARIANT_TYPE_CLASS_TUPLE = 'r',
G_VARIANT_TYPE_CLASS_DICT_ENTRY = 'e',
G_VARIANT_TYPE_CLASS_ALL = '*',
@@ -203,6 +206,15 @@ typedef enum
#define G_VARIANT_TYPE_VARIANT ((const GVariantType *) "v")
/**
+ * G_VARIANT_TYPE_HANDLE:
+ *
+ * The type of a 32bit signed integer value, that by convention, is used
+ * as an index into an array of file descriptors that are sent alongside
+ * a DBus message.
+ **/
+#define G_VARIANT_TYPE_HANDLE ((const GVariantType *) "h")
+
+/**
* G_VARIANT_TYPE_UNIT:
*
* The empty tuple type. Has only one instance. Known also as "triv"
diff --git a/glib/gvarianttypeinfo.c b/glib/gvarianttypeinfo.c
index 344f3d0..c896d32 100644
--- a/glib/gvarianttypeinfo.c
+++ b/glib/gvarianttypeinfo.c
@@ -334,6 +334,7 @@ base_info_new (const GVariantTypeClass class)
case G_VARIANT_TYPE_CLASS_UINT32:
case G_VARIANT_TYPE_CLASS_INT32:
+ case G_VARIANT_TYPE_CLASS_HANDLE:
info->alignment = 4 - 1;
info->fixed_size = 4;
break;
diff --git a/glib/tests/.gitignore b/glib/tests/.gitignore
index a8e8597..6194648 100644
--- a/glib/tests/.gitignore
+++ b/glib/tests/.gitignore
@@ -13,6 +13,7 @@ tmpsample.xml
gvariant-big
gvariant-endian
gvariant-fuzz
+gvariant-handle
gvariant-markup
gvariant-printer-parser
gvariant-random
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 659337a..f71e3bd 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -44,6 +44,9 @@ markup_subparser_LDADD = $(progs_ldadd)
TEST_PROGS += array-test
array_test_LDADD = $(progs_ldadd)
+TEST_PROGS += gvariant-handle
+gvariant_handle_LDADD = $(progs_ldadd)
+
TEST_PROGS += gvariant-big
gvariant_big_LDADD = $(progs_ldadd)
diff --git a/glib/tests/gvariant-handle.c b/glib/tests/gvariant-handle.c
new file mode 100644
index 0000000..0a2e223
--- /dev/null
+++ b/glib/tests/gvariant-handle.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include <glib.h>
+
+static void
+test_handles (void)
+{
+ GVariant *handles;
+ const gint32 *hs;
+ gchar *str;
+ gint32 h;
+ gsize n;
+
+ handles = g_variant_new_parsed ("[6, 27, %h , -6, 77, %h , 0, 1]", 72, -1);
+ g_variant_ref_sink (handles);
+ str = g_variant_print (handles, TRUE);
+ g_variant_unref (handles);
+
+ g_assert_cmpstr (str, ==, "[handle 6, 27, 72, -6, 77, -1, 0, 1]");
+ handles = g_variant_new_parsed (str);
+ g_variant_ref_sink (handles);
+ g_free (str);
+
+ g_variant_get_child (handles, 2, "h", &h);
+ g_assert_cmpint (h, ==, 72);
+
+ g_variant_get_child (handles, 3, "h", &h);
+ g_assert_cmpint (h, ==, -6);
+
+ str = g_variant_markup_print (handles, 0, 0, 0);
+ g_assert_cmpstr ("<array><handle>6</handle><handle>27</handle><handle>72</handle><handle>-6</handle><handle>77</handle><handle>-1</handle><handle>0</handle><handle>1</handle></array>", ==, str);
+ g_variant_unref (handles);
+
+ handles = g_variant_markup_parse (str, -1, NULL, NULL);
+ g_free (str);
+
+ hs = g_variant_get_fixed_array (handles, sizeof *hs, &n);
+ g_assert_cmpint (n, ==, 8);
+ g_assert_cmpint (hs[0], ==, 6);
+ g_assert_cmpint (hs[1], ==, 27);
+ g_assert_cmpint (hs[2], ==, 72);
+ g_assert_cmpint (hs[3], ==, -6);
+ g_variant_unref (handles);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/variant/handles", test_handles);
+
+ return g_test_run ();
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]