[glib] gsocketconnectable: Add a to_string() virtual method
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gsocketconnectable: Add a to_string() virtual method
- Date: Tue, 13 Oct 2015 14:52:46 +0000 (UTC)
commit 128c413261f60c044aca14895ca2c5d2574d791e
Author: Philip Withnall <philip withnall collabora co uk>
Date: Sun Oct 4 15:24:24 2015 +0100
gsocketconnectable: Add a to_string() virtual method
Add string serialisation functions for GNetworkAddress, GSocketAddress,
GUnixSocketAddress, GInetSocketAddress, GNetworkService and
GSocketConnectable. These are intended for use in debug output, not for
serialisation in network or disc protocols.
They are implemented as a new virtual method on GSocketConnectable:
g_socket_connectable_to_string().
GInetSocketAddress and GUnixSocketAddress now implement
GSocketConnectable directly to implement to_string(). Previously they
implemented it via their abstract parent class, GSocketAddress.
https://bugzilla.gnome.org/show_bug.cgi?id=737116
docs/reference/gio/gio-sections.txt | 1 +
gio/ginetsocketaddress.c | 62 ++++++++++++++++++++++++++++++++++-
gio/gnetworkaddress.c | 26 ++++++++++++++
gio/gnetworkservice.c | 14 ++++++++
gio/gsocketaddress.c | 1 +
gio/gsocketconnectable.c | 31 +++++++++++++++++
gio/gsocketconnectable.h | 6 +++
gio/gunixsocketaddress.c | 52 ++++++++++++++++++++++++++++-
gio/tests/inet-address.c | 50 ++++++++++++++++++++++++++++
gio/tests/network-address.c | 38 +++++++++++++++++++++
gio/tests/socket-address.c | 40 ++++++++++++++++++++++
11 files changed, 319 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index f0a4c49..9eb68b2 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1915,6 +1915,7 @@ GSocketConnectable
GSocketConnectableIface
g_socket_connectable_enumerate
g_socket_connectable_proxy_enumerate
+g_socket_connectable_to_string
<SUBSECTION>
GSocketAddressEnumerator
g_socket_address_enumerator_next
diff --git a/gio/ginetsocketaddress.c b/gio/ginetsocketaddress.c
index 5cf26f7..c38fa60 100644
--- a/gio/ginetsocketaddress.c
+++ b/gio/ginetsocketaddress.c
@@ -26,6 +26,7 @@
#include "ginetsocketaddress.h"
#include "ginetaddress.h"
#include "gnetworkingprivate.h"
+#include "gsocketconnectable.h"
#include "gioerror.h"
#include "glibintl.h"
@@ -54,7 +55,13 @@ struct _GInetSocketAddressPrivate
guint32 scope_id;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS)
+static void g_inet_socket_address_connectable_iface_init (GSocketConnectableIface *iface);
+static gchar *g_inet_socket_address_connectable_to_string (GSocketConnectable *connectable);
+
+G_DEFINE_TYPE_WITH_CODE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS,
+ G_ADD_PRIVATE (GInetSocketAddress)
+ G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
+ g_inet_socket_address_connectable_iface_init))
enum {
PROP_0,
@@ -302,6 +309,59 @@ g_inet_socket_address_class_init (GInetSocketAddressClass *klass)
}
static void
+g_inet_socket_address_connectable_iface_init (GSocketConnectableIface *iface)
+{
+ GSocketConnectableIface *parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->enumerate = parent_iface->enumerate;
+ iface->proxy_enumerate = parent_iface->proxy_enumerate;
+ iface->to_string = g_inet_socket_address_connectable_to_string;
+}
+
+static gchar *
+g_inet_socket_address_connectable_to_string (GSocketConnectable *connectable)
+{
+ GInetSocketAddress *sa;
+ GInetAddress *a;
+ gchar *a_string;
+ GString *out;
+ guint16 port;
+
+ sa = G_INET_SOCKET_ADDRESS (connectable);
+ a = g_inet_socket_address_get_address (sa);
+ out = g_string_new ("");
+
+ /* Address. */
+ a_string = g_inet_address_to_string (a);
+ g_string_append (out, a_string);
+ g_free (a_string);
+
+ /* Scope ID (IPv6 only). */
+ if (g_inet_address_get_family (a) == G_SOCKET_FAMILY_IPV6 &&
+ g_inet_socket_address_get_scope_id (sa) != 0)
+ {
+ g_string_append_printf (out, "%%%u",
+ g_inet_socket_address_get_scope_id (sa));
+ }
+
+ /* Port. */
+ port = g_inet_socket_address_get_port (sa);
+ if (port != 0)
+ {
+ /* Disambiguate ports from IPv6 addresses using square brackets. */
+ if (g_inet_address_get_family (a) == G_SOCKET_FAMILY_IPV6)
+ {
+ g_string_prepend (out, "[");
+ g_string_append (out, "]");
+ }
+
+ g_string_append_printf (out, ":%u", port);
+ }
+
+ return g_string_free (out, FALSE);
+}
+
+static void
g_inet_socket_address_init (GInetSocketAddress *address)
{
address->priv = g_inet_socket_address_get_instance_private (address);
diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c
index 144db44..99c495a 100644
--- a/gio/gnetworkaddress.c
+++ b/gio/gnetworkaddress.c
@@ -86,6 +86,7 @@ static void g_network_address_get_property (GObject *object,
static void g_network_address_connectable_iface_init (GSocketConnectableIface
*iface);
static GSocketAddressEnumerator *g_network_address_connectable_enumerate (GSocketConnectable
*connectable);
static GSocketAddressEnumerator *g_network_address_connectable_proxy_enumerate (GSocketConnectable
*connectable);
+static gchar *g_network_address_connectable_to_string (GSocketConnectable
*connectable);
G_DEFINE_TYPE_WITH_CODE (GNetworkAddress, g_network_address, G_TYPE_OBJECT,
G_ADD_PRIVATE (GNetworkAddress)
@@ -145,6 +146,7 @@ g_network_address_connectable_iface_init (GSocketConnectableIface *connectable_i
{
connectable_iface->enumerate = g_network_address_connectable_enumerate;
connectable_iface->proxy_enumerate = g_network_address_connectable_proxy_enumerate;
+ connectable_iface->to_string = g_network_address_connectable_to_string;
}
static void
@@ -1111,3 +1113,27 @@ g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
return proxy_enum;
}
+
+static gchar *
+g_network_address_connectable_to_string (GSocketConnectable *connectable)
+{
+ GNetworkAddress *addr;
+ const gchar *scheme;
+ guint16 port;
+ GString *out; /* owned */
+
+ addr = G_NETWORK_ADDRESS (connectable);
+ out = g_string_new ("");
+
+ scheme = g_network_address_get_scheme (addr);
+ if (scheme != NULL)
+ g_string_append_printf (out, "%s:", scheme);
+
+ g_string_append (out, g_network_address_get_hostname (addr));
+
+ port = g_network_address_get_port (addr);
+ if (port != 0)
+ g_string_append_printf (out, ":%u", port);
+
+ return g_string_free (out, FALSE);
+}
diff --git a/gio/gnetworkservice.c b/gio/gnetworkservice.c
index 497d6fd..d759819 100644
--- a/gio/gnetworkservice.c
+++ b/gio/gnetworkservice.c
@@ -89,6 +89,7 @@ static void g_network_service_get_property (GObject *object,
static void g_network_service_connectable_iface_init (GSocketConnectableIface
*iface);
static GSocketAddressEnumerator *g_network_service_connectable_enumerate (GSocketConnectable
*connectable);
static GSocketAddressEnumerator *g_network_service_connectable_proxy_enumerate (GSocketConnectable
*connectable);
+static gchar *g_network_service_connectable_to_string (GSocketConnectable
*connectable);
G_DEFINE_TYPE_WITH_CODE (GNetworkService, g_network_service, G_TYPE_OBJECT,
G_ADD_PRIVATE (GNetworkService)
@@ -159,6 +160,7 @@ g_network_service_connectable_iface_init (GSocketConnectableIface *connectable_i
{
connectable_iface->enumerate = g_network_service_connectable_enumerate;
connectable_iface->proxy_enumerate = g_network_service_connectable_proxy_enumerate;
+ connectable_iface->to_string = g_network_service_connectable_to_string;
}
static void
@@ -743,3 +745,15 @@ g_network_service_connectable_proxy_enumerate (GSocketConnectable *connectable)
return addr_enum;
}
+
+static gchar *
+g_network_service_connectable_to_string (GSocketConnectable *connectable)
+{
+ GNetworkService *service;
+
+ service = G_NETWORK_SERVICE (connectable);
+
+ return g_strdup_printf ("(%s, %s, %s, %s)", service->priv->service,
+ service->priv->protocol, service->priv->domain,
+ service->priv->scheme);
+}
diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c
index d0caf33..cefd9e0 100644
--- a/gio/gsocketaddress.c
+++ b/gio/gsocketaddress.c
@@ -129,6 +129,7 @@ g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_if
{
connectable_iface->enumerate = g_socket_address_connectable_enumerate;
connectable_iface->proxy_enumerate = g_socket_address_connectable_proxy_enumerate;
+ /* to_string() is implemented by subclasses */
}
static void
diff --git a/gio/gsocketconnectable.c b/gio/gsocketconnectable.c
index 79901aa..ef9f92d 100644
--- a/gio/gsocketconnectable.c
+++ b/gio/gsocketconnectable.c
@@ -146,3 +146,34 @@ g_socket_connectable_proxy_enumerate (GSocketConnectable *connectable)
else
return (* iface->enumerate) (connectable);
}
+
+/**
+ * g_socket_connectable_to_string:
+ * @connectable: a #GSocketConnectable
+ *
+ * Format a #GSocketConnectable as a string. This is a human-readable format for
+ * use in debugging output, and is not a stable serialization format. It is not
+ * suitable for use in user interfaces as it exposes too much information for a
+ * user.
+ *
+ * If the #GSocketConnectable implementation does not support string formatting,
+ * the implementation’s type name will be returned as a fallback.
+ *
+ * Returns: (transfer full): the formatted string
+ *
+ * Since: 2.48.0
+ */
+gchar *
+g_socket_connectable_to_string (GSocketConnectable *connectable)
+{
+ GSocketConnectableIface *iface;
+
+ g_return_val_if_fail (G_IS_SOCKET_CONNECTABLE (connectable), NULL);
+
+ iface = G_SOCKET_CONNECTABLE_GET_IFACE (connectable);
+
+ if (iface->to_string != NULL)
+ return iface->to_string (connectable);
+ else
+ return g_strdup (G_OBJECT_TYPE_NAME (connectable));
+}
diff --git a/gio/gsocketconnectable.h b/gio/gsocketconnectable.h
index f7db680..b562ff1 100644
--- a/gio/gsocketconnectable.h
+++ b/gio/gsocketconnectable.h
@@ -44,6 +44,8 @@ typedef struct _GSocketConnectableIface GSocketConnectableIface;
* @g_iface: The parent interface.
* @enumerate: Creates a #GSocketAddressEnumerator
* @proxy_enumerate: Creates a #GProxyAddressEnumerator
+ * @to_string: Format the connectable’s address as a string for debugging.
+ * Implementing this is optional. (Since: 2.48.0.)
*
* Provides an interface for returning a #GSocketAddressEnumerator
* and #GProxyAddressEnumerator
@@ -58,6 +60,7 @@ struct _GSocketConnectableIface
GSocketAddressEnumerator * (* proxy_enumerate) (GSocketConnectable *connectable);
+ gchar * (* to_string) (GSocketConnectable *connectable);
};
GLIB_AVAILABLE_IN_ALL
@@ -69,6 +72,9 @@ GSocketAddressEnumerator *g_socket_connectable_enumerate (GSocketConnectable *co
GLIB_AVAILABLE_IN_ALL
GSocketAddressEnumerator *g_socket_connectable_proxy_enumerate (GSocketConnectable *connectable);
+GLIB_AVAILABLE_IN_2_48
+gchar *g_socket_connectable_to_string (GSocketConnectable *addr);
+
G_END_DECLS
diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c
index b1702cb..f4fc077 100644
--- a/gio/gunixsocketaddress.c
+++ b/gio/gunixsocketaddress.c
@@ -24,6 +24,7 @@
#include <string.h>
#include "gunixsocketaddress.h"
+#include "gsocketconnectable.h"
#include "glibintl.h"
#include "gnetworking.h"
@@ -76,7 +77,13 @@ struct _GUnixSocketAddressPrivate
GUnixSocketAddressType address_type;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GUnixSocketAddress, g_unix_socket_address, G_TYPE_SOCKET_ADDRESS)
+static void g_unix_socket_address_connectable_iface_init (GSocketConnectableIface *iface);
+static gchar *g_unix_socket_address_connectable_to_string (GSocketConnectable *connectable);
+
+G_DEFINE_TYPE_WITH_CODE (GUnixSocketAddress, g_unix_socket_address, G_TYPE_SOCKET_ADDRESS,
+ G_ADD_PRIVATE (GUnixSocketAddress)
+ G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
+ g_unix_socket_address_connectable_iface_init))
static void
g_unix_socket_address_set_property (GObject *object,
@@ -300,6 +307,49 @@ g_unix_socket_address_class_init (GUnixSocketAddressClass *klass)
}
static void
+g_unix_socket_address_connectable_iface_init (GSocketConnectableIface *iface)
+{
+ GSocketConnectableIface *parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->enumerate = parent_iface->enumerate;
+ iface->proxy_enumerate = parent_iface->proxy_enumerate;
+ iface->to_string = g_unix_socket_address_connectable_to_string;
+}
+
+static gchar *
+g_unix_socket_address_connectable_to_string (GSocketConnectable *connectable)
+{
+ GUnixSocketAddress *ua;
+ GString *out;
+ const gchar *path;
+ gsize path_len, i;
+
+ ua = G_UNIX_SOCKET_ADDRESS (connectable);
+
+ /* Anonymous sockets have no path. */
+ if (ua->priv->address_type == G_UNIX_SOCKET_ADDRESS_ANONYMOUS)
+ return g_strdup ("anonymous");
+
+ path = g_unix_socket_address_get_path (ua);
+ path_len = g_unix_socket_address_get_path_len (ua);
+ out = g_string_sized_new (path_len);
+
+ /* Return the #GUnixSocketAddress:path, but with all non-printable characters
+ * (including nul bytes) escaped to hex. */
+ for (i = 0; i < path_len; i++)
+ {
+ guint8 c = path[i];
+
+ if (g_ascii_isprint (path[i]))
+ g_string_append_c (out, c);
+ else
+ g_string_append_printf (out, "\\x%02x", (guint) c);
+ }
+
+ return g_string_free (out, FALSE);
+}
+
+static void
g_unix_socket_address_init (GUnixSocketAddress *address)
{
address->priv = g_unix_socket_address_get_instance_private (address);
diff --git a/gio/tests/inet-address.c b/gio/tests/inet-address.c
index addcbb4..6e4c424 100644
--- a/gio/tests/inet-address.c
+++ b/gio/tests/inet-address.c
@@ -236,6 +236,55 @@ test_socket_address (void)
}
static void
+test_socket_address_to_string (void)
+{
+ GSocketAddress *sa = NULL;
+ GInetAddress *ia = NULL;
+ gchar *str = NULL;
+
+ /* IPv4. */
+ ia = g_inet_address_new_from_string ("123.1.123.1");
+ sa = g_inet_socket_address_new (ia, 80);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (sa));
+ g_assert_cmpstr (str, ==, "123.1.123.1:80");
+ g_free (str);
+ g_object_unref (sa);
+ g_object_unref (ia);
+
+ /* IPv6. */
+ ia = g_inet_address_new_from_string ("::80");
+ sa = g_inet_socket_address_new (ia, 80);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (sa));
+ g_assert_cmpstr (str, ==, "[::80]:80");
+ g_free (str);
+ g_object_unref (sa);
+ g_object_unref (ia);
+
+ /* IPv6 without port. */
+ ia = g_inet_address_new_from_string ("::80");
+ sa = g_inet_socket_address_new (ia, 0);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (sa));
+ g_assert_cmpstr (str, ==, "::80");
+ g_free (str);
+ g_object_unref (sa);
+ g_object_unref (ia);
+
+ /* IPv6 with scope. */
+ ia = g_inet_address_new_from_string ("::1");
+ sa = G_SOCKET_ADDRESS (g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
+ "address", ia,
+ "port", 123,
+ "flowinfo", 10,
+ "scope-id", 25,
+ NULL));
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (sa));
+ g_assert_cmpstr (str, ==, "[::1%25]:123");
+ g_free (str);
+ g_object_unref (sa);
+ g_object_unref (ia);
+}
+
+static void
test_mask_parse (void)
{
GInetAddressMask *mask;
@@ -368,6 +417,7 @@ main (int argc, char *argv[])
g_test_add_func ("/inet-address/bytes", test_bytes);
g_test_add_func ("/inet-address/property", test_property);
g_test_add_func ("/socket-address/basic", test_socket_address);
+ g_test_add_func ("/socket-address/to-string", test_socket_address_to_string);
g_test_add_func ("/address-mask/parse", test_mask_parse);
g_test_add_func ("/address-mask/property", test_mask_property);
g_test_add_func ("/address-mask/equal", test_mask_equal);
diff --git a/gio/tests/network-address.c b/gio/tests/network-address.c
index 73e323c..622af17 100644
--- a/gio/tests/network-address.c
+++ b/gio/tests/network-address.c
@@ -477,6 +477,43 @@ test_loopback_async (void)
g_object_unref (addr);
}
+static void
+test_to_string (void)
+{
+ GSocketConnectable *addr = NULL;
+ gchar *str = NULL;
+ GError *error = NULL;
+
+ /* Without port. */
+ addr = g_network_address_new ("some-hostname", 0);
+ str = g_socket_connectable_to_string (addr);
+ g_assert_cmpstr (str, ==, "some-hostname");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* With port. */
+ addr = g_network_address_new ("some-hostname", 123);
+ str = g_socket_connectable_to_string (addr);
+ g_assert_cmpstr (str, ==, "some-hostname:123");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* With scheme and port. */
+ addr = g_network_address_parse_uri ("http://some-hostname:123", 80, &error);
+ g_assert_no_error (error);
+ str = g_socket_connectable_to_string (addr);
+ g_assert_cmpstr (str, ==, "http:some-hostname:123");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* Loopback. */
+ addr = g_network_address_new ("localhost", 456);
+ str = g_socket_connectable_to_string (addr);
+ g_assert_cmpstr (str, ==, "localhost:456");
+ g_free (str);
+ g_object_unref (addr);
+}
+
int
main (int argc, char *argv[])
{
@@ -520,6 +557,7 @@ main (int argc, char *argv[])
g_test_add_func ("/network-address/loopback/basic", test_loopback_basic);
g_test_add_func ("/network-address/loopback/sync", test_loopback_sync);
g_test_add_func ("/network-address/loopback/async", test_loopback_async);
+ g_test_add_func ("/network-address/to-string", test_to_string);
return g_test_run ();
}
diff --git a/gio/tests/socket-address.c b/gio/tests/socket-address.c
index c3cd809..b3323c2 100644
--- a/gio/tests/socket-address.c
+++ b/gio/tests/socket-address.c
@@ -67,6 +67,45 @@ test_unix_socket_address_construct (void)
g_object_unref (a);
}
+static void
+test_unix_socket_address_to_string (void)
+{
+ GSocketAddress *addr = NULL;
+ gchar *str = NULL;
+
+ /* ADDRESS_PATH. */
+ addr = g_unix_socket_address_new_with_type ("/some/path", -1,
+ G_UNIX_SOCKET_ADDRESS_PATH);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
+ g_assert_cmpstr (str, ==, "/some/path");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* ADDRESS_ANONYMOUS. */
+ addr = g_unix_socket_address_new_with_type ("", 0,
+ G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
+ g_assert_cmpstr (str, ==, "anonymous");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* ADDRESS_ABSTRACT. */
+ addr = g_unix_socket_address_new_with_type ("abstract-path\0✋", 17,
+ G_UNIX_SOCKET_ADDRESS_ABSTRACT);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
+ g_assert_cmpstr (str, ==, "abstract-path\\x00\\xe2\\x9c\\x8b");
+ g_free (str);
+ g_object_unref (addr);
+
+ /* ADDRESS_ABSTRACT_PADDED. */
+ addr = g_unix_socket_address_new_with_type ("abstract-path\0✋", 17,
+ G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
+ str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
+ g_assert_cmpstr (str, ==, "abstract-path\\x00\\xe2\\x9c\\x8b");
+ g_free (str);
+ g_object_unref (addr);
+}
+
int
main (int argc,
char **argv)
@@ -74,6 +113,7 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/socket/address/unix/construct", test_unix_socket_address_construct);
+ g_test_add_func ("/socket/address/unix/to-string", test_unix_socket_address_to_string);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]