structure: fix serialisation of nested structures.
authorStefan Kost <ensonic@users.sf.net>
Tue, 2 Jun 2009 15:36:10 +0000 (18:36 +0300)
committerStefan Kost <ensonic@users.sf.net>
Tue, 2 Jun 2009 15:39:17 +0000 (18:39 +0300)
Use string_warp/unwrap to escape delimiters, otherwise deserialisation fails.
Also move GST_ASCII_IS_STRING to private header to avoid keeping it in sync.
Also use '\0' when terminating a string for better readability.

gst/gst_private.h
gst/gststructure.c
gst/gstvalue.c
tests/check/gst/gststructure.c

index c54bf19dd25e64e07619c83fbada602b4d8f10af..553f7161c83cb4994817220b0c153293c9918e40 100644 (file)
@@ -20,7 +20,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-
 #ifndef __GST_PRIVATE_H__
 #define __GST_PRIVATE_H__
 
@@ -109,6 +108,12 @@ gboolean  priv_gst_structure_append_to_gstring (const GstStructure * structure,
 gboolean               gst_registry_binary_read_cache  (GstRegistry * registry, const char *location);
 gboolean               gst_registry_binary_write_cache (GstRegistry * registry, const char *location);
 
+
+/* used in gstvalue.c and gststructure.c */
+#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
+    ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
+    ((c) == '.'))
+
 /*** debugging categories *****************************************************/
 
 #ifndef GST_DISABLE_GST_DEBUG
index a43b9e7a8c1e2e95faa69cd2c493cf710c2db0c9..e668762006cd581ba7471dce74ed6284c8f67230 100644 (file)
@@ -1560,11 +1560,6 @@ gst_structure_value_get_generic_type (GValue * val)
   return G_VALUE_TYPE (val);
 }
 
-/* keep in sync with gstvalue.c */
-#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
-      ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
-      ((c) == '.'))
-
 gboolean
 priv_gst_structure_append_to_gstring (const GstStructure * structure,
     GString * s)
