Commit 58b18a36 authored by David Schleef's avatar David Schleef
Browse files

Merge gstvalue and gststructure from CAPS branch

Original commit message from CVS:
Merge gstvalue and gststructure from CAPS branch
parent 97383fda
......@@ -601,7 +601,7 @@ gst_structure_remove_all_fields(GstStructure *structure)
* @fieldname: the name of the field
*
* Finds the field with the given name, and returns the type of the
* value it contains. If the field is not found, G_TYPE_NONE is
* value it contains. If the field is not found, G_TYPE_INVALID is
* returned.
*
* Returns: the #GValue of the field
......@@ -611,11 +611,11 @@ gst_structure_get_field_type(const GstStructure *structure, const gchar *fieldna
{
GstStructureField *field;
g_return_val_if_fail(structure != NULL, G_TYPE_NONE);
g_return_val_if_fail(fieldname != NULL, G_TYPE_NONE);
g_return_val_if_fail(structure != NULL, G_TYPE_INVALID);
g_return_val_if_fail(fieldname != NULL, G_TYPE_INVALID);
field = gst_structure_get_field(structure, fieldname);
if(field == NULL) return G_TYPE_NONE;
if(field == NULL) return G_TYPE_INVALID;
return G_VALUE_TYPE(&field->value);
}
......@@ -865,6 +865,67 @@ gst_structure_get_string(const GstStructure *structure, const gchar *fieldname)
return g_value_get_string(&field->value);
}
typedef struct _GstStructureAbbreviation {
char *type_name;
GType type;
} GstStructureAbbreviation;
static GstStructureAbbreviation _gst_structure_abbrs[] = {
{ "int", G_TYPE_INT },
{ "i", G_TYPE_INT },
{ "float", G_TYPE_FLOAT },
{ "f", G_TYPE_FLOAT },
{ "double", G_TYPE_DOUBLE },
{ "d", G_TYPE_DOUBLE },
//{ "fourcc", GST_TYPE_FOURCC },
{ "boolean", G_TYPE_BOOLEAN },
{ "bool", G_TYPE_BOOLEAN },
{ "b", G_TYPE_BOOLEAN },
{ "string", G_TYPE_STRING },
{ "str", G_TYPE_STRING },
{ "s", G_TYPE_STRING }
};
static GType _gst_structure_from_abbr(const char *type_name)
{
int i;
g_return_val_if_fail(type_name != NULL, G_TYPE_INVALID);
for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
if(strcmp(type_name,_gst_structure_abbrs[i].type_name)==0){
return _gst_structure_abbrs[i].type;
}
}
/* FIXME shouldn't be a special case */
if (strcmp (type_name,"fourcc") == 0 || strcmp (type_name, "4") == 0) {
return GST_TYPE_FOURCC;
}
return g_type_from_name (type_name);
}
static const char *_gst_structure_to_abbr(GType type)
{
int i;
g_return_val_if_fail(type != G_TYPE_INVALID, NULL);
for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
if(type == _gst_structure_abbrs[i].type){
return _gst_structure_abbrs[i].type_name;
}
}
/* FIXME shouldn't be a special case */
if (type == GST_TYPE_FOURCC) {
return "fourcc";
}
return g_type_name(type);
}
/**
* gst_structure_to_string:
* @structure: a #GstStructure
......@@ -886,19 +947,377 @@ gst_structure_to_string(const GstStructure *structure)
g_string_append_printf(s, "\"%s\"", g_quark_to_string(structure->name));
for(i=0;i<structure->fields->len;i++){
GValue s_val = { 0 };
GType type;
field = GST_STRUCTURE_FIELD(structure, i);
g_value_init(&s_val, G_TYPE_STRING);
g_value_transform (&field->value, &s_val);
g_value_transform(&field->value, &s_val);
g_string_append_printf(s, ", %s:%s", g_quark_to_string(field->name),
g_value_get_string(&s_val));
g_value_unset(&s_val);
type = G_VALUE_TYPE (&field->value);
if (type == GST_TYPE_LIST) {
GPtrArray *ptr_array = g_value_peek_pointer (&field->value);
if (ptr_array->len > 0){
GValue *value = g_ptr_array_index (ptr_array, 0);
type = G_VALUE_TYPE (value);
} else {
type = G_TYPE_INT;
}
} else if (G_VALUE_TYPE(&field->value) == GST_TYPE_INT_RANGE) {
type = G_TYPE_INT;
} else if (G_VALUE_TYPE(&field->value) == GST_TYPE_DOUBLE_RANGE) {
type = G_TYPE_DOUBLE;
}
g_string_append_printf(s, ", %s:%s=%s", g_quark_to_string(field->name),
_gst_structure_to_abbr(type), g_value_get_string(&s_val));
g_value_unset (&s_val);
}
return g_string_free(s, FALSE);
}
/*
* r will still point to the string. if end == next, the string will not be
* null-terminated. In all other cases it will be.
* end = pointer to char behind end of string, next = pointer to start of
* unread data.
* THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING
*/
static gboolean
_gst_structure_parse_string (gchar *r, gchar **end, gchar **next)
{
gchar *w;
gchar c = '\0';
w = r;
if (*r == '\'' || *r == '\"') {
c = *r;
r++;
}
for (;;r++) {
if (*r == '\0') {
if (c) {
goto error;
} else {
goto found;
}
}
if (*r == '\\') {
r++;
if (*r == '\0')
goto error;
*w++ = *r;
continue;
}
if (*r == c) {
r++;
if (*r == '\0')
goto found;
break;
}
if (!c) {
if (g_ascii_isspace (*r))
break;
/* this needs to be escaped */
if (*r == ',' || *r == ')' || *r == ']' || *r == ':' ||
*r == ';' || *r == '(' || *r == '[')
break;
}
*w++ = *r;
}
found:
while (g_ascii_isspace (*r)) r++;
if (w != r)
*w++ = '\0';
*end = w;
*next = r;
return TRUE;
error:
return FALSE;
}
static gboolean
_gst_structure_parse_value (gchar *s, gchar **after, GType type,
GValue *value)
{
gboolean ret = FALSE;
gchar *val;
gchar *end;
if (type == G_TYPE_INVALID) return FALSE;
while (g_ascii_isspace (*s)) s++;
g_value_init(value, type);
val = s;
switch (type) {
case G_TYPE_INT:
{
int x;
x = strtol (val, &s, 0);
if (val != s) {
g_value_set_int (value, x);
ret = TRUE;
}
}
break;
case G_TYPE_FLOAT:
{
double x;
x = g_ascii_strtod (val, &s);
if (val != s) {
g_value_set_float (value, x);
ret = TRUE;
}
}
break;
case G_TYPE_DOUBLE:
{
double x;
x = g_ascii_strtod (val, &s);
if (val != s) {
g_value_set_double (value, x);
ret = TRUE;
}
}
break;
case G_TYPE_BOOLEAN:
{
int len;
ret = _gst_structure_parse_string (val, &end, &s);
len = end - val;
if (ret && len > 0) {
if (g_ascii_strncasecmp (val, "true", len) == 0 ||
g_ascii_strncasecmp (val, "yes", len) == 0 ||
g_ascii_strncasecmp (val, "t", len) == 0 ||
strncmp (val, "1", len)) {
g_value_set_boolean (value, TRUE);
} else if (g_ascii_strncasecmp (val, "false", len) == 0 ||
g_ascii_strncasecmp (val, "no", len) == 0 ||
g_ascii_strncasecmp (val, "f", len) == 0 ||
strncmp (val, "0", len)) {
g_value_set_boolean (value, FALSE);
} else {
ret = FALSE;
}
}
}
break;
case G_TYPE_STRING:
{
ret = _gst_structure_parse_string (val, &end, &s);
if (ret) {
g_value_set_string_take_ownership (value,
g_strndup(val, end - val));
ret = TRUE;
}
}
break;
default:
/* FIXME: make more general */
if (type == GST_TYPE_FOURCC) {
guint32 fourcc = 0;
if (g_ascii_isdigit (*s)) {
fourcc = strtoul (val, &s, 0);
if (val != s) {
ret = TRUE;
}
} else {
ret = _gst_structure_parse_string (val, &end, &s);
g_print("end - val = %d\n", end - val);
if (end - val >= 4) {
fourcc = GST_MAKE_FOURCC(val[0], val[1], val[2], val[3]);
ret = TRUE;
}
}
gst_value_set_fourcc (value, fourcc);
} else {
g_critical("type %s not handled", g_type_name(type));
}
break;
}
*after = s;
return ret;
}
static gboolean
_gst_structure_parse_range (gchar *s, gchar **after, GType type,
GValue *value)
{
GValue value1 = { 0 };
GValue value2 = { 0 };
GType range_type;
gboolean ret;
if (type == G_TYPE_DOUBLE) {
range_type = GST_TYPE_DOUBLE_RANGE;
} else if (type == G_TYPE_INT) {
range_type = GST_TYPE_INT_RANGE;
} else {
return FALSE;
}
g_print("%d \"%s\"\n", __LINE__, s);
if (*s != '[') return FALSE;
s++;
g_print("%d \"%s\"\n", __LINE__, s);
ret = _gst_structure_parse_value(s, &s, type, &value1);
if (ret == FALSE) return FALSE;
while (g_ascii_isspace (*s)) s++;
g_print("%d \"%s\"\n", __LINE__, s);
if (*s != ',') return FALSE;
s++;
while (g_ascii_isspace (*s)) s++;
g_print("%d \"%s\"\n", __LINE__, s);
ret = _gst_structure_parse_value(s, &s, type, &value2);
if (ret == FALSE) return FALSE;
while (g_ascii_isspace (*s)) s++;
g_print("%d \"%s\"\n", __LINE__, s);
if (*s != ']') return FALSE;
s++;
g_value_init(value, range_type);
if (range_type == GST_TYPE_DOUBLE_RANGE) {
gst_value_set_double_range(value, g_value_get_double(&value1),
g_value_get_double(&value2));
} else {
gst_value_set_int_range(value, g_value_get_int(&value1),
g_value_get_int(&value2));
}
*after = s;
return TRUE;
}
static gboolean
_gst_structure_parse_list (gchar *s, gchar **after, GType type, GValue *value)
{
GValue list_value = { 0 };
gboolean ret;
g_value_init(value, GST_TYPE_LIST);
if (*s != '(') return FALSE;
s++;
while (g_ascii_isspace (*s)) s++;
if (*s == ')') {
s++;
*after = s;
return TRUE;
}
ret = _gst_structure_parse_value(s, &s, type, &list_value);
if (ret == FALSE) return FALSE;
while (g_ascii_isspace (*s)) s++;
while (*s != ')') {
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, type, &list_value);
if (ret == FALSE) return FALSE;
while (g_ascii_isspace (*s)) s++;
}
s++;
*after = s;
return TRUE;
}
static gboolean
_gst_structure_parse_field (gchar *str, gchar **after, GstStructureField *field)
{
/* NAME[:TYPE]=VALUE */
gchar *name;
gchar *type_name;
gchar *s, *del;
gboolean have_type = FALSE;
GType type = G_TYPE_INVALID;
int ret;
g_print("parsing: \"%s\"\n", str);
name = s = str;
while (g_ascii_isalnum (*s) || *s == '_' || *s == '-') s++;
del = s;
while (g_ascii_isspace (*s)) s++;
if (!(*s == '=' || *s == ':')) return FALSE;
if (*s == ':') have_type = TRUE;
s++;
while (g_ascii_isspace (*s)) s++;
*del = '\0';
field->name = g_quark_from_string (name);
if (have_type) {
while (g_ascii_isspace (*s)) s++;
type_name = s;
while (g_ascii_isalnum (*s) || *s == '_' || *s == '-') s++;
del = s;
while (g_ascii_isspace (*s)) s++;
if (*s != '=') return FALSE;
s++;
while (g_ascii_isspace (*s)) s++;
*del = '\0';
g_print("type name is \"%s\"\n",type_name);
type = _gst_structure_from_abbr(type_name);
g_print("type n is \"%s\"\n",g_type_name(type));
if (type == G_TYPE_INVALID) return FALSE;
} else {
if (g_ascii_isdigit (*s) ||
((*s == '-' || *s == '+') && g_ascii_isdigit (s[1]))) {
char *t = s;
while (g_ascii_isdigit (*t)) t++;
if (*t == '.'){
type = G_TYPE_DOUBLE;
} else {
type = G_TYPE_INT;
}
} else if (g_ascii_isalpha (*s) || *s == '"' || *s == '\'') {
type = G_TYPE_STRING;
}
}
if (*s == '[') {
ret = _gst_structure_parse_range (s, &s, type, &field->value);
} else if (*s == '(') {
ret = _gst_structure_parse_list (s, &s, type, &field->value);
} else {
ret = _gst_structure_parse_value(s, &s, type, &field->value);
}
*after = s;
return ret;
}
/**
* gst_structure_from_string:
* @structure: a #GstStructure
......@@ -908,15 +1327,54 @@ gst_structure_to_string(const GstStructure *structure)
* Returns: a new #GstStructure
*/
GstStructure *
gst_structure_from_string (const gchar *string)
gst_structure_from_string (const gchar *string, gchar **end)
{
/* FIXME */
char *name;
char *copy;
char *w;
char *r;
char save;
GstStructure *structure;
GstStructureField field = { 0 };
gboolean res;
g_return_val_if_fail(string != NULL, NULL);
g_assert_not_reached();
copy = g_strdup(string);
r = copy;
return NULL;
name = r;
res = _gst_structure_parse_string (r, &w, &r);
if (!res) return NULL;
while (g_ascii_isspace(*r)) r++;
if(*r != 0 && *r != ';' && *r != ',') return NULL;
save = *w;
*w = 0;
structure = gst_structure_empty_new(name);
*w = save;
while (*r && (*r != ';')){
if(*r != ',') {
return NULL;
}
r++;
while (*r && g_ascii_isspace(*r)) r++;
memset(&field,0,sizeof(field));
res = _gst_structure_parse_field (r, &r, &field);
g_print("returned %d \"%s\"\n", res, r);
if (!res) {
gst_structure_free (structure);
return NULL;
}
gst_structure_set_field(structure, &field);
while (*r && g_ascii_isspace(*r)) r++;
}
if (end) *end = (char *)string + (r - copy);
return structure;
}
static void
......
......@@ -59,7 +59,7 @@ GstStructure *gst_structure_new_valist(const gchar *name,
GstStructure *gst_structure_copy(GstStructure *structure);
void gst_structure_free(GstStructure *structure);
const gchar *gst_structure_get_name(GstStructure *structure);
G_CONST_RETURN gchar *gst_structure_get_name(GstStructure *structure);
void gst_structure_set_name(GstStructure *structure, const gchar *name);
void gst_structure_set_field_copy (GstStructure *structure,
const GstStructureField *field);
......@@ -73,7 +73,8 @@ void gst_structure_set_value(GstStructure *structure, const gchar *field,
void gst_structure_set(GstStructure *structure, const gchar *field, ...);
void gst_structure_set_valist(GstStructure *structure, const gchar *field,
va_list varargs);
const GValue *gst_structure_get_value(const GstStructure *structure, const gchar *field);
G_CONST_RETURN GValue *gst_structure_get_value(const GstStructure *structure,
const gchar *field);
GstStructureField *gst_structure_get_field(const GstStructure *structure,
const gchar *fieldname);
GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
......@@ -100,11 +101,11 @@ gboolean gst_structure_get_fourcc(const GstStructure *structure, const gchar *fi
guint32 *value);
gboolean gst_structure_get_double(const GstStructure *structure, const gchar *field,
gdouble *value);
const gchar *gst_structure_get_string(const GstStructure *structure,
G_CONST_RETURN gchar *gst_structure_get_string(const GstStructure *structure,
const gchar *field);
gchar * gst_structure_to_string(const GstStructure *structure);
GstStructure * gst_structure_from_string (const gchar *string);
GstStructure * gst_structure_from_string (const gchar *string, gchar **end);
G_END_DECLS
......
......@@ -245,7 +245,7 @@ gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
g_return_if_fail (name != NULL);
g_return_if_fail (nick != NULL);
g_return_if_fail (blurb != NULL);
g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
key = g_quark_from_string (name);
info = gst_tag_lookup (key);
......@@ -547,7 +547,7 @@ gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
value = gst_structure_get_value ((GstStructure *) list, tag);
if (value == NULL)
return 0;
if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
return 1;
return gst_value_list_get_size (value);
......@@ -761,7 +761,7 @@ gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
src = gst_structure_get_value ((GstStructure *) list, tag);
if (!src) return FALSE;
if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {
if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
/* must be there or lists aren't allowed */
g_assert (info->merge_func);
......
......@@ -245,7 +245,7 @@ gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
g_return_if_fail (name != NULL);
g_return_if_fail (nick != NULL);
g_return_if_fail (blurb != NULL);
g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
key = g_quark_from_string (name);
info = gst_tag_lookup (key);
......@@ -547,7 +547,7 @@ gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
value = gst_structure_get_value ((GstStructure *) list, tag);
if (value == NULL)
return 0;
if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
return 1;
return gst_value_list_get_size (value);
......@@ -761,7 +761,7 @@ gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
src = gst_structure_get_value ((GstStructure *) list, tag);
if (!src) return FALSE;
if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {
if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
/* must be there or lists aren't allowed */
g_assert (info->merge_func);
......