GMarkup: share some common code for closing tags

The code for dealing with </foo> and the second half of <foo/> was
largely duplicated.  We can share a lot of it by using a common
function.

This slightly changes the behaviour of the parser under error
circumstances: previously the parser would deal with '<foo/}' by first
issuing the end_element callback and then flagging the error due to the
unexpected character.  Now we will flag the unexpected character error
first, skipping the callback.

This behaviour change required modifying the testsuite.

https://bugzilla.gnome.org/show_bug.cgi?id=665634
This commit is contained in:
Ryan Lortie 2013-10-28 13:56:26 -07:00
parent 44f13124c9
commit cbccbaeacf
3 changed files with 50 additions and 65 deletions

View File

@ -1038,6 +1038,37 @@ emit_start_element (GMarkupParseContext *context,
propagate_error (context, error, tmp_error);
}
static void
emit_end_element (GMarkupParseContext *context,
GError **error)
{
/* We need to pop the tag stack and call the end_element
* function, since this is the close tag
*/
GError *tmp_error = NULL;
g_assert (context->tag_stack != NULL);
possibly_finish_subparser (context);
tmp_error = NULL;
if (context->parser->end_element)
(* context->parser->end_element) (context,
current_element (context),
context->user_data,
&tmp_error);
ensure_no_outstanding_subparser (context);
if (tmp_error)
{
mark_error (context, tmp_error);
g_propagate_error (error, tmp_error);
}
pop_tag (context);
}
/**
* g_markup_parse_context_parse:
* @context: a #GMarkupParseContext
@ -1184,54 +1215,25 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
case STATE_AFTER_ELISION_SLASH:
/* Possible next state: AFTER_CLOSE_ANGLE */
if (*context->iter == '>')
{
/* move after the close angle */
advance_char (context);
context->state = STATE_AFTER_CLOSE_ANGLE;
emit_end_element (context, error);
}
else
{
gchar buf[8];
{
/* We need to pop the tag stack and call the end_element
* function, since this is the close tag
*/
GError *tmp_error = NULL;
g_assert (context->tag_stack != NULL);
possibly_finish_subparser (context);
tmp_error = NULL;
if (context->parser->end_element)
(* context->parser->end_element) (context,
current_element (context),
context->user_data,
&tmp_error);
ensure_no_outstanding_subparser (context);
if (tmp_error)
{
mark_error (context, tmp_error);
g_propagate_error (error, tmp_error);
}
else
{
if (*context->iter == '>')
{
/* move after the close angle */
advance_char (context);
context->state = STATE_AFTER_CLOSE_ANGLE;
}
else
{
gchar buf[8];
set_error (context,
error,
G_MARKUP_ERROR_PARSE,
_("Odd character '%s', expected a '>' character "
"to end the empty-element tag '%s'"),
utf8_str (context->iter, buf),
current_element (context));
}
}
pop_tag (context);
}
set_error (context,
error,
G_MARKUP_ERROR_PARSE,
_("Odd character '%s', expected a '>' character "
"to end the empty-element tag '%s'"),
utf8_str (context->iter, buf),
current_element (context));
}
break;
case STATE_INSIDE_OPEN_TAG_NAME:
@ -1589,26 +1591,11 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
}
else
{
GError *tmp_error;
advance_char (context);
context->state = STATE_AFTER_CLOSE_ANGLE;
context->start = NULL;
possibly_finish_subparser (context);
/* call the end_element callback */
tmp_error = NULL;
if (context->parser->end_element)
(* context->parser->end_element) (context,
close_name->str,
context->user_data,
&tmp_error);
ensure_no_outstanding_subparser (context);
pop_tag (context);
if (tmp_error)
propagate_error (context, error, tmp_error);
emit_end_element (context, error);
}
context->partial_chunk = close_name;
truncate_partial (context);

View File

@ -1,3 +1,2 @@
ELEMENT 'foo'
END 'foo'
ERROR Error on line 1 char 6: Odd character '≻', expected a '>' character to end the empty-element tag 'foo'

View File

@ -1,3 +1,2 @@
ELEMENT 'foo'
END 'foo'
ERROR Error on line 1 char 6: Odd character '}', expected a '>' character to end the empty-element tag 'foo'