mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-10 12:55:48 +01:00
back out change by mitch@convergence.de and apply patch in bug id #52067
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com> * gmarkup.c: back out change by mitch@convergence.de and apply patch in bug id #52067 that fixes the same problem in a more complete manner. This fixes also a segfault for a malformed XML file and adds a new test case.
This commit is contained in:
parent
cd759bbd6e
commit
477106292a
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 24 21:24:16 CEST 2001 Paolo Molaro <lupus@ximian.com>
|
||||||
|
|
||||||
|
* gmarkup.c: back out change by mitch@convergence.de and apply patch in
|
||||||
|
bug id #52067 that fixes the same problem in a more complete manner.
|
||||||
|
This fixes also a segfault for a malformed XML file and adds a new
|
||||||
|
test case.
|
||||||
|
|
||||||
2001-05-24 Hans Breuer <hans@breuer.org>
|
2001-05-24 Hans Breuer <hans@breuer.org>
|
||||||
|
|
||||||
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
* grel.c : reflect renaming of g_string_sprintfa to g_string_printfa
|
||||||
|
201
glib/gmarkup.c
201
glib/gmarkup.c
@ -38,36 +38,6 @@ g_markup_error_quark ()
|
|||||||
return error_quark;
|
return error_quark;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _GMarkupAttribute GMarkupAttribute;
|
|
||||||
|
|
||||||
struct _GMarkupAttribute
|
|
||||||
{
|
|
||||||
gchar *name;
|
|
||||||
gchar *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GMarkupAttribute*
|
|
||||||
attribute_new (const gchar *name, const gchar *value)
|
|
||||||
{
|
|
||||||
GMarkupAttribute *attr;
|
|
||||||
|
|
||||||
attr = g_new (GMarkupAttribute, 1);
|
|
||||||
|
|
||||||
/* name/value are allowed to be NULL */
|
|
||||||
attr->name = g_strdup (name);
|
|
||||||
attr->value = g_strdup (value);
|
|
||||||
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
attribute_free (GMarkupAttribute *attr)
|
|
||||||
{
|
|
||||||
g_free (attr->name);
|
|
||||||
g_free (attr->value);
|
|
||||||
g_free (attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
STATE_START,
|
STATE_START,
|
||||||
@ -106,7 +76,10 @@ struct _GMarkupParseContext
|
|||||||
|
|
||||||
GMarkupParseState state;
|
GMarkupParseState state;
|
||||||
GSList *tag_stack;
|
GSList *tag_stack;
|
||||||
GSList *attributes;
|
gchar **attr_names;
|
||||||
|
gchar **attr_values;
|
||||||
|
gint cur_attr;
|
||||||
|
gint alloc_attrs;
|
||||||
|
|
||||||
const gchar *current_text;
|
const gchar *current_text;
|
||||||
gint current_text_len;
|
gint current_text_len;
|
||||||
@ -162,7 +135,10 @@ g_markup_parse_context_new (const GMarkupParser *parser,
|
|||||||
|
|
||||||
context->state = STATE_START;
|
context->state = STATE_START;
|
||||||
context->tag_stack = NULL;
|
context->tag_stack = NULL;
|
||||||
context->attributes = NULL;
|
context->attr_names = NULL;
|
||||||
|
context->attr_values = NULL;
|
||||||
|
context->cur_attr = -1;
|
||||||
|
context->alloc_attrs = 0;
|
||||||
|
|
||||||
context->current_text = NULL;
|
context->current_text = NULL;
|
||||||
context->current_text_len = -1;
|
context->current_text_len = -1;
|
||||||
@ -195,8 +171,8 @@ g_markup_parse_context_free (GMarkupParseContext *context)
|
|||||||
if (context->dnotify)
|
if (context->dnotify)
|
||||||
(* context->dnotify) (context->user_data);
|
(* context->dnotify) (context->user_data);
|
||||||
|
|
||||||
g_slist_foreach (context->attributes, (GFunc)attribute_free, NULL);
|
g_strfreev (context->attr_names);
|
||||||
g_slist_free (context->attributes);
|
g_strfreev (context->attr_values);
|
||||||
|
|
||||||
g_slist_foreach (context->tag_stack, (GFunc)g_free, NULL);
|
g_slist_foreach (context->tag_stack, (GFunc)g_free, NULL);
|
||||||
g_slist_free (context->tag_stack);
|
g_slist_free (context->tag_stack);
|
||||||
@ -210,68 +186,6 @@ g_markup_parse_context_free (GMarkupParseContext *context)
|
|||||||
g_free (context);
|
g_free (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
attribute_list_to_arrays (GSList *attributes,
|
|
||||||
gchar ***namesp,
|
|
||||||
gchar ***valuesp,
|
|
||||||
gint *n_attributes)
|
|
||||||
{
|
|
||||||
GSList *tmp_list;
|
|
||||||
gint len;
|
|
||||||
gchar **names;
|
|
||||||
gchar **values;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
len = g_slist_length (attributes);
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
{
|
|
||||||
names = g_new (gchar*, len + 1);
|
|
||||||
names[len] = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
names = NULL;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
{
|
|
||||||
values = g_new (gchar*, len + 1);
|
|
||||||
values[len] = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
values = NULL;
|
|
||||||
|
|
||||||
/* We want to reverse the list, since it's
|
|
||||||
* backward from the order the attributes appeared
|
|
||||||
* in the file.
|
|
||||||
*/
|
|
||||||
i = len - 1;
|
|
||||||
tmp_list = attributes;
|
|
||||||
while (tmp_list)
|
|
||||||
{
|
|
||||||
GMarkupAttribute *attr = tmp_list->data;
|
|
||||||
|
|
||||||
g_assert (i >= 0);
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
names[i] = attr->name;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
values[i] = attr->value;
|
|
||||||
|
|
||||||
tmp_list = g_slist_next (tmp_list);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_attributes)
|
|
||||||
*n_attributes = len;
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
*namesp = names;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
*valuesp = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mark_error (GMarkupParseContext *context,
|
mark_error (GMarkupParseContext *context,
|
||||||
GError *error)
|
GError *error)
|
||||||
@ -748,12 +662,11 @@ add_to_partial (GMarkupParseContext *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_partial (GMarkupParseContext *context)
|
truncate_partial (GMarkupParseContext *context)
|
||||||
{
|
{
|
||||||
if (context->partial_chunk != NULL)
|
if (context->partial_chunk != NULL)
|
||||||
{
|
{
|
||||||
g_string_free (context->partial_chunk, TRUE);
|
context->partial_chunk = g_string_truncate (context->partial_chunk, 0);
|
||||||
context->partial_chunk = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,7 +679,8 @@ current_element (GMarkupParseContext *context)
|
|||||||
static const gchar*
|
static const gchar*
|
||||||
current_attribute (GMarkupParseContext *context)
|
current_attribute (GMarkupParseContext *context)
|
||||||
{
|
{
|
||||||
return ((GMarkupAttribute*)context->attributes->data)->name;
|
g_assert (context->cur_attr >= 0);
|
||||||
|
return context->attr_names[context->cur_attr];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -806,6 +720,21 @@ find_current_text_end (GMarkupParseContext *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_attribute (GMarkupParseContext *context, char *name)
|
||||||
|
{
|
||||||
|
if (context->cur_attr + 2 >= context->alloc_attrs)
|
||||||
|
{
|
||||||
|
context->alloc_attrs += 5; /* silly magic number */
|
||||||
|
context->attr_names = g_realloc (context->attr_names, sizeof(char*)*context->alloc_attrs);
|
||||||
|
context->attr_values = g_realloc (context->attr_values, sizeof(char*)*context->alloc_attrs);
|
||||||
|
}
|
||||||
|
context->cur_attr++;
|
||||||
|
context->attr_names[context->cur_attr] = name;
|
||||||
|
context->attr_values[context->cur_attr] = NULL;
|
||||||
|
context->attr_names[context->cur_attr+1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_markup_parse_context_parse:
|
* g_markup_parse_context_parse:
|
||||||
* @context: a #GMarkupParseContext
|
* @context: a #GMarkupParseContext
|
||||||
@ -1073,10 +1002,6 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
g_free (context->tag_stack->data);
|
|
||||||
context->tag_stack = g_slist_delete_link (context->tag_stack,
|
|
||||||
context->tag_stack);
|
|
||||||
|
|
||||||
if (tmp_error)
|
if (tmp_error)
|
||||||
{
|
{
|
||||||
mark_error (context, tmp_error);
|
mark_error (context, tmp_error);
|
||||||
@ -1102,6 +1027,10 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
current_element (context));
|
current_element (context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (context->tag_stack->data);
|
||||||
|
context->tag_stack = g_slist_delete_link (context->tag_stack,
|
||||||
|
context->tag_stack);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1161,20 +1090,13 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
/* The name has ended. Combine it with the partial chunk
|
/* The name has ended. Combine it with the partial chunk
|
||||||
* if any; push it on the stack; enter next state.
|
* if any; push it on the stack; enter next state.
|
||||||
*/
|
*/
|
||||||
GMarkupAttribute *attr;
|
|
||||||
add_to_partial (context, context->start, context->iter);
|
add_to_partial (context, context->start, context->iter);
|
||||||
|
|
||||||
attr = attribute_new (NULL, NULL);
|
add_attribute (context, g_string_free (context->partial_chunk, FALSE));
|
||||||
|
|
||||||
attr->name = g_string_free (context->partial_chunk,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
context->partial_chunk = NULL;
|
context->partial_chunk = NULL;
|
||||||
context->start = NULL;
|
context->start = NULL;
|
||||||
|
|
||||||
context->attributes =
|
|
||||||
g_slist_prepend (context->attributes, attr);
|
|
||||||
|
|
||||||
if (*context->iter == '=')
|
if (*context->iter == '=')
|
||||||
{
|
{
|
||||||
advance_char (context);
|
advance_char (context);
|
||||||
@ -1189,7 +1111,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
_("Odd character '%s', expected a '=' after "
|
_("Odd character '%s', expected a '=' after "
|
||||||
"attribute name '%s' of element '%s'"),
|
"attribute name '%s' of element '%s'"),
|
||||||
utf8_str (context->iter, buf),
|
utf8_str (context->iter, buf),
|
||||||
attr->name,
|
current_attribute (context),
|
||||||
current_element (context));
|
current_element (context));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1243,17 +1165,20 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->state == STATE_AFTER_CLOSE_ANGLE)
|
context->state == STATE_AFTER_CLOSE_ANGLE)
|
||||||
{
|
{
|
||||||
const gchar *start_name;
|
const gchar *start_name;
|
||||||
gchar **attr_names = NULL;
|
/* Ugly, but the current code expects an empty array instead of NULL */
|
||||||
gchar **attr_values = NULL;
|
const gchar *empty = NULL;
|
||||||
|
const gchar **attr_names = ∅
|
||||||
|
const gchar **attr_values = ∅
|
||||||
GError *tmp_error;
|
GError *tmp_error;
|
||||||
|
|
||||||
/* Call user callback for element start */
|
/* Call user callback for element start */
|
||||||
start_name = current_element (context);
|
start_name = current_element (context);
|
||||||
|
|
||||||
attribute_list_to_arrays (context->attributes,
|
if (context->cur_attr >= 0)
|
||||||
&attr_names,
|
{
|
||||||
&attr_values,
|
attr_names = (const gchar**)context->attr_names;
|
||||||
NULL);
|
attr_values = (const gchar**)context->attr_values;
|
||||||
|
}
|
||||||
|
|
||||||
tmp_error = NULL;
|
tmp_error = NULL;
|
||||||
if (context->parser->start_element)
|
if (context->parser->start_element)
|
||||||
@ -1264,17 +1189,15 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
/* Free only the string arrays, as we didn't g_strdup() the attribute
|
/* Go ahead and free the attributes. */
|
||||||
* list's strings
|
for (; context->cur_attr >= 0; context->cur_attr--)
|
||||||
*/
|
{
|
||||||
g_free (attr_names);
|
int pos = context->cur_attr;
|
||||||
g_free (attr_values);
|
g_free (context->attr_names[pos]);
|
||||||
|
g_free (context->attr_values[pos]);
|
||||||
/* Go ahead and free this. */
|
context->attr_names[pos] = context->attr_values[pos] = NULL;
|
||||||
g_slist_foreach (context->attributes, (GFunc)attribute_free,
|
}
|
||||||
NULL);
|
context->cur_attr = -1;
|
||||||
g_slist_free (context->attributes);
|
|
||||||
context->attributes = NULL;
|
|
||||||
|
|
||||||
if (tmp_error != NULL)
|
if (tmp_error != NULL)
|
||||||
{
|
{
|
||||||
@ -1330,17 +1253,15 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
* with the partial chunk if any; set it for the current
|
* with the partial chunk if any; set it for the current
|
||||||
* attribute.
|
* attribute.
|
||||||
*/
|
*/
|
||||||
GMarkupAttribute *attr;
|
|
||||||
|
|
||||||
add_to_partial (context, context->start, context->iter);
|
add_to_partial (context, context->start, context->iter);
|
||||||
|
|
||||||
attr = context->attributes->data;
|
g_assert (context->cur_attr >= 0);
|
||||||
|
|
||||||
if (unescape_text (context,
|
if (unescape_text (context,
|
||||||
context->partial_chunk->str,
|
context->partial_chunk->str,
|
||||||
context->partial_chunk->str +
|
context->partial_chunk->str +
|
||||||
context->partial_chunk->len,
|
context->partial_chunk->len,
|
||||||
&attr->value,
|
&context->attr_values[context->cur_attr],
|
||||||
error))
|
error))
|
||||||
{
|
{
|
||||||
/* success, advance past quote and set state. */
|
/* success, advance past quote and set state. */
|
||||||
@ -1349,7 +1270,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->start = NULL;
|
context->start = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1409,7 +1330,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1558,7 +1479,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
|
|
||||||
if (tmp_error == NULL)
|
if (tmp_error == NULL)
|
||||||
{
|
{
|
||||||
@ -1609,6 +1530,12 @@ g_markup_parse_context_end_parse (GMarkupParseContext *context,
|
|||||||
g_return_val_if_fail (!context->parsing, FALSE);
|
g_return_val_if_fail (!context->parsing, FALSE);
|
||||||
g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
|
g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
|
||||||
|
|
||||||
|
if (context->partial_chunk != NULL)
|
||||||
|
{
|
||||||
|
g_string_free (context->partial_chunk, TRUE);
|
||||||
|
context->partial_chunk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (context->document_empty)
|
if (context->document_empty)
|
||||||
{
|
{
|
||||||
set_error (context, error, G_MARKUP_ERROR_EMPTY,
|
set_error (context, error, G_MARKUP_ERROR_EMPTY,
|
||||||
|
201
gmarkup.c
201
gmarkup.c
@ -38,36 +38,6 @@ g_markup_error_quark ()
|
|||||||
return error_quark;
|
return error_quark;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _GMarkupAttribute GMarkupAttribute;
|
|
||||||
|
|
||||||
struct _GMarkupAttribute
|
|
||||||
{
|
|
||||||
gchar *name;
|
|
||||||
gchar *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GMarkupAttribute*
|
|
||||||
attribute_new (const gchar *name, const gchar *value)
|
|
||||||
{
|
|
||||||
GMarkupAttribute *attr;
|
|
||||||
|
|
||||||
attr = g_new (GMarkupAttribute, 1);
|
|
||||||
|
|
||||||
/* name/value are allowed to be NULL */
|
|
||||||
attr->name = g_strdup (name);
|
|
||||||
attr->value = g_strdup (value);
|
|
||||||
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
attribute_free (GMarkupAttribute *attr)
|
|
||||||
{
|
|
||||||
g_free (attr->name);
|
|
||||||
g_free (attr->value);
|
|
||||||
g_free (attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
STATE_START,
|
STATE_START,
|
||||||
@ -106,7 +76,10 @@ struct _GMarkupParseContext
|
|||||||
|
|
||||||
GMarkupParseState state;
|
GMarkupParseState state;
|
||||||
GSList *tag_stack;
|
GSList *tag_stack;
|
||||||
GSList *attributes;
|
gchar **attr_names;
|
||||||
|
gchar **attr_values;
|
||||||
|
gint cur_attr;
|
||||||
|
gint alloc_attrs;
|
||||||
|
|
||||||
const gchar *current_text;
|
const gchar *current_text;
|
||||||
gint current_text_len;
|
gint current_text_len;
|
||||||
@ -162,7 +135,10 @@ g_markup_parse_context_new (const GMarkupParser *parser,
|
|||||||
|
|
||||||
context->state = STATE_START;
|
context->state = STATE_START;
|
||||||
context->tag_stack = NULL;
|
context->tag_stack = NULL;
|
||||||
context->attributes = NULL;
|
context->attr_names = NULL;
|
||||||
|
context->attr_values = NULL;
|
||||||
|
context->cur_attr = -1;
|
||||||
|
context->alloc_attrs = 0;
|
||||||
|
|
||||||
context->current_text = NULL;
|
context->current_text = NULL;
|
||||||
context->current_text_len = -1;
|
context->current_text_len = -1;
|
||||||
@ -195,8 +171,8 @@ g_markup_parse_context_free (GMarkupParseContext *context)
|
|||||||
if (context->dnotify)
|
if (context->dnotify)
|
||||||
(* context->dnotify) (context->user_data);
|
(* context->dnotify) (context->user_data);
|
||||||
|
|
||||||
g_slist_foreach (context->attributes, (GFunc)attribute_free, NULL);
|
g_strfreev (context->attr_names);
|
||||||
g_slist_free (context->attributes);
|
g_strfreev (context->attr_values);
|
||||||
|
|
||||||
g_slist_foreach (context->tag_stack, (GFunc)g_free, NULL);
|
g_slist_foreach (context->tag_stack, (GFunc)g_free, NULL);
|
||||||
g_slist_free (context->tag_stack);
|
g_slist_free (context->tag_stack);
|
||||||
@ -210,68 +186,6 @@ g_markup_parse_context_free (GMarkupParseContext *context)
|
|||||||
g_free (context);
|
g_free (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
attribute_list_to_arrays (GSList *attributes,
|
|
||||||
gchar ***namesp,
|
|
||||||
gchar ***valuesp,
|
|
||||||
gint *n_attributes)
|
|
||||||
{
|
|
||||||
GSList *tmp_list;
|
|
||||||
gint len;
|
|
||||||
gchar **names;
|
|
||||||
gchar **values;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
len = g_slist_length (attributes);
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
{
|
|
||||||
names = g_new (gchar*, len + 1);
|
|
||||||
names[len] = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
names = NULL;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
{
|
|
||||||
values = g_new (gchar*, len + 1);
|
|
||||||
values[len] = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
values = NULL;
|
|
||||||
|
|
||||||
/* We want to reverse the list, since it's
|
|
||||||
* backward from the order the attributes appeared
|
|
||||||
* in the file.
|
|
||||||
*/
|
|
||||||
i = len - 1;
|
|
||||||
tmp_list = attributes;
|
|
||||||
while (tmp_list)
|
|
||||||
{
|
|
||||||
GMarkupAttribute *attr = tmp_list->data;
|
|
||||||
|
|
||||||
g_assert (i >= 0);
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
names[i] = attr->name;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
values[i] = attr->value;
|
|
||||||
|
|
||||||
tmp_list = g_slist_next (tmp_list);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_attributes)
|
|
||||||
*n_attributes = len;
|
|
||||||
|
|
||||||
if (namesp)
|
|
||||||
*namesp = names;
|
|
||||||
|
|
||||||
if (valuesp)
|
|
||||||
*valuesp = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mark_error (GMarkupParseContext *context,
|
mark_error (GMarkupParseContext *context,
|
||||||
GError *error)
|
GError *error)
|
||||||
@ -748,12 +662,11 @@ add_to_partial (GMarkupParseContext *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_partial (GMarkupParseContext *context)
|
truncate_partial (GMarkupParseContext *context)
|
||||||
{
|
{
|
||||||
if (context->partial_chunk != NULL)
|
if (context->partial_chunk != NULL)
|
||||||
{
|
{
|
||||||
g_string_free (context->partial_chunk, TRUE);
|
context->partial_chunk = g_string_truncate (context->partial_chunk, 0);
|
||||||
context->partial_chunk = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,7 +679,8 @@ current_element (GMarkupParseContext *context)
|
|||||||
static const gchar*
|
static const gchar*
|
||||||
current_attribute (GMarkupParseContext *context)
|
current_attribute (GMarkupParseContext *context)
|
||||||
{
|
{
|
||||||
return ((GMarkupAttribute*)context->attributes->data)->name;
|
g_assert (context->cur_attr >= 0);
|
||||||
|
return context->attr_names[context->cur_attr];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -806,6 +720,21 @@ find_current_text_end (GMarkupParseContext *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_attribute (GMarkupParseContext *context, char *name)
|
||||||
|
{
|
||||||
|
if (context->cur_attr + 2 >= context->alloc_attrs)
|
||||||
|
{
|
||||||
|
context->alloc_attrs += 5; /* silly magic number */
|
||||||
|
context->attr_names = g_realloc (context->attr_names, sizeof(char*)*context->alloc_attrs);
|
||||||
|
context->attr_values = g_realloc (context->attr_values, sizeof(char*)*context->alloc_attrs);
|
||||||
|
}
|
||||||
|
context->cur_attr++;
|
||||||
|
context->attr_names[context->cur_attr] = name;
|
||||||
|
context->attr_values[context->cur_attr] = NULL;
|
||||||
|
context->attr_names[context->cur_attr+1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_markup_parse_context_parse:
|
* g_markup_parse_context_parse:
|
||||||
* @context: a #GMarkupParseContext
|
* @context: a #GMarkupParseContext
|
||||||
@ -1073,10 +1002,6 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
g_free (context->tag_stack->data);
|
|
||||||
context->tag_stack = g_slist_delete_link (context->tag_stack,
|
|
||||||
context->tag_stack);
|
|
||||||
|
|
||||||
if (tmp_error)
|
if (tmp_error)
|
||||||
{
|
{
|
||||||
mark_error (context, tmp_error);
|
mark_error (context, tmp_error);
|
||||||
@ -1102,6 +1027,10 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
current_element (context));
|
current_element (context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (context->tag_stack->data);
|
||||||
|
context->tag_stack = g_slist_delete_link (context->tag_stack,
|
||||||
|
context->tag_stack);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1161,20 +1090,13 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
/* The name has ended. Combine it with the partial chunk
|
/* The name has ended. Combine it with the partial chunk
|
||||||
* if any; push it on the stack; enter next state.
|
* if any; push it on the stack; enter next state.
|
||||||
*/
|
*/
|
||||||
GMarkupAttribute *attr;
|
|
||||||
add_to_partial (context, context->start, context->iter);
|
add_to_partial (context, context->start, context->iter);
|
||||||
|
|
||||||
attr = attribute_new (NULL, NULL);
|
add_attribute (context, g_string_free (context->partial_chunk, FALSE));
|
||||||
|
|
||||||
attr->name = g_string_free (context->partial_chunk,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
context->partial_chunk = NULL;
|
context->partial_chunk = NULL;
|
||||||
context->start = NULL;
|
context->start = NULL;
|
||||||
|
|
||||||
context->attributes =
|
|
||||||
g_slist_prepend (context->attributes, attr);
|
|
||||||
|
|
||||||
if (*context->iter == '=')
|
if (*context->iter == '=')
|
||||||
{
|
{
|
||||||
advance_char (context);
|
advance_char (context);
|
||||||
@ -1189,7 +1111,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
_("Odd character '%s', expected a '=' after "
|
_("Odd character '%s', expected a '=' after "
|
||||||
"attribute name '%s' of element '%s'"),
|
"attribute name '%s' of element '%s'"),
|
||||||
utf8_str (context->iter, buf),
|
utf8_str (context->iter, buf),
|
||||||
attr->name,
|
current_attribute (context),
|
||||||
current_element (context));
|
current_element (context));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1243,17 +1165,20 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->state == STATE_AFTER_CLOSE_ANGLE)
|
context->state == STATE_AFTER_CLOSE_ANGLE)
|
||||||
{
|
{
|
||||||
const gchar *start_name;
|
const gchar *start_name;
|
||||||
gchar **attr_names = NULL;
|
/* Ugly, but the current code expects an empty array instead of NULL */
|
||||||
gchar **attr_values = NULL;
|
const gchar *empty = NULL;
|
||||||
|
const gchar **attr_names = ∅
|
||||||
|
const gchar **attr_values = ∅
|
||||||
GError *tmp_error;
|
GError *tmp_error;
|
||||||
|
|
||||||
/* Call user callback for element start */
|
/* Call user callback for element start */
|
||||||
start_name = current_element (context);
|
start_name = current_element (context);
|
||||||
|
|
||||||
attribute_list_to_arrays (context->attributes,
|
if (context->cur_attr >= 0)
|
||||||
&attr_names,
|
{
|
||||||
&attr_values,
|
attr_names = (const gchar**)context->attr_names;
|
||||||
NULL);
|
attr_values = (const gchar**)context->attr_values;
|
||||||
|
}
|
||||||
|
|
||||||
tmp_error = NULL;
|
tmp_error = NULL;
|
||||||
if (context->parser->start_element)
|
if (context->parser->start_element)
|
||||||
@ -1264,17 +1189,15 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
/* Free only the string arrays, as we didn't g_strdup() the attribute
|
/* Go ahead and free the attributes. */
|
||||||
* list's strings
|
for (; context->cur_attr >= 0; context->cur_attr--)
|
||||||
*/
|
{
|
||||||
g_free (attr_names);
|
int pos = context->cur_attr;
|
||||||
g_free (attr_values);
|
g_free (context->attr_names[pos]);
|
||||||
|
g_free (context->attr_values[pos]);
|
||||||
/* Go ahead and free this. */
|
context->attr_names[pos] = context->attr_values[pos] = NULL;
|
||||||
g_slist_foreach (context->attributes, (GFunc)attribute_free,
|
}
|
||||||
NULL);
|
context->cur_attr = -1;
|
||||||
g_slist_free (context->attributes);
|
|
||||||
context->attributes = NULL;
|
|
||||||
|
|
||||||
if (tmp_error != NULL)
|
if (tmp_error != NULL)
|
||||||
{
|
{
|
||||||
@ -1330,17 +1253,15 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
* with the partial chunk if any; set it for the current
|
* with the partial chunk if any; set it for the current
|
||||||
* attribute.
|
* attribute.
|
||||||
*/
|
*/
|
||||||
GMarkupAttribute *attr;
|
|
||||||
|
|
||||||
add_to_partial (context, context->start, context->iter);
|
add_to_partial (context, context->start, context->iter);
|
||||||
|
|
||||||
attr = context->attributes->data;
|
g_assert (context->cur_attr >= 0);
|
||||||
|
|
||||||
if (unescape_text (context,
|
if (unescape_text (context,
|
||||||
context->partial_chunk->str,
|
context->partial_chunk->str,
|
||||||
context->partial_chunk->str +
|
context->partial_chunk->str +
|
||||||
context->partial_chunk->len,
|
context->partial_chunk->len,
|
||||||
&attr->value,
|
&context->attr_values[context->cur_attr],
|
||||||
error))
|
error))
|
||||||
{
|
{
|
||||||
/* success, advance past quote and set state. */
|
/* success, advance past quote and set state. */
|
||||||
@ -1349,7 +1270,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->start = NULL;
|
context->start = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1409,7 +1330,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1558,7 +1479,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
|
|||||||
context->user_data,
|
context->user_data,
|
||||||
&tmp_error);
|
&tmp_error);
|
||||||
|
|
||||||
free_partial (context);
|
truncate_partial (context);
|
||||||
|
|
||||||
if (tmp_error == NULL)
|
if (tmp_error == NULL)
|
||||||
{
|
{
|
||||||
@ -1609,6 +1530,12 @@ g_markup_parse_context_end_parse (GMarkupParseContext *context,
|
|||||||
g_return_val_if_fail (!context->parsing, FALSE);
|
g_return_val_if_fail (!context->parsing, FALSE);
|
||||||
g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
|
g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
|
||||||
|
|
||||||
|
if (context->partial_chunk != NULL)
|
||||||
|
{
|
||||||
|
g_string_free (context->partial_chunk, TRUE);
|
||||||
|
context->partial_chunk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (context->document_empty)
|
if (context->document_empty)
|
||||||
{
|
{
|
||||||
set_error (context, error, G_MARKUP_ERROR_EMPTY,
|
set_error (context, error, G_MARKUP_ERROR_EMPTY,
|
||||||
|
10
tests/markups/valid-3.gmarkup
Normal file
10
tests/markups/valid-3.gmarkup
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<foo>
|
||||||
|
<bar a="1"/>
|
||||||
|
<bar a="1" b="2"/>
|
||||||
|
<bar a="1" b="2" c="3"/>
|
||||||
|
<bar a="1" b="2" c="3" d="4"/>
|
||||||
|
<bar a="1" b="2" c="3" d="4" e="5"/>
|
||||||
|
<bar a="1" b="2" c="3" d="4" e="5" f="6"/>
|
||||||
|
<bar a="1" b="2" c="3"/>
|
||||||
|
<bar a="1"/>
|
||||||
|
</foo>
|
Loading…
x
Reference in New Issue
Block a user