[glib] Optimize reading strings when deserializing gdbus messages
- From: Mike Gorse <mgorse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Optimize reading strings when deserializing gdbus messages
- Date: Fri, 30 Nov 2012 21:49:32 +0000 (UTC)
commit fe0b77fea8c9e5e5d1dd1cada4c18f17b6c9085a
Author: Mike Gorse <mgorse suse com>
Date: Thu Nov 29 16:51:59 2012 -0600
Optimize reading strings when deserializing gdbus messages
Now that we're directly accessing the memory holding a message blob,
we can access strings directly while reading them. This speeds up
read_string significantly, since we no longer malloc/memcpy/free.
gio/gdbusmessage.c | 98 ++++++++++++++-------------------------------------
1 files changed, 27 insertions(+), 71 deletions(-)
---
diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 0bbf1b2..ecbc033 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -66,27 +66,6 @@ struct _GMemoryBuffer
GDataStreamByteOrder byte_order;
};
-static gssize
-g_memory_buffer_read (GMemoryBuffer *mbuf,
- void **buffer,
- gsize count,
- GError **error)
-{
- gssize res;
-
- if (((gssize) count) < 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- _("Too large count value passed to %s"), G_STRFUNC);
- return -1;
- }
-
- res = MIN (count, mbuf->valid_len - mbuf->pos);
- *buffer = mbuf->data + mbuf->pos;
- mbuf->pos += res;
- return res;
-}
-
static guchar
g_memory_buffer_read_byte (GMemoryBuffer *mbuf,
GError **error)
@@ -1384,28 +1363,17 @@ ensure_input_padding (GMemoryBuffer *buf,
return TRUE;
}
-static gchar *
+static const gchar *
read_string (GMemoryBuffer *mbuf,
gsize len,
GError **error)
{
gchar *str;
- guchar nul;
- GError *local_error;
const gchar *end_valid;
- gssize num_read;
- gchar *ptr;
- str = g_malloc (len + 1);
-
- num_read = g_memory_buffer_read (mbuf,
- (void **)&ptr,
- len,
- error);
- if (num_read < 0)
- goto fail;
- if (num_read < len)
+ if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
{
+ mbuf->pos = mbuf->valid_len;
/* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
g_set_error (error,
G_IO_ERROR,
@@ -1415,19 +1383,27 @@ read_string (GMemoryBuffer *mbuf,
"Wanted to read %lu byte but only got %lu",
(gulong)len),
(gulong)len,
- (gulong)num_read);
- goto fail;
+ (gulong)mbuf->valid_len - mbuf->pos);
+ mbuf->pos = mbuf->valid_len;
+ return NULL;
}
- memcpy (str, ptr, len);
- local_error = NULL;
- nul = g_memory_buffer_read_byte (mbuf, &local_error);
- if (local_error != NULL)
+ if (mbuf->data[mbuf->pos + len] != '\0')
{
- g_propagate_error (error, local_error);
- goto fail;
+ str = g_strndup (mbuf->data + mbuf->pos, len);
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Expected NUL byte after the string `%s' but found byte %d"),
+ str, mbuf->data[mbuf->pos + len]);
+ g_free (str);
+ mbuf->pos += len + 1;
+ return NULL;
}
- str[num_read] = '\0';
+
+ str = mbuf->data + mbuf->pos;
+ mbuf->pos += len + 1;
+
if (!g_utf8_validate (str, -1, &end_valid))
{
gint offset;
@@ -1440,26 +1416,13 @@ read_string (GMemoryBuffer *mbuf,
_("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
"The valid UTF-8 string up until that point was `%s'"),
offset,
- (gint) num_read,
+ (gint) len,
valid_str);
g_free (valid_str);
- goto fail;
- }
- if (nul != '\0')
- {
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_INVALID_ARGUMENT,
- _("Expected NUL byte after the string `%s' but found byte %d"),
- str, nul);
- goto fail;
+ return NULL;
}
return str;
-
- fail:
- g_free (str);
- return NULL;
}
/* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
@@ -1623,7 +1586,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
if (!just_align)
{
guint32 len;
- gchar *v;
+ const gchar *v;
len = g_memory_buffer_read_uint32 (buf, &local_error);
if (local_error != NULL)
goto fail;
@@ -1631,7 +1594,6 @@ parse_value_from_blob (GMemoryBuffer *buf,
if (v == NULL)
goto fail;
ret = g_variant_new_string (v);
- g_free (v);
}
break;
@@ -1641,7 +1603,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
if (!just_align)
{
guint32 len;
- gchar *v;
+ const gchar *v;
len = g_memory_buffer_read_uint32 (buf, &local_error);
if (local_error != NULL)
goto fail;
@@ -1655,11 +1617,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
G_IO_ERROR_INVALID_ARGUMENT,
_("Parsed value `%s' is not a valid D-Bus object path"),
v);
- g_free (v);
goto fail;
}
ret = g_variant_new_object_path (v);
- g_free (v);
}
break;
@@ -1667,7 +1627,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
if (!just_align)
{
guchar len;
- gchar *v;
+ const gchar *v;
len = g_memory_buffer_read_byte (buf, &local_error);
if (local_error != NULL)
goto fail;
@@ -1681,11 +1641,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
G_IO_ERROR_INVALID_ARGUMENT,
_("Parsed value `%s' is not a valid D-Bus signature"),
v);
- g_free (v);
goto fail;
}
ret = g_variant_new_signature (v);
- g_free (v);
}
break;
@@ -1874,7 +1832,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
if (!just_align)
{
guchar siglen;
- gchar *sig;
+ const gchar *sig;
GVariantType *variant_type;
GVariant *value;
@@ -1891,11 +1849,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
G_IO_ERROR_INVALID_ARGUMENT,
_("Parsed value `%s' for variant is not a valid D-Bus signature"),
sig);
- g_free (sig);
goto fail;
}
variant_type = g_variant_type_new (sig);
- g_free (sig);
value = parse_value_from_blob (buf,
variant_type,
FALSE,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]