@@ -1853,7 +1848,7 @@ gst_structure_parse_field (gchar * str,
   s++;
 
   c = *name_end;
-  *name_end = 0;
+  *name_end = '\0';
   field->name = g_quark_from_string (name);
   *name_end = c;
 
@@ -1877,7 +1872,6 @@ gst_structure_parse_value (gchar * str,
   int ret = 0;
   GType type = default_type;
 
-
   s = str;
   while (g_ascii_isspace (*s))
     s++;
@@ -1923,7 +1917,7 @@ gst_structure_parse_value (gchar * str,
       return FALSE;
 
     c = *value_end;
-    *value_end = 0;
+    *value_end = '\0';
     if (type == G_TYPE_INVALID) {
       GType try_types[] =
           { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, G_TYPE_BOOLEAN,
@@ -1991,7 +1985,7 @@ gst_structure_from_string (const gchar * string, gchar ** end)
   }
 
   save = *w;
-  *w = 0;
+  *w = '\0';
   structure = gst_structure_empty_new (name);
   *w = save;
 
@@ -2024,7 +2018,6 @@ gst_structure_from_string (const gchar * string, gchar ** end)
     if (!gst_structure_parse_field (r, &r, &field))
       goto error;
     gst_structure_set_field (structure, &field);
-
   } while (TRUE);
 
   if (end)
index 7286a97c11ed0d20ef953045632da852ba392bbf..8cbb61d406c6231dab3f04678685f4e9495122be 100644 (file)
@@ -80,6 +80,9 @@ static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
 static gint gst_value_compare_with_func (const GValue * value1,
     const GValue * value2, GstValueCompareFunc compare);
 
+static gchar *gst_string_wrap (const gchar * s);
+static gchar *gst_string_unwrap (const gchar * s);
+
 /********
  * list *
  ********/
@@ -1335,7 +1338,7 @@ gst_value_serialize_structure (const GValue * value)
 {
   GstStructure *structure = g_value_get_boxed (value);
 
-  return gst_structure_to_string (structure);
+  return gst_string_wrap (gst_structure_to_string (structure));
 }
 
 static gboolean
@@ -1343,7 +1346,16 @@ gst_value_deserialize_structure (GValue * dest, const gchar * s)
 {
   GstStructure *structure;
 
-  structure = gst_structure_from_string (s, NULL);
+  if (*s != '"') {
+    structure = gst_structure_from_string (s, NULL);
+  } else {
+    gchar *str = gst_string_unwrap (s);
+
+    if (!str)
+      return FALSE;
+
+    structure = gst_structure_from_string (str, NULL);
+  }
 
   if (structure) {
     g_value_set_boxed (dest, structure);
@@ -1777,11 +1789,6 @@ gst_value_compare_string (const GValue * value1, const GValue * value2)
   }
 }
 
-/* keep in sync with gststructure.c */
-#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
-    ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
-    ((c) == '.'))
-
 static gchar *
 gst_string_wrap (const gchar * s)
 {
index e2cf577ff6e059809dcf89ba13c1cb7d4d915dff..3d84057e0050b40db9d3c4758b4c53fb42b3bd83 100644 (file)
@@ -349,30 +349,33 @@ GST_START_TEST (test_structure_nested)
   GstStructure *sp, *sc1, *sc2;
   gchar *str;
 
-  sc1 =
-      gst_structure_new ("Camera", "XResolution", G_TYPE_INT, 72, "YResolution",
-      G_TYPE_INT, 73, NULL);
+  sc1 = gst_structure_new ("Camera",
+      "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL);
   fail_unless (sc1 != NULL);
 
-  sc2 =
-      gst_structure_new ("Image-Data", "Orientation", G_TYPE_STRING, "top-left",
-      NULL);
+  sc2 = gst_structure_new ("Image-Data",
+      "Orientation", G_TYPE_STRING, "top-left",
+      "Comment", G_TYPE_STRING, "super photo", NULL);
   fail_unless (sc2 != NULL);
 
   sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
       "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
   fail_unless (sp != NULL);
 
+  fail_unless (gst_structure_n_fields (sp) == 2);
+
   fail_unless (gst_structure_has_field_typed (sp, "Camera",
           GST_TYPE_STRUCTURE));
 
   str = gst_structure_to_string (sp);
   fail_unless (str != NULL);
 
+  GST_DEBUG ("serialized to '%s'", str);
+
   fail_unless (g_str_equal (str,
           "Exif"
-          ", Camera=(structure)Camera, XResolution=(int)72, YResolution=(int)73;"
-          ", Image Data=(structure)Image-Data, Orientation=(string)top-left;;"));
+          ", Camera=(structure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\""
+          ", Image Data=(structure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";"));
 
   g_free (str);
   str = NULL;
@@ -380,7 +383,40 @@ GST_START_TEST (test_structure_nested)
   gst_structure_free (sc1);
   gst_structure_free (sc2);
   gst_structure_free (sp);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_structure_nested_from_and_to_string)
+{
+  GstStructure *s;
+  gchar *str1, *str2, *end = NULL;
+
+  str1 = "main"
+      ", main-sub1=(structure)\"type-b\\,\\ machine-type\\=\\(int\\)0\\;\""
+      ", main-sub2=(structure)\"type-a\\,\\ plugin-filename\\=\\(string\\)\\\"/home/user/lib/lib\\\\\\ with\\\\\\ spaces.dll\\\"\\,\\ machine-type\\=\\(int\\)1\\;\""
+      ", main-sub3=(structure)\"type-b\\,\\ plugin-filename\\=\\(string\\)/home/user/lib/lib_no_spaces.so\\,\\ machine-type\\=\\(int\\)1\\;\""
+      ";";
 
+  s = gst_structure_from_string (str1, &end);
+  fail_unless (s != NULL);
+
+  GST_DEBUG ("not parsed part : %s", end);
+  fail_unless (*end == '\0');
+
+  fail_unless (gst_structure_n_fields (s) == 3);
+
+  fail_unless (gst_structure_has_field_typed (s, "main-sub1",
+          GST_TYPE_STRUCTURE));
+
+  str2 = gst_structure_to_string (s);
+  fail_unless (str2 != NULL);
+
+  fail_unless (g_str_equal (str1, str2));
+
+  g_free (str2);
+
+  gst_structure_free (s);
 }
 
 GST_END_TEST;
@@ -413,6 +449,7 @@ gst_structure_suite (void)
   tcase_add_test (tc_chain, test_fixate);
   tcase_add_test (tc_chain, test_fixate_frac_list);
   tcase_add_test (tc_chain, test_structure_nested);
+  tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
   tcase_add_test (tc_chain, test_empty_string_fields);
   return s;
 }