mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 18:20:44 +00:00
value: Move list/array serialization/deserialization functions from GstStructure to GstValue
https://bugzilla.gnome.org/show_bug.cgi?id=777375
This commit is contained in:
parent
978df5d0ff
commit
33118f6118
3 changed files with 515 additions and 497 deletions
|
@ -150,6 +150,15 @@ G_GNUC_INTERNAL GstPlugin * _priv_gst_plugin_load_file_for_registry (const gcha
|
||||||
GstRegistry * registry,
|
GstRegistry * registry,
|
||||||
GError** error);
|
GError** error);
|
||||||
|
|
||||||
|
/* GValue serialization/deserialization */
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL const char * _priv_gst_value_gtype_to_abbr (GType type);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL gboolean _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next, gboolean unescape);
|
||||||
|
G_GNUC_INTERNAL gboolean _priv_gst_value_parse_simple_string (gchar * str, gchar ** end);
|
||||||
|
G_GNUC_INTERNAL gboolean _priv_gst_value_parse_value (gchar * str, gchar ** after, GValue * value, GType default_type);
|
||||||
|
G_GNUC_INTERNAL gchar * _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin, const gchar * end);
|
||||||
|
|
||||||
/* Used in GstBin for manual state handling */
|
/* Used in GstBin for manual state handling */
|
||||||
G_GNUC_INTERNAL void _priv_gst_element_state_changed (GstElement *element,
|
G_GNUC_INTERNAL void _priv_gst_element_state_changed (GstElement *element,
|
||||||
GstState oldstate, GstState newstate, GstState pending);
|
GstState oldstate, GstState newstate, GstState pending);
|
||||||
|
|
|
@ -116,9 +116,6 @@ static void gst_structure_transform_to_string (const GValue * src_value,
|
||||||
GValue * dest_value);
|
GValue * dest_value);
|
||||||
static GstStructure *gst_structure_copy_conditional (const GstStructure *
|
static GstStructure *gst_structure_copy_conditional (const GstStructure *
|
||||||
structure);
|
structure);
|
||||||
static gboolean gst_structure_parse_value (gchar * str, gchar ** after,
|
|
||||||
GValue * value, GType default_type);
|
|
||||||
static gboolean gst_structure_parse_simple_string (gchar * s, gchar ** end);
|
|
||||||
|
|
||||||
GType _gst_structure_type = 0;
|
GType _gst_structure_type = 0;
|
||||||
|
|
||||||
|
@ -1760,130 +1757,6 @@ gst_structure_get_flagset (const GstStructure * structure,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _GstStructureAbbreviation
|
|
||||||
{
|
|
||||||
const gchar *type_name;
|
|
||||||
GType type;
|
|
||||||
}
|
|
||||||
GstStructureAbbreviation;
|
|
||||||
|
|
||||||
/* return a copy of an array of GstStructureAbbreviation containing all the
|
|
||||||
* known type_string, GType maps, including abbreviations for common types */
|
|
||||||
static GstStructureAbbreviation *
|
|
||||||
gst_structure_get_abbrs (gint * n_abbrs)
|
|
||||||
{
|
|
||||||
static GstStructureAbbreviation *abbrs = NULL;
|
|
||||||
static volatile gsize num = 0;
|
|
||||||
|
|
||||||
if (g_once_init_enter (&num)) {
|
|
||||||
/* dynamically generate the array */
|
|
||||||
gsize _num;
|
|
||||||
GstStructureAbbreviation dyn_abbrs[] = {
|
|
||||||
{"int", G_TYPE_INT}
|
|
||||||
,
|
|
||||||
{"i", G_TYPE_INT}
|
|
||||||
,
|
|
||||||
{"uint", G_TYPE_UINT}
|
|
||||||
,
|
|
||||||
{"u", G_TYPE_UINT}
|
|
||||||
,
|
|
||||||
{"float", G_TYPE_FLOAT}
|
|
||||||
,
|
|
||||||
{"f", G_TYPE_FLOAT}
|
|
||||||
,
|
|
||||||
{"double", G_TYPE_DOUBLE}
|
|
||||||
,
|
|
||||||
{"d", G_TYPE_DOUBLE}
|
|
||||||
,
|
|
||||||
{"buffer", GST_TYPE_BUFFER}
|
|
||||||
,
|
|
||||||
{"fraction", GST_TYPE_FRACTION}
|
|
||||||
,
|
|
||||||
{"boolean", G_TYPE_BOOLEAN}
|
|
||||||
,
|
|
||||||
{"bool", G_TYPE_BOOLEAN}
|
|
||||||
,
|
|
||||||
{"b", G_TYPE_BOOLEAN}
|
|
||||||
,
|
|
||||||
{"string", G_TYPE_STRING}
|
|
||||||
,
|
|
||||||
{"str", G_TYPE_STRING}
|
|
||||||
,
|
|
||||||
{"s", G_TYPE_STRING}
|
|
||||||
,
|
|
||||||
{"structure", GST_TYPE_STRUCTURE}
|
|
||||||
,
|
|
||||||
{"date", G_TYPE_DATE}
|
|
||||||
,
|
|
||||||
{"datetime", GST_TYPE_DATE_TIME}
|
|
||||||
,
|
|
||||||
{"bitmask", GST_TYPE_BITMASK}
|
|
||||||
,
|
|
||||||
{"sample", GST_TYPE_SAMPLE}
|
|
||||||
,
|
|
||||||
{"taglist", GST_TYPE_TAG_LIST}
|
|
||||||
,
|
|
||||||
{"type", G_TYPE_GTYPE}
|
|
||||||
};
|
|
||||||
_num = G_N_ELEMENTS (dyn_abbrs);
|
|
||||||
/* permanently allocate and copy the array now */
|
|
||||||
abbrs = g_new0 (GstStructureAbbreviation, _num);
|
|
||||||
memcpy (abbrs, dyn_abbrs, sizeof (GstStructureAbbreviation) * _num);
|
|
||||||
g_once_init_leave (&num, _num);
|
|
||||||
}
|
|
||||||
*n_abbrs = num;
|
|
||||||
|
|
||||||
return abbrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* given a type_name that could be a type abbreviation or a registered GType,
|
|
||||||
* return a matching GType */
|
|
||||||
static GType
|
|
||||||
gst_structure_gtype_from_abbr (const char *type_name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GstStructureAbbreviation *abbrs;
|
|
||||||
gint n_abbrs;
|
|
||||||
GType ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
|
|
||||||
|
|
||||||
abbrs = gst_structure_get_abbrs (&n_abbrs);
|
|
||||||
|
|
||||||
for (i = 0; i < n_abbrs; i++) {
|
|
||||||
if (strcmp (type_name, abbrs[i].type_name) == 0) {
|
|
||||||
return abbrs[i].type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this is the fallback */
|
|
||||||
ret = g_type_from_name (type_name);
|
|
||||||
/* If not found, try it as a dynamic type */
|
|
||||||
if (G_UNLIKELY (ret == 0))
|
|
||||||
ret = gst_dynamic_type_factory_load (type_name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
gst_structure_to_abbr (GType type)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GstStructureAbbreviation *abbrs;
|
|
||||||
gint n_abbrs;
|
|
||||||
|
|
||||||
g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
|
|
||||||
|
|
||||||
abbrs = gst_structure_get_abbrs (&n_abbrs);
|
|
||||||
|
|
||||||
for (i = 0; i < n_abbrs; i++) {
|
|
||||||
if (type == abbrs[i].type) {
|
|
||||||
return abbrs[i].type_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_type_name (type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
static GType
|
||||||
gst_structure_value_get_generic_type (const GValue * val)
|
gst_structure_value_get_generic_type (const GValue * val)
|
||||||
{
|
{
|
||||||
|
@ -1933,14 +1806,15 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
|
||||||
/* FIXME: do we need to escape fieldnames? */
|
/* FIXME: do we need to escape fieldnames? */
|
||||||
g_string_append (s, g_quark_to_string (field->name));
|
g_string_append (s, g_quark_to_string (field->name));
|
||||||
g_string_append_len (s, "=(", 2);
|
g_string_append_len (s, "=(", 2);
|
||||||
g_string_append (s, gst_structure_to_abbr (type));
|
g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
|
||||||
g_string_append_c (s, ')');
|
g_string_append_c (s, ')');
|
||||||
if (t) {
|
if (t) {
|
||||||
g_string_append (s, t);
|
g_string_append (s, t);
|
||||||
g_free (t);
|
g_free (t);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
|
GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
|
||||||
g_quark_to_string (field->name), gst_structure_to_abbr (type));
|
g_quark_to_string (field->name),
|
||||||
|
_priv_gst_value_gtype_to_abbr (type));
|
||||||
g_string_append (s, "NULL");
|
g_string_append (s, "NULL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1960,7 +1834,7 @@ priv__gst_structure_append_template_to_gstring (GQuark field_id,
|
||||||
/* FIXME: do we need to escape fieldnames? */
|
/* FIXME: do we need to escape fieldnames? */
|
||||||
g_string_append (s, g_quark_to_string (field_id));
|
g_string_append (s, g_quark_to_string (field_id));
|
||||||
g_string_append_len (s, "=(", 2);
|
g_string_append_len (s, "=(", 2);
|
||||||
g_string_append (s, gst_structure_to_abbr (type));
|
g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
|
||||||
g_string_append_c (s, ')');
|
g_string_append_c (s, ')');
|
||||||
|
|
||||||
//TODO(ensonic): table like GstStructureAbbreviation (or extend it)
|
//TODO(ensonic): table like GstStructureAbbreviation (or extend it)
|
||||||
|
@ -2039,266 +1913,6 @@ gst_structure_to_string (const GstStructure * structure)
|
||||||
return g_string_free (s, FALSE);
|
return g_string_free (s, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* gst_structure_parse_string:
|
|
||||||
* @s: string to parse
|
|
||||||
* @end: out-pointer to char behind end of string
|
|
||||||
* @next: out-pointer to start of unread data
|
|
||||||
* @unescape: @TRUE if the substring is escaped.
|
|
||||||
*
|
|
||||||
* Find the end of a sub-string. If end == next, the string will not be
|
|
||||||
* null-terminated. In all other cases it will be.
|
|
||||||
*
|
|
||||||
* Note: This function modifies the string in @s (if unescape == @TRUE).
|
|
||||||
*
|
|
||||||
* Returns: @TRUE if a sub-string was found and @FALSE if the string is not
|
|
||||||
* terminated.
|
|
||||||
*/
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
|
|
||||||
gboolean unescape)
|
|
||||||
{
|
|
||||||
gchar *w;
|
|
||||||
|
|
||||||
if (*s == 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (*s != '"') {
|
|
||||||
int ret = gst_structure_parse_simple_string (s, end);
|
|
||||||
*next = *end;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the closing quotes */
|
|
||||||
if (unescape) {
|
|
||||||
w = s;
|
|
||||||
s++;
|
|
||||||
while (*s != '"') {
|
|
||||||
if (G_UNLIKELY (*s == 0))
|
|
||||||
return FALSE;
|
|
||||||
if (G_UNLIKELY (*s == '\\')) {
|
|
||||||
s++;
|
|
||||||
if (G_UNLIKELY (*s == 0))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
*w = *s;
|
|
||||||
w++;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
} else {
|
|
||||||
s++;
|
|
||||||
while (*s != '"') {
|
|
||||||
if (G_UNLIKELY (*s == 0))
|
|
||||||
return FALSE;
|
|
||||||
if (G_UNLIKELY (*s == '\\')) {
|
|
||||||
s++;
|
|
||||||
if (G_UNLIKELY (*s == 0))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
w = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
*end = w;
|
|
||||||
*next = s;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
|
|
||||||
GType type)
|
|
||||||
{
|
|
||||||
GValue value1 = { 0 };
|
|
||||||
GValue value2 = { 0 };
|
|
||||||
GValue value3 = { 0 };
|
|
||||||
GType range_type;
|
|
||||||
gboolean ret, have_step = FALSE;
|
|
||||||
|
|
||||||
if (*s != '[')
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
|
|
||||||
ret = gst_structure_parse_value (s, &s, &value1, type);
|
|
||||||
if (!ret)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
if (*s != ',')
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
ret = gst_structure_parse_value (s, &s, &value2, type);
|
|
||||||
if (!ret)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
/* optional step for int and int64 */
|
|
||||||
if (G_VALUE_TYPE (&value1) == G_TYPE_INT
|
|
||||||
|| G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
|
|
||||||
if (*s == ',') {
|
|
||||||
s++;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
ret = gst_structure_parse_value (s, &s, &value3, type);
|
|
||||||
if (!ret)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
have_step = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*s != ']')
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
|
|
||||||
if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
|
|
||||||
return FALSE;
|
|
||||||
if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
|
|
||||||
range_type = GST_TYPE_DOUBLE_RANGE;
|
|
||||||
g_value_init (value, range_type);
|
|
||||||
gst_value_set_double_range (value,
|
|
||||||
gst_g_value_get_double_unchecked (&value1),
|
|
||||||
gst_g_value_get_double_unchecked (&value2));
|
|
||||||
} else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
|
|
||||||
range_type = GST_TYPE_INT_RANGE;
|
|
||||||
g_value_init (value, range_type);
|
|
||||||
if (have_step)
|
|
||||||
gst_value_set_int_range_step (value,
|
|
||||||
gst_g_value_get_int_unchecked (&value1),
|
|
||||||
gst_g_value_get_int_unchecked (&value2),
|
|
||||||
gst_g_value_get_int_unchecked (&value3));
|
|
||||||
else
|
|
||||||
gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
|
|
||||||
gst_g_value_get_int_unchecked (&value2));
|
|
||||||
} else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
|
|
||||||
range_type = GST_TYPE_INT64_RANGE;
|
|
||||||
g_value_init (value, range_type);
|
|
||||||
if (have_step)
|
|
||||||
gst_value_set_int64_range_step (value,
|
|
||||||
gst_g_value_get_int64_unchecked (&value1),
|
|
||||||
gst_g_value_get_int64_unchecked (&value2),
|
|
||||||
gst_g_value_get_int64_unchecked (&value3));
|
|
||||||
else
|
|
||||||
gst_value_set_int64_range (value,
|
|
||||||
gst_g_value_get_int64_unchecked (&value1),
|
|
||||||
gst_g_value_get_int64_unchecked (&value2));
|
|
||||||
} else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
|
|
||||||
range_type = GST_TYPE_FRACTION_RANGE;
|
|
||||||
g_value_init (value, range_type);
|
|
||||||
gst_value_set_fraction_range (value, &value1, &value2);
|
|
||||||
} else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*after = s;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_any_list (gchar * s, gchar ** after, GValue * value,
|
|
||||||
GType type, GType list_type, char begin, char end)
|
|
||||||
{
|
|
||||||
GValue list_value = { 0 };
|
|
||||||
gboolean ret;
|
|
||||||
GArray *array;
|
|
||||||
|
|
||||||
g_value_init (value, list_type);
|
|
||||||
array = g_value_peek_pointer (value);
|
|
||||||
|
|
||||||
if (*s != begin)
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
if (*s == end) {
|
|
||||||
s++;
|
|
||||||
*after = s;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = gst_structure_parse_value (s, &s, &list_value, type);
|
|
||||||
if (!ret)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
g_array_append_val (array, list_value);
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
while (*s != end) {
|
|
||||||
if (*s != ',')
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
memset (&list_value, 0, sizeof (list_value));
|
|
||||||
ret = gst_structure_parse_value (s, &s, &list_value, type);
|
|
||||||
if (!ret)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
g_array_append_val (array, list_value);
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
s++;
|
|
||||||
|
|
||||||
*after = s;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_list (gchar * s, gchar ** after, GValue * value, GType type)
|
|
||||||
{
|
|
||||||
return gst_structure_parse_any_list (s, after, value, type, GST_TYPE_LIST,
|
|
||||||
'{', '}');
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_array (gchar * s, gchar ** after, GValue * value,
|
|
||||||
GType type)
|
|
||||||
{
|
|
||||||
return gst_structure_parse_any_list (s, after, value, type,
|
|
||||||
GST_TYPE_ARRAY, '<', '>');
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_simple_string (gchar * str, gchar ** end)
|
|
||||||
{
|
|
||||||
char *s = str;
|
|
||||||
|
|
||||||
while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*end = s;
|
|
||||||
|
|
||||||
return (s != str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_structure_parse_field (gchar * str,
|
gst_structure_parse_field (gchar * str,
|
||||||
gchar ** after, GstStructureField * field)
|
gchar ** after, GstStructureField * field)
|
||||||
|
@ -2313,7 +1927,7 @@ gst_structure_parse_field (gchar * str,
|
||||||
while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
|
while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
|
||||||
s++;
|
s++;
|
||||||
name = s;
|
name = s;
|
||||||
if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &name_end))) {
|
if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &name_end))) {
|
||||||
GST_WARNING ("failed to parse simple string, str=%s", str);
|
GST_WARNING ("failed to parse simple string, str=%s", str);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2334,7 +1948,7 @@ gst_structure_parse_field (gchar * str,
|
||||||
GST_DEBUG ("trying field name '%s'", name);
|
GST_DEBUG ("trying field name '%s'", name);
|
||||||
*name_end = c;
|
*name_end = c;
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_structure_parse_value (s, &s, &field->value,
|
if (G_UNLIKELY (!_priv_gst_value_parse_value (s, &s, &field->value,
|
||||||
G_TYPE_INVALID))) {
|
G_TYPE_INVALID))) {
|
||||||
GST_WARNING ("failed to parse value %s", str);
|
GST_WARNING ("failed to parse value %s", str);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2344,106 +1958,6 @@ gst_structure_parse_field (gchar * str,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_structure_parse_value (gchar * str,
|
|
||||||
gchar ** after, GValue * value, GType default_type)
|
|
||||||
{
|
|
||||||
gchar *type_name;
|
|
||||||
gchar *type_end;
|
|
||||||
gchar *value_s;
|
|
||||||
gchar *value_end;
|
|
||||||
gchar *s;
|
|
||||||
gchar c;
|
|
||||||
int ret = 0;
|
|
||||||
GType type = default_type;
|
|
||||||
|
|
||||||
s = str;
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
/* check if there's a (type_name) 'cast' */
|
|
||||||
type_name = NULL;
|
|
||||||
if (*s == '(') {
|
|
||||||
s++;
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
type_name = s;
|
|
||||||
if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &type_end)))
|
|
||||||
return FALSE;
|
|
||||||
s = type_end;
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
if (G_UNLIKELY (*s != ')'))
|
|
||||||
return FALSE;
|
|
||||||
s++;
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
c = *type_end;
|
|
||||||
*type_end = 0;
|
|
||||||
type = gst_structure_gtype_from_abbr (type_name);
|
|
||||||
GST_DEBUG ("trying type name '%s'", type_name);
|
|
||||||
*type_end = c;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (type == G_TYPE_INVALID)) {
|
|
||||||
GST_WARNING ("invalid type");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (g_ascii_isspace (*s))
|
|
||||||
s++;
|
|
||||||
if (*s == '[') {
|
|
||||||
ret = gst_structure_parse_range (s, &s, value, type);
|
|
||||||
} else if (*s == '{') {
|
|
||||||
ret = gst_structure_parse_list (s, &s, value, type);
|
|
||||||
} else if (*s == '<') {
|
|
||||||
ret = gst_structure_parse_array (s, &s, value, type);
|
|
||||||
} else {
|
|
||||||
value_s = s;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (type == G_TYPE_INVALID)) {
|
|
||||||
GType try_types[] =
|
|
||||||
{ G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
|
|
||||||
G_TYPE_BOOLEAN, G_TYPE_STRING
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s, TRUE)))
|
|
||||||
return FALSE;
|
|
||||||
/* Set NULL terminator for deserialization */
|
|
||||||
c = *value_end;
|
|
||||||
*value_end = '\0';
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
|
|
||||||
g_value_init (value, try_types[i]);
|
|
||||||
ret = gst_value_deserialize (value, value_s);
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
g_value_unset (value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g_value_init (value, type);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s,
|
|
||||||
(type != G_TYPE_STRING))))
|
|
||||||
return FALSE;
|
|
||||||
/* Set NULL terminator for deserialization */
|
|
||||||
c = *value_end;
|
|
||||||
*value_end = '\0';
|
|
||||||
|
|
||||||
ret = gst_value_deserialize (value, value_s);
|
|
||||||
if (G_UNLIKELY (!ret))
|
|
||||||
g_value_unset (value);
|
|
||||||
}
|
|
||||||
*value_end = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
*after = s;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
|
priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
|
||||||
gchar ** next)
|
gchar ** next)
|
||||||
|
@ -2460,7 +1974,7 @@ priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
|
||||||
|
|
||||||
*start = r;
|
*start = r;
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_structure_parse_string (r, &w, &r, TRUE))) {
|
if (G_UNLIKELY (!_priv_gst_value_parse_string (r, &w, &r, TRUE))) {
|
||||||
GST_WARNING ("Failed to parse structure string '%s'", str);
|
GST_WARNING ("Failed to parse structure string '%s'", str);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
503
gst/gstvalue.c
503
gst/gstvalue.c
|
@ -96,6 +96,9 @@ static void gst_value_register_intersect_func (GType type1,
|
||||||
static void gst_value_register_subtract_func (GType minuend_type,
|
static void gst_value_register_subtract_func (GType minuend_type,
|
||||||
GType subtrahend_type, GstValueSubtractFunc func);
|
GType subtrahend_type, GstValueSubtractFunc func);
|
||||||
|
|
||||||
|
static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after,
|
||||||
|
GValue * value, GType type);
|
||||||
|
|
||||||
typedef struct _GstValueUnionInfo GstValueUnionInfo;
|
typedef struct _GstValueUnionInfo GstValueUnionInfo;
|
||||||
struct _GstValueUnionInfo
|
struct _GstValueUnionInfo
|
||||||
{
|
{
|
||||||
|
@ -128,6 +131,14 @@ struct _GstFlagSetClass
|
||||||
|
|
||||||
typedef struct _GstFlagSetClass GstFlagSetClass;
|
typedef struct _GstFlagSetClass GstFlagSetClass;
|
||||||
|
|
||||||
|
typedef struct _GstValueAbbreviation GstValueAbbreviation;
|
||||||
|
|
||||||
|
struct _GstValueAbbreviation
|
||||||
|
{
|
||||||
|
const gchar *type_name;
|
||||||
|
GType type;
|
||||||
|
};
|
||||||
|
|
||||||
#define FUNDAMENTAL_TYPE_ID_MAX \
|
#define FUNDAMENTAL_TYPE_ID_MAX \
|
||||||
(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
|
(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
|
||||||
#define FUNDAMENTAL_TYPE_ID(type) \
|
#define FUNDAMENTAL_TYPE_ID(type) \
|
||||||
|
@ -185,8 +196,8 @@ gst_value_hash_add_type (GType type, const GstValueTable * table)
|
||||||
/* two helper functions to serialize/stringify any type of list
|
/* two helper functions to serialize/stringify any type of list
|
||||||
* regular lists are done with { }, arrays with < >
|
* regular lists are done with { }, arrays with < >
|
||||||
*/
|
*/
|
||||||
static gchar *
|
gchar *
|
||||||
gst_value_serialize_any_list (const GValue * value, const gchar * begin,
|
_priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin,
|
||||||
const gchar * end)
|
const gchar * end)
|
||||||
{
|
{
|
||||||
guint i;
|
guint i;
|
||||||
|
@ -1025,7 +1036,7 @@ gst_value_compare_g_value_array (const GValue * value1, const GValue * value2)
|
||||||
static gchar *
|
static gchar *
|
||||||
gst_value_serialize_value_list (const GValue * value)
|
gst_value_serialize_value_list (const GValue * value)
|
||||||
{
|
{
|
||||||
return gst_value_serialize_any_list (value, "{ ", " }");
|
return _priv_gst_value_serialize_any_list (value, "{ ", " }");
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1038,7 +1049,7 @@ gst_value_deserialize_value_list (GValue * dest, const gchar * s)
|
||||||
static gchar *
|
static gchar *
|
||||||
gst_value_serialize_value_array (const GValue * value)
|
gst_value_serialize_value_array (const GValue * value)
|
||||||
{
|
{
|
||||||
return gst_value_serialize_any_list (value, "< ", " >");
|
return _priv_gst_value_serialize_any_list (value, "< ", " >");
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -2063,6 +2074,490 @@ gst_value_deserialize_caps (GValue * dest, const gchar * s)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************
|
||||||
|
* Serialization/deserialization of GValues *
|
||||||
|
********************************************/
|
||||||
|
|
||||||
|
static GstValueAbbreviation *
|
||||||
|
_priv_gst_value_get_abbrs (gint * n_abbrs)
|
||||||
|
{
|
||||||
|
static GstValueAbbreviation *abbrs = NULL;
|
||||||
|
static volatile gsize num = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&num)) {
|
||||||
|
/* dynamically generate the array */
|
||||||
|
gsize _num;
|
||||||
|
GstValueAbbreviation dyn_abbrs[] = {
|
||||||
|
{"int", G_TYPE_INT}
|
||||||
|
,
|
||||||
|
{"i", G_TYPE_INT}
|
||||||
|
,
|
||||||
|
{"uint", G_TYPE_UINT}
|
||||||
|
,
|
||||||
|
{"u", G_TYPE_UINT}
|
||||||
|
,
|
||||||
|
{"float", G_TYPE_FLOAT}
|
||||||
|
,
|
||||||
|
{"f", G_TYPE_FLOAT}
|
||||||
|
,
|
||||||
|
{"double", G_TYPE_DOUBLE}
|
||||||
|
,
|
||||||
|
{"d", G_TYPE_DOUBLE}
|
||||||
|
,
|
||||||
|
{"buffer", GST_TYPE_BUFFER}
|
||||||
|
,
|
||||||
|
{"fraction", GST_TYPE_FRACTION}
|
||||||
|
,
|
||||||
|
{"boolean", G_TYPE_BOOLEAN}
|
||||||
|
,
|
||||||
|
{"bool", G_TYPE_BOOLEAN}
|
||||||
|
,
|
||||||
|
{"b", G_TYPE_BOOLEAN}
|
||||||
|
,
|
||||||
|
{"string", G_TYPE_STRING}
|
||||||
|
,
|
||||||
|
{"str", G_TYPE_STRING}
|
||||||
|
,
|
||||||
|
{"s", G_TYPE_STRING}
|
||||||
|
,
|
||||||
|
{"structure", GST_TYPE_STRUCTURE}
|
||||||
|
,
|
||||||
|
{"date", G_TYPE_DATE}
|
||||||
|
,
|
||||||
|
{"datetime", GST_TYPE_DATE_TIME}
|
||||||
|
,
|
||||||
|
{"bitmask", GST_TYPE_BITMASK}
|
||||||
|
,
|
||||||
|
{"sample", GST_TYPE_SAMPLE}
|
||||||
|
,
|
||||||
|
{"taglist", GST_TYPE_TAG_LIST}
|
||||||
|
,
|
||||||
|
{"type", G_TYPE_GTYPE}
|
||||||
|
,
|
||||||
|
{"array", GST_TYPE_ARRAY}
|
||||||
|
,
|
||||||
|
{"list", GST_TYPE_LIST}
|
||||||
|
};
|
||||||
|
_num = G_N_ELEMENTS (dyn_abbrs);
|
||||||
|
/* permanently allocate and copy the array now */
|
||||||
|
abbrs = g_new0 (GstValueAbbreviation, _num);
|
||||||
|
memcpy (abbrs, dyn_abbrs, sizeof (GstValueAbbreviation) * _num);
|
||||||
|
g_once_init_leave (&num, _num);
|
||||||
|
}
|
||||||
|
*n_abbrs = num;
|
||||||
|
|
||||||
|
return abbrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* given a type_name that could be a type abbreviation or a registered GType,
|
||||||
|
* return a matching GType */
|
||||||
|
static GType
|
||||||
|
_priv_gst_value_gtype_from_abbr (const char *type_name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GstValueAbbreviation *abbrs;
|
||||||
|
gint n_abbrs;
|
||||||
|
GType ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
|
||||||
|
|
||||||
|
abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
|
||||||
|
|
||||||
|
for (i = 0; i < n_abbrs; i++) {
|
||||||
|
if (strcmp (type_name, abbrs[i].type_name) == 0) {
|
||||||
|
return abbrs[i].type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is the fallback */
|
||||||
|
ret = g_type_from_name (type_name);
|
||||||
|
/* If not found, try it as a dynamic type */
|
||||||
|
if (G_UNLIKELY (ret == 0))
|
||||||
|
ret = gst_dynamic_type_factory_load (type_name);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_priv_gst_value_gtype_to_abbr (GType type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GstValueAbbreviation *abbrs;
|
||||||
|
gint n_abbrs;
|
||||||
|
|
||||||
|
g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
|
||||||
|
|
||||||
|
abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
|
||||||
|
|
||||||
|
for (i = 0; i < n_abbrs; i++) {
|
||||||
|
if (type == abbrs[i].type) {
|
||||||
|
return abbrs[i].type_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_type_name (type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _priv_gst_value_parse_string:
|
||||||
|
* @s: string to parse
|
||||||
|
* @end: out-pointer to char behind end of string
|
||||||
|
* @next: out-pointer to start of unread data
|
||||||
|
* @unescape: @TRUE if the substring is escaped.
|
||||||
|
*
|
||||||
|
* Find the end of a sub-string. If end == next, the string will not be
|
||||||
|
* null-terminated. In all other cases it will be.
|
||||||
|
*
|
||||||
|
* Note: This function modifies the string in @s (if unescape == @TRUE).
|
||||||
|
*
|
||||||
|
* Returns: @TRUE if a sub-string was found and @FALSE if the string is not
|
||||||
|
* terminated.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
_priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next,
|
||||||
|
gboolean unescape)
|
||||||
|
{
|
||||||
|
gchar *w;
|
||||||
|
|
||||||
|
if (*s == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*s != '"') {
|
||||||
|
int ret = _priv_gst_value_parse_simple_string (s, end);
|
||||||
|
*next = *end;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the closing quotes */
|
||||||
|
if (unescape) {
|
||||||
|
w = s;
|
||||||
|
s++;
|
||||||
|
while (*s != '"') {
|
||||||
|
if (G_UNLIKELY (*s == 0))
|
||||||
|
return FALSE;
|
||||||
|
if (G_UNLIKELY (*s == '\\')) {
|
||||||
|
s++;
|
||||||
|
if (G_UNLIKELY (*s == 0))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*w = *s;
|
||||||
|
w++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
} else {
|
||||||
|
s++;
|
||||||
|
while (*s != '"') {
|
||||||
|
if (G_UNLIKELY (*s == 0))
|
||||||
|
return FALSE;
|
||||||
|
if (G_UNLIKELY (*s == '\\')) {
|
||||||
|
s++;
|
||||||
|
if (G_UNLIKELY (*s == 0))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
w = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
*end = w;
|
||||||
|
*next = s;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
|
||||||
|
GType type)
|
||||||
|
{
|
||||||
|
GValue value1 = { 0 };
|
||||||
|
GValue value2 = { 0 };
|
||||||
|
GValue value3 = { 0 };
|
||||||
|
GType range_type;
|
||||||
|
gboolean ret, have_step = FALSE;
|
||||||
|
|
||||||
|
if (*s != '[')
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
ret = _priv_gst_value_parse_value (s, &s, &value1, type);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
if (*s != ',')
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
ret = _priv_gst_value_parse_value (s, &s, &value2, type);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
/* optional step for int and int64 */
|
||||||
|
if (G_VALUE_TYPE (&value1) == G_TYPE_INT
|
||||||
|
|| G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
|
||||||
|
if (*s == ',') {
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
ret = _priv_gst_value_parse_value (s, &s, &value3, type);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
have_step = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s != ']')
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
|
||||||
|
return FALSE;
|
||||||
|
if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
|
||||||
|
range_type = GST_TYPE_DOUBLE_RANGE;
|
||||||
|
g_value_init (value, range_type);
|
||||||
|
gst_value_set_double_range (value,
|
||||||
|
gst_g_value_get_double_unchecked (&value1),
|
||||||
|
gst_g_value_get_double_unchecked (&value2));
|
||||||
|
} else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
|
||||||
|
range_type = GST_TYPE_INT_RANGE;
|
||||||
|
g_value_init (value, range_type);
|
||||||
|
if (have_step)
|
||||||
|
gst_value_set_int_range_step (value,
|
||||||
|
gst_g_value_get_int_unchecked (&value1),
|
||||||
|
gst_g_value_get_int_unchecked (&value2),
|
||||||
|
gst_g_value_get_int_unchecked (&value3));
|
||||||
|
else
|
||||||
|
gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
|
||||||
|
gst_g_value_get_int_unchecked (&value2));
|
||||||
|
} else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
|
||||||
|
range_type = GST_TYPE_INT64_RANGE;
|
||||||
|
g_value_init (value, range_type);
|
||||||
|
if (have_step)
|
||||||
|
gst_value_set_int64_range_step (value,
|
||||||
|
gst_g_value_get_int64_unchecked (&value1),
|
||||||
|
gst_g_value_get_int64_unchecked (&value2),
|
||||||
|
gst_g_value_get_int64_unchecked (&value3));
|
||||||
|
else
|
||||||
|
gst_value_set_int64_range (value,
|
||||||
|
gst_g_value_get_int64_unchecked (&value1),
|
||||||
|
gst_g_value_get_int64_unchecked (&value2));
|
||||||
|
} else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
|
||||||
|
range_type = GST_TYPE_FRACTION_RANGE;
|
||||||
|
g_value_init (value, range_type);
|
||||||
|
gst_value_set_fraction_range (value, &value1, &value2);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*after = s;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
|
||||||
|
GType type, char begin, char end)
|
||||||
|
{
|
||||||
|
GValue list_value = { 0 };
|
||||||
|
gboolean ret;
|
||||||
|
GArray *array;
|
||||||
|
|
||||||
|
array = g_value_peek_pointer (value);
|
||||||
|
|
||||||
|
if (*s != begin)
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
if (*s == end) {
|
||||||
|
s++;
|
||||||
|
*after = s;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_array_append_val (array, list_value);
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (*s != end) {
|
||||||
|
if (*s != ',')
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
memset (&list_value, 0, sizeof (list_value));
|
||||||
|
ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_array_append_val (array, list_value);
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
s++;
|
||||||
|
|
||||||
|
*after = s;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value,
|
||||||
|
GType type)
|
||||||
|
{
|
||||||
|
return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value,
|
||||||
|
GType type)
|
||||||
|
{
|
||||||
|
return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>');
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_priv_gst_value_parse_simple_string (gchar * str, gchar ** end)
|
||||||
|
{
|
||||||
|
char *s = str;
|
||||||
|
|
||||||
|
while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*end = s;
|
||||||
|
|
||||||
|
return (s != str);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_priv_gst_value_parse_value (gchar * str,
|
||||||
|
gchar ** after, GValue * value, GType default_type)
|
||||||
|
{
|
||||||
|
gchar *type_name;
|
||||||
|
gchar *type_end;
|
||||||
|
gchar *value_s;
|
||||||
|
gchar *value_end;
|
||||||
|
gchar *s;
|
||||||
|
gchar c;
|
||||||
|
int ret = 0;
|
||||||
|
GType type = default_type;
|
||||||
|
|
||||||
|
s = str;
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
/* check if there's a (type_name) 'cast' */
|
||||||
|
type_name = NULL;
|
||||||
|
if (*s == '(') {
|
||||||
|
s++;
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
type_name = s;
|
||||||
|
if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &type_end)))
|
||||||
|
return FALSE;
|
||||||
|
s = type_end;
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
if (G_UNLIKELY (*s != ')'))
|
||||||
|
return FALSE;
|
||||||
|
s++;
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
|
||||||
|
c = *type_end;
|
||||||
|
*type_end = 0;
|
||||||
|
type = _priv_gst_value_gtype_from_abbr (type_name);
|
||||||
|
GST_DEBUG ("trying type name '%s'", type_name);
|
||||||
|
*type_end = c;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (type == G_TYPE_INVALID)) {
|
||||||
|
GST_WARNING ("invalid type");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g_ascii_isspace (*s))
|
||||||
|
s++;
|
||||||
|
if (*s == '[') {
|
||||||
|
ret = _priv_gst_value_parse_range (s, &s, value, type);
|
||||||
|
} else if (*s == '{') {
|
||||||
|
g_value_init (value, GST_TYPE_LIST);
|
||||||
|
ret = _priv_gst_value_parse_list (s, &s, value, type);
|
||||||
|
} else if (*s == '<') {
|
||||||
|
g_value_init (value, GST_TYPE_ARRAY);
|
||||||
|
ret = _priv_gst_value_parse_array (s, &s, value, type);
|
||||||
|
} else {
|
||||||
|
value_s = s;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (type == G_TYPE_INVALID)) {
|
||||||
|
GType try_types[] =
|
||||||
|
{ G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
|
||||||
|
G_TYPE_BOOLEAN, G_TYPE_STRING
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE)))
|
||||||
|
return FALSE;
|
||||||
|
/* Set NULL terminator for deserialization */
|
||||||
|
c = *value_end;
|
||||||
|
*value_end = '\0';
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
|
||||||
|
g_value_init (value, try_types[i]);
|
||||||
|
ret = gst_value_deserialize (value, value_s);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
g_value_unset (value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_value_init (value, type);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s,
|
||||||
|
(type != G_TYPE_STRING))))
|
||||||
|
return FALSE;
|
||||||
|
/* Set NULL terminator for deserialization */
|
||||||
|
c = *value_end;
|
||||||
|
*value_end = '\0';
|
||||||
|
|
||||||
|
ret = gst_value_deserialize (value, value_s);
|
||||||
|
if (G_UNLIKELY (!ret))
|
||||||
|
g_value_unset (value);
|
||||||
|
}
|
||||||
|
*value_end = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
*after = s;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**************
|
/**************
|
||||||
* GstSegment *
|
* GstSegment *
|
||||||
**************/
|
**************/
|
||||||
|
|
Loading…
Reference in a new issue