From f25668a223d2c2d33411dfbd0ea359d13ee53102 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 13 Feb 2025 09:54:43 -0500 Subject: [PATCH] gststructure: Fix deserialization of GStrv Part-of: --- girs/Gst-1.0.gir | 3 ++ subprojects/gstreamer/gst/gststructure.c | 3 ++ subprojects/gstreamer/gst/gstvalue.c | 39 ++++++++++++++----- .../gstreamer/tests/check/gst/gststructure.c | 26 +++++++++++++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/girs/Gst-1.0.gir b/girs/Gst-1.0.gir index 30ae84187e..010c4430f2 100644 --- a/girs/Gst-1.0.gir +++ b/girs/Gst-1.0.gir @@ -42701,6 +42701,9 @@ Some types have special delimiters: `a-structure, a-int64-range=(gint64) [1, 5]` - [GstValueList](GST_TYPE_LIST) are inside curly brackets (`{` and `}`). For example `a-structure, list={1, 2, 3}` +- [GStrv](G_TYPE_STRV) are inside "less and greater than" (`<` and + `>`) and each string is double-quoted. + For example `a-structure, strv=(GStrv)<"foo", "bar">`. Since 1.26.0. Structures are delimited either by a null character `\0` or a semicolon `;` the latter allowing to store multiple structures in the same string (see diff --git a/subprojects/gstreamer/gst/gststructure.c b/subprojects/gstreamer/gst/gststructure.c index e0494f052d..c2f80b4302 100644 --- a/subprojects/gstreamer/gst/gststructure.c +++ b/subprojects/gstreamer/gst/gststructure.c @@ -98,6 +98,9 @@ * `a-structure, a-int64-range=(gint64) [1, 5]` * - [GstValueList](GST_TYPE_LIST) are inside curly brackets (`{` and `}`). * For example `a-structure, list={1, 2, 3}` + * - [GStrv](G_TYPE_STRV) are inside "less and greater than" (`<` and + * `>`) and each string is double-quoted. + * For example `a-structure, strv=(GStrv)<"foo", "bar">`. Since 1.26.0. * * Structures are delimited either by a null character `\0` or a semicolon `;` * the latter allowing to store multiple structures in the same string (see diff --git a/subprojects/gstreamer/gst/gstvalue.c b/subprojects/gstreamer/gst/gstvalue.c index 11804a4d1d..e99ed745a2 100644 --- a/subprojects/gstreamer/gst/gstvalue.c +++ b/subprojects/gstreamer/gst/gstvalue.c @@ -100,6 +100,8 @@ static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value, GType type, GParamSpec * pspec); static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value, GType type, GParamSpec * pspec); +static gboolean _priv_gst_value_parse_strv (const gchar * s, + const gchar ** after, GValue * dest); typedef struct _GstValueUnionInfo GstValueUnionInfo; struct _GstValueUnionInfo @@ -2811,8 +2813,13 @@ _priv_gst_value_parse_value (gchar * str, g_value_init (value, GST_TYPE_LIST); ret = _priv_gst_value_parse_list (s, &s, value, type, pspec); } else if (*s == '<') { - g_value_init (value, GST_TYPE_ARRAY); - ret = _priv_gst_value_parse_array (s, &s, value, type, pspec); + if (type == G_TYPE_STRV) { + g_value_init (value, G_TYPE_STRV); + ret = _priv_gst_value_parse_strv (s, (const gchar **) &s, value); + } else { + g_value_init (value, GST_TYPE_ARRAY); + ret = _priv_gst_value_parse_array (s, &s, value, type, pspec); + } } else { value_s = s; @@ -8171,15 +8178,13 @@ gst_value_serialize_strv (const GValue * value) } static gboolean -gst_value_deserialize_strv (GValue * dest, const gchar * s) +_priv_gst_value_parse_strv (const gchar * s, const gchar ** after, + GValue * dest) { - /* If it's not starting with '<' assume it's a simple comma separated list - * with no escaping. Otherwise assume the format <"foo","bar"> with spaces - * allowed between delimiters and \ for escaping. */ - if (*s != '<') { - g_value_take_boxed (dest, g_strsplit (s, ",", -1)); - return TRUE; - } + /* Parse the format <"foo","bar"> with spaces allowed between delimiters, + * and \ for escaping. */ + if (*s != '<') + return FALSE; s++; while (g_ascii_isspace (*s)) @@ -8235,6 +8240,8 @@ gst_value_deserialize_strv (GValue * dest, const gchar * s) g_ptr_array_add (strv, NULL); g_value_take_boxed (dest, g_ptr_array_free (strv, FALSE)); + *after = s + 1; + return TRUE; error: @@ -8242,6 +8249,18 @@ error: return FALSE; } +static gboolean +gst_value_deserialize_strv (GValue * dest, const gchar * s) +{ + /* If it's not starting with '<' assume it's a simple comma separated list + * with no escaping. This makes usage in gst-launch-1.0 easier. */ + if (*s != '<') { + g_value_take_boxed (dest, g_strsplit (s, ",", -1)); + return TRUE; + } + return _priv_gst_value_parse_strv (s, &s, dest); +} + static GTypeInfo _info = { 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL, }; diff --git a/subprojects/gstreamer/tests/check/gst/gststructure.c b/subprojects/gstreamer/tests/check/gst/gststructure.c index 961f205c77..bcc54b14ca 100644 --- a/subprojects/gstreamer/tests/check/gst/gststructure.c +++ b/subprojects/gstreamer/tests/check/gst/gststructure.c @@ -1169,6 +1169,31 @@ GST_START_TEST (test_strict) GST_END_TEST; +GST_START_TEST (test_strv) +{ + GstStructure *s; + const gchar *strv[] = { "foo", " ,<>\" ", NULL }; + + s = gst_structure_new ("test-struct", "strv", G_TYPE_STRV, strv, NULL); + fail_unless (s); + + gchar *serialized = gst_structure_serialize_full (s, GST_SERIALIZE_FLAG_NONE); + fail_unless (serialized); + gst_structure_free (s); + + s = gst_structure_new_from_string (serialized); + fail_unless (s); + g_free (serialized); + + gchar **out_strv = NULL; + fail_unless (gst_structure_get (s, "strv", G_TYPE_STRV, &out_strv, NULL)); + fail_unless (g_strv_equal (strv, (const gchar * const *) out_strv)); + gst_structure_free (s); + g_strfreev (out_strv); +} + +GST_END_TEST; + static Suite * gst_structure_suite (void) { @@ -1203,6 +1228,7 @@ gst_structure_suite (void) tcase_add_test (tc_chain, test_flagset); tcase_add_test (tc_chain, test_flags); tcase_add_test (tc_chain, test_strict); + tcase_add_test (tc_chain, test_strv); return s; }