Tests for handling of whitespace inside tags.

2004-07-28  Matthias Clasen  <mclasen@redhat.com>

	* tests/markups/valid-{9,10,11}.gmarkup:
	* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
	of whitespace inside tags.

	* glib/gmarkup.c (enum GMarkupParseState): Add
	STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
	(g_markup_parse_context_parse): Accept whitespace between
	attribute names, '=' and attribute values and between
	close tag name and '>'. (#148646, Hiroyuki Ikezoe)
This commit is contained in:
Matthias Clasen 2004-07-28 15:00:59 +00:00 committed by Matthias Clasen
parent 45e1212b68
commit 889096b1ea
12 changed files with 198 additions and 115 deletions

View File

@ -1,3 +1,15 @@
2004-07-28 Matthias Clasen <mclasen@redhat.com>
* tests/markups/valid-{9,10,11}.gmarkup:
* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
of whitespace inside tags.
* glib/gmarkup.c (enum GMarkupParseState): Add
STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
(g_markup_parse_context_parse): Accept whitespace between
attribute names, '=' and attribute values and between
close tag name and '>'. (#148646, Hiroyuki Ikezoe)
Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de> Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de>
* glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/ * glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/

View File

@ -1,3 +1,15 @@
2004-07-28 Matthias Clasen <mclasen@redhat.com>
* tests/markups/valid-{9,10,11}.gmarkup:
* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
of whitespace inside tags.
* glib/gmarkup.c (enum GMarkupParseState): Add
STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
(g_markup_parse_context_parse): Accept whitespace between
attribute names, '=' and attribute values and between
close tag name and '>'. (#148646, Hiroyuki Ikezoe)
Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de> Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de>
* glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/ * glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/

View File

@ -1,3 +1,15 @@
2004-07-28 Matthias Clasen <mclasen@redhat.com>
* tests/markups/valid-{9,10,11}.gmarkup:
* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
of whitespace inside tags.
* glib/gmarkup.c (enum GMarkupParseState): Add
STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
(g_markup_parse_context_parse): Accept whitespace between
attribute names, '=' and attribute values and between
close tag name and '>'. (#148646, Hiroyuki Ikezoe)
Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de> Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de>
* glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/ * glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/

View File

@ -1,3 +1,15 @@
2004-07-28 Matthias Clasen <mclasen@redhat.com>
* tests/markups/valid-{9,10,11}.gmarkup:
* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
of whitespace inside tags.
* glib/gmarkup.c (enum GMarkupParseState): Add
STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
(g_markup_parse_context_parse): Accept whitespace between
attribute names, '=' and attribute values and between
close tag name and '>'. (#148646, Hiroyuki Ikezoe)
Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de> Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de>
* glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/ * glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/

View File

@ -1,3 +1,15 @@
2004-07-28 Matthias Clasen <mclasen@redhat.com>
* tests/markups/valid-{9,10,11}.gmarkup:
* tests/markups/fail-{37,38,39}.gmarkup: Tests for handling
of whitespace inside tags.
* glib/gmarkup.c (enum GMarkupParseState): Add
STATE_AFTER_ATTRIBUTE_NAME and STATE_AFTER_CLOSE_TAG_NAME.
(g_markup_parse_context_parse): Accept whitespace between
attribute names, '=' and attribute values and between
close tag name and '>'. (#148646, Hiroyuki Ikezoe)
Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de> Tue Jul 27 02:01:31 2004 Matthias Clasen <maclas@gmx.de>
* glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/ * glib/gstrfuncs.c (g_strsplit_set): s/g_strsplit/g_strsplit_set/

View File

@ -49,6 +49,7 @@ typedef enum
STATE_AFTER_ELISION_SLASH, /* the slash that obviates need for end element */ STATE_AFTER_ELISION_SLASH, /* the slash that obviates need for end element */
STATE_INSIDE_OPEN_TAG_NAME, STATE_INSIDE_OPEN_TAG_NAME,
STATE_INSIDE_ATTRIBUTE_NAME, STATE_INSIDE_ATTRIBUTE_NAME,
STATE_AFTER_ATTRIBUTE_NAME,
STATE_BETWEEN_ATTRIBUTES, STATE_BETWEEN_ATTRIBUTES,
STATE_AFTER_ATTRIBUTE_EQUALS_SIGN, STATE_AFTER_ATTRIBUTE_EQUALS_SIGN,
STATE_INSIDE_ATTRIBUTE_VALUE_SQ, STATE_INSIDE_ATTRIBUTE_VALUE_SQ,
@ -56,6 +57,7 @@ typedef enum
STATE_INSIDE_TEXT, STATE_INSIDE_TEXT,
STATE_AFTER_CLOSE_TAG_SLASH, STATE_AFTER_CLOSE_TAG_SLASH,
STATE_INSIDE_CLOSE_TAG_NAME, STATE_INSIDE_CLOSE_TAG_NAME,
STATE_AFTER_CLOSE_TAG_NAME,
STATE_INSIDE_PASSTHROUGH, STATE_INSIDE_PASSTHROUGH,
STATE_ERROR STATE_ERROR
} GMarkupParseState; } GMarkupParseState;
@ -1136,33 +1138,34 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
break; break;
case STATE_INSIDE_ATTRIBUTE_NAME: case STATE_INSIDE_ATTRIBUTE_NAME:
/* Possible next states: AFTER_ATTRIBUTE_EQUALS_SIGN */ /* Possible next states: AFTER_ATTRIBUTE_NAME */
advance_to_name_end (context);
add_to_partial (context, context->start, context->iter);
/* read the full name, if we enter the equals sign state /* read the full name, if we enter the equals sign state
* then add the attribute to the list (without the value), * then add the attribute to the list (without the value),
* otherwise store a partial chunk to be prepended later. * otherwise store a partial chunk to be prepended later.
*/ */
advance_to_name_end (context); if (context->iter != context->current_text_end)
context->state = STATE_AFTER_ATTRIBUTE_NAME;
break;
if (context->iter == context->current_text_end) case STATE_AFTER_ATTRIBUTE_NAME:
{ /* Possible next states: AFTER_ATTRIBUTE_EQUALS_SIGN */
/* The name hasn't necessarily ended. Merge with
* partial chunk, leave state unchanged.
*/
add_to_partial (context, context->start, context->iter);
}
else
{
/* The name has ended. Combine it with the partial chunk
* if any; push it on the stack; enter next state.
*/
add_to_partial (context, context->start, context->iter);
skip_spaces (context);
if (context->iter != context->current_text_end)
{
/* The name has ended. Combine it with the partial chunk
* if any; push it on the stack; enter next state.
*/
add_attribute (context, g_string_free (context->partial_chunk, FALSE)); add_attribute (context, g_string_free (context->partial_chunk, FALSE));
context->partial_chunk = NULL; context->partial_chunk = NULL;
context->start = NULL; context->start = NULL;
if (*context->iter == '=') if (*context->iter == '=')
{ {
advance_char (context); advance_char (context);
@ -1179,7 +1182,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
utf8_str (context->iter, buf), utf8_str (context->iter, buf),
current_attribute (context), current_attribute (context),
current_element (context)); current_element (context));
} }
} }
break; break;
@ -1280,31 +1283,37 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
case STATE_AFTER_ATTRIBUTE_EQUALS_SIGN: case STATE_AFTER_ATTRIBUTE_EQUALS_SIGN:
/* Possible next state: INSIDE_ATTRIBUTE_VALUE_[SQ/DQ] */ /* Possible next state: INSIDE_ATTRIBUTE_VALUE_[SQ/DQ] */
if (*context->iter == '"')
{ skip_spaces (context);
advance_char (context);
context->state = STATE_INSIDE_ATTRIBUTE_VALUE_DQ; if (context->iter != context->current_text_end)
context->start = context->iter; {
} if (*context->iter == '"')
else if (*context->iter == '\'') {
{ advance_char (context);
advance_char (context); context->state = STATE_INSIDE_ATTRIBUTE_VALUE_DQ;
context->state = STATE_INSIDE_ATTRIBUTE_VALUE_SQ; context->start = context->iter;
context->start = context->iter; }
} else if (*context->iter == '\'')
else {
{ advance_char (context);
gchar buf[7]; context->state = STATE_INSIDE_ATTRIBUTE_VALUE_SQ;
set_error (context, context->start = context->iter;
error, }
G_MARKUP_ERROR_PARSE, else
_("Odd character '%s', expected an open quote mark " {
"after the equals sign when giving value for " gchar buf[7];
"attribute '%s' of element '%s'"), set_error (context,
utf8_str (context->iter, buf), error,
current_attribute (context), G_MARKUP_ERROR_PARSE,
current_element (context)); _("Odd character '%s', expected an open quote mark "
} "after the equals sign when giving value for "
"attribute '%s' of element '%s'"),
utf8_str (context->iter, buf),
current_attribute (context),
current_element (context));
}
}
break; break;
case STATE_INSIDE_ATTRIBUTE_VALUE_SQ: case STATE_INSIDE_ATTRIBUTE_VALUE_SQ:
@ -1447,88 +1456,89 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
break; break;
case STATE_INSIDE_CLOSE_TAG_NAME: case STATE_INSIDE_CLOSE_TAG_NAME:
/* Possible next state: AFTER_CLOSE_ANGLE */ /* Possible next state: AFTER_CLOSE_TAG_NAME */
advance_to_name_end (context); advance_to_name_end (context);
add_to_partial (context, context->start, context->iter);
if (context->iter == context->current_text_end) if (context->iter != context->current_text_end)
{ context->state = STATE_AFTER_CLOSE_TAG_NAME;
/* The name hasn't necessarily ended. Merge with break;
* partial chunk, leave state unchanged.
*/
add_to_partial (context, context->start, context->iter);
}
else
{
/* The name has ended. Combine it with the partial chunk
* if any; check that it matches stack top and pop
* stack; invoke proper callback; enter next state.
*/
gchar *close_name;
add_to_partial (context, context->start, context->iter); case STATE_AFTER_CLOSE_TAG_NAME:
/* Possible next state: AFTER_CLOSE_TAG_SLASH */
close_name = g_string_free (context->partial_chunk, FALSE); skip_spaces (context);
context->partial_chunk = NULL;
if (context->iter != context->current_text_end)
{
gchar *close_name;
/* The name has ended. Combine it with the partial chunk
* if any; check that it matches stack top and pop
* stack; invoke proper callback; enter next state.
*/
close_name = g_string_free (context->partial_chunk, FALSE);
context->partial_chunk = NULL;
if (*context->iter != '>') if (*context->iter != '>')
{ {
gchar buf[7]; gchar buf[7];
set_error (context, set_error (context,
error, error,
G_MARKUP_ERROR_PARSE, G_MARKUP_ERROR_PARSE,
_("'%s' is not a valid character following " _("'%s' is not a valid character following "
"the close element name '%s'; the allowed " "the close element name '%s'; the allowed "
"character is '>'"), "character is '>'"),
utf8_str (context->iter, buf), utf8_str (context->iter, buf),
close_name); close_name);
} }
else if (context->tag_stack == NULL) else if (context->tag_stack == NULL)
{ {
set_error (context, set_error (context,
error, error,
G_MARKUP_ERROR_PARSE, G_MARKUP_ERROR_PARSE,
_("Element '%s' was closed, no element " _("Element '%s' was closed, no element "
"is currently open"), "is currently open"),
close_name); close_name);
} }
else if (strcmp (close_name, current_element (context)) != 0) else if (strcmp (close_name, current_element (context)) != 0)
{ {
set_error (context, set_error (context,
error, error,
G_MARKUP_ERROR_PARSE, G_MARKUP_ERROR_PARSE,
_("Element '%s' was closed, but the currently " _("Element '%s' was closed, but the currently "
"open element is '%s'"), "open element is '%s'"),
close_name, close_name,
current_element (context)); current_element (context));
} }
else else
{ {
GError *tmp_error; GError *tmp_error;
advance_char (context); advance_char (context);
context->state = STATE_AFTER_CLOSE_ANGLE; context->state = STATE_AFTER_CLOSE_ANGLE;
context->start = NULL; context->start = NULL;
/* call the end_element callback */ /* call the end_element callback */
tmp_error = NULL; tmp_error = NULL;
if (context->parser->end_element) if (context->parser->end_element)
(* context->parser->end_element) (context, (* context->parser->end_element) (context,
close_name, close_name,
context->user_data, context->user_data,
&tmp_error); &tmp_error);
/* Pop the tag stack */ /* Pop the tag stack */
g_free (context->tag_stack->data); g_free (context->tag_stack->data);
context->tag_stack = g_slist_delete_link (context->tag_stack, context->tag_stack = g_slist_delete_link (context->tag_stack,
context->tag_stack); context->tag_stack);
if (tmp_error) if (tmp_error)
{ {
mark_error (context, tmp_error); mark_error (context, tmp_error);
g_propagate_error (error, tmp_error); g_propagate_error (error, tmp_error);
} }
} }
g_free (close_name); g_free (close_name);
} }
break; break;

View File

@ -0,0 +1 @@
< foo>

View File

@ -0,0 +1 @@
<foo>data< /foo>

View File

@ -0,0 +1 @@
<foo>data</ foo>

View File

@ -0,0 +1,6 @@
<foo
bar="baz"
bar2 = "baz2"
bar3 =
"baz3"
>data</foo>

View File

@ -0,0 +1,2 @@
<foo
>data</foo>

View File

@ -0,0 +1,2 @@
<foo>data</foo
>