gststructure: Fix some memory leaks. Sprinkle G_LIKELY/UNLIKELY

Fix some memory leaks shown by the new serialisation/deserialisation unit
test. Split the gst_string_wrap function in gstvalue.c into components and
use them to make gst_string_take_and_wrap, which takes ownership of the
string, avoiding a strdup.

Add some G_LIKELY/UNLIKELY, and clean up some leaks in error paths.
This commit is contained in:
Jan Schmidt 2009-06-05 20:57:05 +01:00
parent 4bb3702886
commit 766e7afc23
2 changed files with 65 additions and 31 deletions

View file

@ -1899,7 +1899,7 @@ gst_structure_parse_value (gchar * str,
type = gst_structure_gtype_from_abbr (type_name); type = gst_structure_gtype_from_abbr (type_name);
*type_end = c; *type_end = c;
if (type == G_TYPE_INVALID) if (G_UNLIKELY (type == G_TYPE_INVALID))
return FALSE; return FALSE;
} }
@ -1913,12 +1913,12 @@ gst_structure_parse_value (gchar * str,
ret = gst_structure_parse_array (s, &s, value, type); ret = gst_structure_parse_array (s, &s, value, type);
} else { } else {
value_s = s; value_s = s;
if (!gst_structure_parse_string (s, &value_end, &s)) if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s)))
return FALSE; return FALSE;
c = *value_end; c = *value_end;
*value_end = '\0'; *value_end = '\0';
if (type == G_TYPE_INVALID) { if (G_UNLIKELY (type == G_TYPE_INVALID)) {
GType try_types[] = GType try_types[] =
{ G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, G_TYPE_BOOLEAN, { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, G_TYPE_BOOLEAN,
G_TYPE_STRING G_TYPE_STRING
@ -1936,6 +1936,8 @@ gst_structure_parse_value (gchar * str,
g_value_init (value, type); g_value_init (value, type);
ret = gst_value_deserialize (value, value_s); ret = gst_value_deserialize (value, value_s);
if (G_UNLIKELY (!ret))
g_value_unset (value);
} }
*value_end = c; *value_end = c;
} }
@ -1989,7 +1991,7 @@ gst_structure_from_string (const gchar * string, gchar ** end)
structure = gst_structure_empty_new (name); structure = gst_structure_empty_new (name);
*w = save; *w = save;
if (structure == NULL) if (G_UNLIKELY (structure == NULL))
goto error; goto error;
do { do {

View file

@ -81,6 +81,7 @@ static gint gst_value_compare_with_func (const GValue * value1,
const GValue * value2, GstValueCompareFunc compare); const GValue * value2, GstValueCompareFunc compare);
static gchar *gst_string_wrap (const gchar * s); static gchar *gst_string_wrap (const gchar * s);
static gchar *gst_string_take_and_wrap (gchar * s);
static gchar *gst_string_unwrap (const gchar * s); static gchar *gst_string_unwrap (const gchar * s);
/******** /********
@ -1338,7 +1339,7 @@ gst_value_serialize_structure (const GValue * value)
{ {
GstStructure *structure = g_value_get_boxed (value); GstStructure *structure = g_value_get_boxed (value);
return gst_string_wrap (gst_structure_to_string (structure)); return gst_string_take_and_wrap (gst_structure_to_string (structure));
} }
static gboolean static gboolean
@ -1351,14 +1352,15 @@ gst_value_deserialize_structure (GValue * dest, const gchar * s)
} else { } else {
gchar *str = gst_string_unwrap (s); gchar *str = gst_string_unwrap (s);
if (!str) if (G_UNLIKELY (!str))
return FALSE; return FALSE;
structure = gst_structure_from_string (str, NULL); structure = gst_structure_from_string (str, NULL);
g_free (str);
} }
if (structure) { if (G_LIKELY (structure)) {
g_value_set_boxed (dest, structure); g_value_take_boxed (dest, structure);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -1789,49 +1791,51 @@ gst_value_compare_string (const GValue * value1, const GValue * value2)
} }
} }
static gchar * static int
gst_string_wrap (const gchar * s) gst_string_measure_wrapping (const gchar * s)
{ {
const gchar *t;
int len; int len;
gchar *d, *e;
gboolean wrap = FALSE; gboolean wrap = FALSE;
if (s == NULL)
return -1;
len = 0; len = 0;
t = s; while (*s) {
if (!s) if (GST_ASCII_IS_STRING (*s)) {
return NULL;
while (*t) {
if (GST_ASCII_IS_STRING (*t)) {
len++; len++;
} else if (*t < 0x20 || *t >= 0x7f) { } else if (*s < 0x20 || *s >= 0x7f) {
wrap = TRUE; wrap = TRUE;
len += 4; len += 4;
} else { } else {
wrap = TRUE; wrap = TRUE;
len += 2; len += 2;
} }
t++; s++;
} }
if (!wrap) return wrap ? len : -1;
return g_strdup (s); }
static gchar *
gst_string_wrap_inner (const gchar * s, int len)
{
gchar *d, *e;
e = d = g_malloc (len + 3); e = d = g_malloc (len + 3);
*e++ = '\"'; *e++ = '\"';
t = s; while (*s) {
while (*t) { if (GST_ASCII_IS_STRING (*s)) {
if (GST_ASCII_IS_STRING (*t)) { *e++ = *s++;
*e++ = *t++; } else if (*s < 0x20 || *s >= 0x7f) {
} else if (*t < 0x20 || *t >= 0x7f) {
*e++ = '\\'; *e++ = '\\';
*e++ = '0' + ((*(guchar *) t) >> 6); *e++ = '0' + ((*(guchar *) s) >> 6);
*e++ = '0' + (((*t) >> 3) & 0x7); *e++ = '0' + (((*s) >> 3) & 0x7);
*e++ = '0' + ((*t++) & 0x7); *e++ = '0' + ((*s++) & 0x7);
} else { } else {
*e++ = '\\'; *e++ = '\\';
*e++ = *t++; *e++ = *s++;
} }
} }
*e++ = '\"'; *e++ = '\"';
@ -1840,6 +1844,34 @@ gst_string_wrap (const gchar * s)
return d; return d;
} }
/* Do string wrapping/escaping */
static gchar *
gst_string_wrap (const gchar * s)
{
int len = gst_string_measure_wrapping (s);
if (len < 0)
return g_strdup (s);
return gst_string_wrap_inner (s, len);
}
/* Same as above, but take ownership of the string */
static gchar *
gst_string_take_and_wrap (gchar * s)
{
gchar *out;
int len = gst_string_measure_wrapping (s);
if (len < 0)
return s;
out = gst_string_wrap_inner (s, len);
g_free (s);
return out;
}
/* /*
* This function takes a string delimited with double quotes (") * This function takes a string delimited with double quotes (")
* and unescapes any \xxx octal numbers. * and unescapes any \xxx octal numbers.
@ -1942,7 +1974,7 @@ gst_value_deserialize_string (GValue * dest, const gchar * s)
} else { } else {
gchar *str = gst_string_unwrap (s); gchar *str = gst_string_unwrap (s);
if (!str) if (G_UNLIKELY (!str))
return FALSE; return FALSE;
g_value_take_string (dest, str); g_value_take_string (dest, str);
} }