mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-26 12:12:10 +01:00
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.
This commit is contained in:
parent
a5f57bad20
commit
fe0b77fea8
@ -66,27 +66,6 @@ struct _GMemoryBuffer
|
|||||||
GDataStreamByteOrder byte_order;
|
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
|
static guchar
|
||||||
g_memory_buffer_read_byte (GMemoryBuffer *mbuf,
|
g_memory_buffer_read_byte (GMemoryBuffer *mbuf,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -1384,28 +1363,17 @@ ensure_input_padding (GMemoryBuffer *buf,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *
|
static const gchar *
|
||||||
read_string (GMemoryBuffer *mbuf,
|
read_string (GMemoryBuffer *mbuf,
|
||||||
gsize len,
|
gsize len,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar *str;
|
gchar *str;
|
||||||
guchar nul;
|
|
||||||
GError *local_error;
|
|
||||||
const gchar *end_valid;
|
const gchar *end_valid;
|
||||||
gssize num_read;
|
|
||||||
gchar *ptr;
|
|
||||||
|
|
||||||
str = g_malloc (len + 1);
|
if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
|
||||||
|
|
||||||
num_read = g_memory_buffer_read (mbuf,
|
|
||||||
(void **)&ptr,
|
|
||||||
len,
|
|
||||||
error);
|
|
||||||
if (num_read < 0)
|
|
||||||
goto fail;
|
|
||||||
if (num_read < len)
|
|
||||||
{
|
{
|
||||||
|
mbuf->pos = mbuf->valid_len;
|
||||||
/* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
|
/* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
G_IO_ERROR,
|
G_IO_ERROR,
|
||||||
@ -1415,19 +1383,27 @@ read_string (GMemoryBuffer *mbuf,
|
|||||||
"Wanted to read %lu byte but only got %lu",
|
"Wanted to read %lu byte but only got %lu",
|
||||||
(gulong)len),
|
(gulong)len),
|
||||||
(gulong)len,
|
(gulong)len,
|
||||||
(gulong)num_read);
|
(gulong)mbuf->valid_len - mbuf->pos);
|
||||||
goto fail;
|
mbuf->pos = mbuf->valid_len;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (str, ptr, len);
|
if (mbuf->data[mbuf->pos + len] != '\0')
|
||||||
local_error = NULL;
|
|
||||||
nul = g_memory_buffer_read_byte (mbuf, &local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
{
|
||||||
g_propagate_error (error, local_error);
|
str = g_strndup (mbuf->data + mbuf->pos, len);
|
||||||
goto fail;
|
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))
|
if (!g_utf8_validate (str, -1, &end_valid))
|
||||||
{
|
{
|
||||||
gint offset;
|
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). "
|
_("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'"),
|
"The valid UTF-8 string up until that point was `%s'"),
|
||||||
offset,
|
offset,
|
||||||
(gint) num_read,
|
(gint) len,
|
||||||
valid_str);
|
valid_str);
|
||||||
g_free (valid_str);
|
g_free (valid_str);
|
||||||
goto fail;
|
return NULL;
|
||||||
}
|
|
||||||
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 str;
|
return str;
|
||||||
|
|
||||||
fail:
|
|
||||||
g_free (str);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
|
/* 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)
|
if (!just_align)
|
||||||
{
|
{
|
||||||
guint32 len;
|
guint32 len;
|
||||||
gchar *v;
|
const gchar *v;
|
||||||
len = g_memory_buffer_read_uint32 (buf, &local_error);
|
len = g_memory_buffer_read_uint32 (buf, &local_error);
|
||||||
if (local_error != NULL)
|
if (local_error != NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1631,7 +1594,6 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
ret = g_variant_new_string (v);
|
ret = g_variant_new_string (v);
|
||||||
g_free (v);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1641,7 +1603,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
if (!just_align)
|
if (!just_align)
|
||||||
{
|
{
|
||||||
guint32 len;
|
guint32 len;
|
||||||
gchar *v;
|
const gchar *v;
|
||||||
len = g_memory_buffer_read_uint32 (buf, &local_error);
|
len = g_memory_buffer_read_uint32 (buf, &local_error);
|
||||||
if (local_error != NULL)
|
if (local_error != NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1655,11 +1617,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
G_IO_ERROR_INVALID_ARGUMENT,
|
G_IO_ERROR_INVALID_ARGUMENT,
|
||||||
_("Parsed value `%s' is not a valid D-Bus object path"),
|
_("Parsed value `%s' is not a valid D-Bus object path"),
|
||||||
v);
|
v);
|
||||||
g_free (v);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ret = g_variant_new_object_path (v);
|
ret = g_variant_new_object_path (v);
|
||||||
g_free (v);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1667,7 +1627,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
if (!just_align)
|
if (!just_align)
|
||||||
{
|
{
|
||||||
guchar len;
|
guchar len;
|
||||||
gchar *v;
|
const gchar *v;
|
||||||
len = g_memory_buffer_read_byte (buf, &local_error);
|
len = g_memory_buffer_read_byte (buf, &local_error);
|
||||||
if (local_error != NULL)
|
if (local_error != NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1681,11 +1641,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
G_IO_ERROR_INVALID_ARGUMENT,
|
G_IO_ERROR_INVALID_ARGUMENT,
|
||||||
_("Parsed value `%s' is not a valid D-Bus signature"),
|
_("Parsed value `%s' is not a valid D-Bus signature"),
|
||||||
v);
|
v);
|
||||||
g_free (v);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ret = g_variant_new_signature (v);
|
ret = g_variant_new_signature (v);
|
||||||
g_free (v);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1874,7 +1832,7 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
if (!just_align)
|
if (!just_align)
|
||||||
{
|
{
|
||||||
guchar siglen;
|
guchar siglen;
|
||||||
gchar *sig;
|
const gchar *sig;
|
||||||
GVariantType *variant_type;
|
GVariantType *variant_type;
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
|
|
||||||
@ -1891,11 +1849,9 @@ parse_value_from_blob (GMemoryBuffer *buf,
|
|||||||
G_IO_ERROR_INVALID_ARGUMENT,
|
G_IO_ERROR_INVALID_ARGUMENT,
|
||||||
_("Parsed value `%s' for variant is not a valid D-Bus signature"),
|
_("Parsed value `%s' for variant is not a valid D-Bus signature"),
|
||||||
sig);
|
sig);
|
||||||
g_free (sig);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
variant_type = g_variant_type_new (sig);
|
variant_type = g_variant_type_new (sig);
|
||||||
g_free (sig);
|
|
||||||
value = parse_value_from_blob (buf,
|
value = parse_value_from_blob (buf,
|
||||||
variant_type,
|
variant_type,
|
||||||
FALSE,
|
FALSE,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user