diff --git a/docs/reference/glib/tmpl/.gitignore b/docs/reference/glib/tmpl/.gitignore
index 638e83e72..8ad3a7d3e 100644
--- a/docs/reference/glib/tmpl/.gitignore
+++ b/docs/reference/glib/tmpl/.gitignore
@@ -17,6 +17,7 @@ hash_tables.sgml
iochannels.sgml
linked_lists_double.sgml
linked_lists_single.sgml
+markup.sgml
memory_chunks.sgml
memory.sgml
option.sgml
diff --git a/docs/reference/glib/tmpl/markup.sgml b/docs/reference/glib/tmpl/markup.sgml
deleted file mode 100644
index 7a14ecbe3..000000000
--- a/docs/reference/glib/tmpl/markup.sgml
+++ /dev/null
@@ -1,327 +0,0 @@
-
-Simple XML Subset Parser
-
-
-parses a subset of XML
-
-
-
-The "GMarkup" parser is intended to parse a simple markup format
-that's a subset of XML. This is a small, efficient, easy-to-use
-parser. It should not be used if you expect to interoperate with other
-applications generating full-scale XML. However, it's very useful for
-application data files, config files, etc. where you know your
-application will be the only one writing the file. Full-scale XML
-parsers should be able to parse the subset used by GMarkup, so you can
-easily migrate to full-scale XML at a later time if the need arises.
-
-
-
-GMarkup is not guaranteed to signal an error on all invalid XML; the
-parser may accept documents that an XML parser would not. However, XML
-documents which are not well-formedBeing wellformed
-is a weaker condition than being valid. See the
-XML specification for
-definitions of these terms. are not considered valid GMarkup
-documents.
-
-
-
-Simplifications to XML include:
-
-
-
-Only UTF-8 encoding is allowed.
-
-
-
-
-No user-defined entities.
-
-
-
-
-Processing instructions, comments and the doctype declaration are "passed
-through" but are not interpreted in any way.
-
-
-
-
-No DTD or validation.
-
-
-
-
-
-
-The markup format does support:
-
-
-
-Elements
-
-
-
-
-Attributes
-
-
-
-
-5 standard entities: & < > " '
-
-
-
-
-Character references
-
-
-
-
-Sections marked as CDATA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Error codes returned by markup parsing.
-
-
-@G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
-@G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
-@G_MARKUP_ERROR_PARSE: document was ill-formed
-@G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser functions; element wasn't known
-@G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser functions; attribute wasn't known
-@G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser functions; content was invalid
-@G_MARKUP_ERROR_MISSING_ATTRIBUTE: error should be set by #GMarkupParser functions; a required attribute was missing
-
-
-
-Error domain for markup parsing. Errors in this domain will
-be from the #GMarkupError enumeration. See #GError for information on
-error domains.
-
-
-
-
-
-
-Flags that affect the behaviour of the parser.
-
-
-@G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG: flag you should not use.
-@G_MARKUP_TREAT_CDATA_AS_TEXT: When this flag is set, CDATA marked
- sections are not passed literally to the @passthrough function of
- the parser. Instead, the content of the section (without the
- <![CDATA[ and ]]>) is
- passed to the @text function. This flag was added in GLib 2.12.
-@G_MARKUP_PREFIX_ERROR_POSITION: Normally errors caught by GMarkup
- itself have line/column information prefixed to them to let the
- caller know the location of the error. When this flag is set the
- location information is also prefixed to errors generated by the
- #GMarkupParser implementation functions.
-
-
-
-A parse context is used to parse a stream of bytes that you expect to
-contain marked-up text. See g_markup_parse_context_new(),
-#GMarkupParser, and so on for more details.
-
-
-
-
-
-Any of the fields in #GMarkupParser can be %NULL, in which case they
-will be ignored. Except for the @error function, any of these
-callbacks can set an error; in particular the
-%G_MARKUP_ERROR_UNKNOWN_ELEMENT, %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
-and %G_MARKUP_ERROR_INVALID_CONTENT errors are intended to be set
-from these callbacks. If you set an error from a callback,
-g_markup_parse_context_parse() will report that error back to its caller.
-
-
-@start_element: Callback to invoke when the opening tag of an element
- is seen.
-@end_element: Callback to invoke when the closing tag of an element is seen.
- Note that this is also called for empty tags like
- <empty/>.
-@text: Callback to invoke when some text is seen (text is always
- inside an element). Note that the text of an element may be spread
- over multiple calls of this function. If the %G_MARKUP_TREAT_CDATA_AS_TEXT
- flag is set, this function is also called for the content of CDATA marked
- sections.
-@passthrough: Callback to invoke for comments, processing instructions
- and doctype declarations; if you're re-writing the parsed document,
- write the passthrough text back out in the same position. If the
- %G_MARKUP_TREAT_CDATA_AS_TEXT flag is not set, this function is also
- called for CDATA marked sections.
-@error: Callback to invoke when an error occurs.
-
-
-
-
-
-
-@text:
-@length:
-@Returns:
-
-
-
-
-
-
-
-@format:
-@Varargs:
-@Returns:
-
-
-
-
-
-
-
-@format:
-@args:
-@Returns:
-
-
-
-
-
-
-
-@context:
-@error:
-@Returns:
-
-
-
-
-
-
-
-@context:
-
-
-
-
-
-
-
-@context:
-@line_number:
-@char_number:
-
-
-
-
-
-
-
-@context:
-@Returns:
-
-
-
-
-
-
-
-@context:
-@Returns:
-
-
-
-
-
-
-
-@context:
-@Returns:
-
-
-
-
-
-
-
-@parser:
-@flags:
-@user_data:
-@user_data_dnotify:
-@Returns:
-
-
-
-
-
-
-
-@context:
-@text:
-@text_len:
-@error:
-@Returns:
-
-
-
-
-
-
-
-@context:
-@parser:
-@user_data:
-
-
-
-
-
-
-
-@context:
-@Returns:
-
-
-
-
-
-
-
-@G_MARKUP_COLLECT_INVALID:
-@G_MARKUP_COLLECT_STRING:
-@G_MARKUP_COLLECT_STRDUP:
-@G_MARKUP_COLLECT_BOOLEAN:
-@G_MARKUP_COLLECT_TRISTATE:
-@G_MARKUP_COLLECT_OPTIONAL:
-
-
-
-
-
-
-@element_name:
-@attribute_names:
-@attribute_values:
-@error:
-@first_type:
-@first_attr:
-@Varargs:
-@Returns:
-
-
diff --git a/glib/gmarkup.c b/glib/gmarkup.c
index b9e8c3130..ccdb50055 100644
--- a/glib/gmarkup.c
+++ b/glib/gmarkup.c
@@ -35,6 +35,52 @@
#include "gtestutils.h"
#include "glibintl.h"
+/**
+ * SECTION:markup
+ * @Title: Simple XML Subset Parser
+ * @Short_description: parses a subset of XML
+ * @See_also: XML
+ * Specification
+ *
+ * The "GMarkup" parser is intended to parse a simple markup format
+ * that's a subset of XML. This is a small, efficient, easy-to-use
+ * parser. It should not be used if you expect to interoperate with
+ * other applications generating full-scale XML. However, it's very
+ * useful for application data files, config files, etc. where you
+ * know your application will be the only one writing the file.
+ * Full-scale XML parsers should be able to parse the subset used by
+ * GMarkup, so you can easily migrate to full-scale XML at a later
+ * time if the need arises.
+ *
+ * GMarkup is not guaranteed to signal an error on all invalid XML;
+ * the parser may accept documents that an XML parser would not.
+ * However, XML documents which are not well-formedBeing wellformed is a weaker condition than being
+ * valid. See the XML
+ * specification for definitions of these terms.
+ * are not considered valid GMarkup documents.
+ *
+ * Simplifications to XML include:
+ *
+ * Only UTF-8 encoding is allowed
+ * No user-defined entities
+ * Processing instructions, comments and the doctype declaration
+ * are "passed through" but are not interpreted in any way
+ * No DTD or validation.
+ *
+ *
+ * The markup format does support:
+ *
+ * Elements
+ * Attributes
+ * 5 standard entities:
+ * & < > " '
+ *
+ * Character references
+ * Sections marked as CDATA
+ *
+ */
+
GQuark
g_markup_error_quark (void)
{
@@ -99,7 +145,7 @@ struct _GMarkupParseContext
gint alloc_attrs;
const gchar *current_text;
- gssize current_text_len;
+ gssize current_text_len;
const gchar *current_text_end;
/* used to save the start of the last interesting thingy */
@@ -156,14 +202,15 @@ string_blank (GString *string)
* @parser: a #GMarkupParser
* @flags: one or more #GMarkupParseFlags
* @user_data: user data to pass to #GMarkupParser functions
- * @user_data_dnotify: user data destroy notifier called when the parse context is freed
- *
+ * @user_data_dnotify: user data destroy notifier called when
+ * the parse context is freed
+ *
* Creates a new parse context. A parse context is used to parse
* marked-up documents. You can feed any number of documents into
* a context, as long as no errors occur; once an error occurs,
- * the parse context can't continue to parse text (you have to free it
- * and create a new parse context).
- *
+ * the parse context can't continue to parse text (you have to
+ * free it and create a new parse context).
+ *
* Return value: a new #GMarkupParseContext
**/
GMarkupParseContext *
@@ -221,7 +268,7 @@ g_markup_parse_context_new (const GMarkupParser *parser,
}
static void
-string_full_free (gpointer ptr, gpointer user_data)
+string_full_free (gpointer ptr)
{
g_string_free (ptr, TRUE);
}
@@ -231,11 +278,12 @@ static void clear_attributes (GMarkupParseContext *context);
/**
* g_markup_parse_context_free:
* @context: a #GMarkupParseContext
- *
- * Frees a #GMarkupParseContext. Can't be called from inside
- * one of the #GMarkupParser functions. Can't be called while
- * a subparser is pushed.
- **/
+ *
+ * Frees a #GMarkupParseContext.
+ *
+ * This function can't be called from inside one of the
+ * #GMarkupParser functions or while a subparser is pushed.
+ */
void
g_markup_parse_context_free (GMarkupParseContext *context)
{
@@ -251,12 +299,10 @@ g_markup_parse_context_free (GMarkupParseContext *context)
g_free (context->attr_names);
g_free (context->attr_values);
- g_slist_foreach (context->tag_stack_gstr, string_full_free, NULL);
- g_slist_free (context->tag_stack_gstr);
+ g_slist_free_full (context->tag_stack_gstr, string_full_free);
g_slist_free (context->tag_stack);
- g_slist_foreach (context->spare_chunks, string_full_free, NULL);
- g_slist_free (context->spare_chunks);
+ g_slist_free_full (context->spare_chunks, string_full_free);
g_slist_free (context->spare_list_nodes);
if (context->partial_chunk)
@@ -287,17 +333,18 @@ mark_error (GMarkupParseContext *context,
}
}
-static void set_error (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *format,
- ...) G_GNUC_PRINTF (4, 5);
+static void
+set_error (GMarkupParseContext *context,
+ GError **error,
+ GMarkupError code,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (4, 5);
static void
-set_error_literal (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *message)
+set_error_literal (GMarkupParseContext *context,
+ GError **error,
+ GMarkupError code,
+ const gchar *message)
{
GError *tmp_error;
@@ -314,10 +361,10 @@ set_error_literal (GMarkupParseContext *context,
}
static void
-set_error (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *format,
+set_error (GMarkupParseContext *context,
+ GError **error,
+ GMarkupError code,
+ const gchar *format,
...)
{
gchar *s;
@@ -328,8 +375,9 @@ set_error (GMarkupParseContext *context,
s = g_strdup_vprintf (format, args);
va_end (args);
- /* Make sure that the GError message is valid UTF-8 even if it is
- * complaining about invalid UTF-8 in the markup: */
+ /* Make sure that the GError message is valid UTF-8
+ * even if it is complaining about invalid UTF-8 in the markup
+ */
s_valid = _g_utf8_make_valid (s);
set_error_literal (context, error, code, s);
@@ -357,25 +405,27 @@ propagate_error (GMarkupParseContext *context,
((c) == '=' || (c) == '/' || (c) == '>' || (c) == ' ')
static gboolean
-slow_name_validate (GMarkupParseContext *context, const char *name, GError **error)
+slow_name_validate (GMarkupParseContext *context,
+ const gchar *name,
+ GError **error)
{
- const char *p = name;
+ const gchar *p = name;
if (!g_utf8_validate (name, strlen (name), NULL))
{
set_error (context, error, G_MARKUP_ERROR_BAD_UTF8,
- _("Invalid UTF-8 encoded text in name - not valid '%s'"), name);
+ _("Invalid UTF-8 encoded text in name - not valid '%s'"), name);
return FALSE;
}
if (!(g_ascii_isalpha (*p) ||
- (!IS_COMMON_NAME_END_CHAR (*p) &&
- (*p == '_' ||
- *p == ':' ||
- g_unichar_isalpha (g_utf8_get_char (p))))))
+ (!IS_COMMON_NAME_END_CHAR (*p) &&
+ (*p == '_' ||
+ *p == ':' ||
+ g_unichar_isalpha (g_utf8_get_char (p))))))
{
set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid name "), name);
+ _("'%s' is not a valid name "), name);
return FALSE;
}
@@ -383,26 +433,28 @@ slow_name_validate (GMarkupParseContext *context, const char *name, GError **err
{
/* is_name_char */
if (!(g_ascii_isalnum (*p) ||
- (!IS_COMMON_NAME_END_CHAR (*p) &&
- (*p == '.' ||
- *p == '-' ||
- *p == '_' ||
- *p == ':' ||
- g_unichar_isalpha (g_utf8_get_char (p))))))
- {
- set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid name: '%c' "), name, *p);
- return FALSE;
- }
+ (!IS_COMMON_NAME_END_CHAR (*p) &&
+ (*p == '.' ||
+ *p == '-' ||
+ *p == '_' ||
+ *p == ':' ||
+ g_unichar_isalpha (g_utf8_get_char (p))))))
+ {
+ set_error (context, error, G_MARKUP_ERROR_PARSE,
+ _("'%s' is not a valid name: '%c' "), name, *p);
+ return FALSE;
+ }
}
return TRUE;
}
-/*
+/*
* Use me for elements, attributes etc.
*/
static gboolean
-name_validate (GMarkupParseContext *context, const char *name, GError **error)
+name_validate (GMarkupParseContext *context,
+ const gchar *name,
+ GError **error)
{
char mask;
const char *p;
@@ -410,21 +462,21 @@ name_validate (GMarkupParseContext *context, const char *name, GError **error)
/* name start char */
p = name;
if (G_UNLIKELY (IS_COMMON_NAME_END_CHAR (*p) ||
- !(g_ascii_isalpha (*p) || *p == '_' || *p == ':')))
+ !(g_ascii_isalpha (*p) || *p == '_' || *p == ':')))
goto slow_validate;
-
+
for (mask = *p++; *p != '\0'; p++)
{
mask |= *p;
/* is_name_char */
if (G_UNLIKELY (!(g_ascii_isalnum (*p) ||
- (!IS_COMMON_NAME_END_CHAR (*p) &&
- (*p == '.' ||
- *p == '-' ||
- *p == '_' ||
- *p == ':')))))
- goto slow_validate;
+ (!IS_COMMON_NAME_END_CHAR (*p) &&
+ (*p == '.' ||
+ *p == '-' ||
+ *p == '_' ||
+ *p == ':')))))
+ goto slow_validate;
}
if (mask & 0x80) /* un-common / non-ascii */
@@ -437,12 +489,15 @@ name_validate (GMarkupParseContext *context, const char *name, GError **error)
}
static gboolean
-text_validate (GMarkupParseContext *context, const char *p, int len, GError **error)
+text_validate (GMarkupParseContext *context,
+ const gchar *p,
+ gint len,
+ GError **error)
{
if (!g_utf8_validate (p, len, NULL))
{
set_error (context, error, G_MARKUP_ERROR_BAD_UTF8,
- _("Invalid UTF-8 encoded text in name - not valid '%s'"), p);
+ _("Invalid UTF-8 encoded text in name - not valid '%s'"), p);
return FALSE;
}
else
@@ -467,11 +522,11 @@ utf8_str (const gchar *utf8,
}
static void
-set_unescape_error (GMarkupParseContext *context,
- GError **error,
- const gchar *remaining_text,
- GMarkupError code,
- const gchar *format,
+set_unescape_error (GMarkupParseContext *context,
+ GError **error,
+ const gchar *remaining_text,
+ GMarkupError code,
+ const gchar *format,
...)
{
GError *tmp_error;
@@ -511,10 +566,10 @@ set_unescape_error (GMarkupParseContext *context,
* most XML does not contain entities, or escaping.
*/
static gboolean
-unescape_gstring_inplace (GMarkupParseContext *context,
- GString *string,
- gboolean *is_ascii,
- GError **error)
+unescape_gstring_inplace (GMarkupParseContext *context,
+ GString *string,
+ gboolean *is_ascii,
+ GError **error)
{
char mask, *to;
int line_num = 1;
@@ -536,146 +591,146 @@ unescape_gstring_inplace (GMarkupParseContext *context,
* thought is required, but this is patently so.
*/
mask = 0;
- for (from = to = string->str; *from != '\0'; from++, to++)
+ for (from = to = string->str; *from != '\0'; from++, to++)
{
*to = *from;
mask |= *to;
if (*to == '\n')
- line_num++;
+ line_num++;
if (normalize_attribute && (*to == '\t' || *to == '\n'))
- *to = ' ';
+ *to = ' ';
if (*to == '\r')
- {
- *to = normalize_attribute ? ' ' : '\n';
- if (from[1] == '\n')
- from++;
- }
+ {
+ *to = normalize_attribute ? ' ' : '\n';
+ if (from[1] == '\n')
+ from++;
+ }
if (*from == '&')
- {
- from++;
- if (*from == '#')
- {
- gboolean is_hex = FALSE;
- gulong l;
- gchar *end = NULL;
+ {
+ from++;
+ if (*from == '#')
+ {
+ gboolean is_hex = FALSE;
+ gulong l;
+ gchar *end = NULL;
- from++;
+ from++;
- if (*from == 'x')
- {
- is_hex = TRUE;
- from++;
- }
+ if (*from == 'x')
+ {
+ is_hex = TRUE;
+ from++;
+ }
- /* digit is between start and p */
- errno = 0;
- if (is_hex)
- l = strtoul (from, &end, 16);
- else
- l = strtoul (from, &end, 10);
-
- if (end == from || errno != 0)
- {
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Failed to parse '%-.*s', which "
- "should have been a digit "
- "inside a character reference "
- "(ê for example) - perhaps "
- "the digit is too large"),
- end - from, from);
- return FALSE;
- }
- else if (*end != ';')
- {
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Character reference did not end with a "
- "semicolon; "
- "most likely you used an ampersand "
- "character without intending to start "
- "an entity - escape ampersand as &"));
- return FALSE;
- }
- else
- {
- /* characters XML 1.1 permits */
- if ((0 < l && l <= 0xD7FF) ||
- (0xE000 <= l && l <= 0xFFFD) ||
- (0x10000 <= l && l <= 0x10FFFF))
- {
- gchar buf[8];
- char_str (l, buf);
- strcpy (to, buf);
- to += strlen (buf) - 1;
- from = end;
- if (l >= 0x80) /* not ascii */
- mask |= 0x80;
- }
- else
- {
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Character reference '%-.*s' does not "
- "encode a permitted character"),
- end - from, from);
- return FALSE;
- }
- }
+ /* digit is between start and p */
+ errno = 0;
+ if (is_hex)
+ l = strtoul (from, &end, 16);
+ else
+ l = strtoul (from, &end, 10);
+
+ if (end == from || errno != 0)
+ {
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Failed to parse '%-.*s', which "
+ "should have been a digit "
+ "inside a character reference "
+ "(ê for example) - perhaps "
+ "the digit is too large"),
+ end - from, from);
+ return FALSE;
+ }
+ else if (*end != ';')
+ {
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Character reference did not end with a "
+ "semicolon; "
+ "most likely you used an ampersand "
+ "character without intending to start "
+ "an entity - escape ampersand as &"));
+ return FALSE;
+ }
+ else
+ {
+ /* characters XML 1.1 permits */
+ if ((0 < l && l <= 0xD7FF) ||
+ (0xE000 <= l && l <= 0xFFFD) ||
+ (0x10000 <= l && l <= 0x10FFFF))
+ {
+ gchar buf[8];
+ char_str (l, buf);
+ strcpy (to, buf);
+ to += strlen (buf) - 1;
+ from = end;
+ if (l >= 0x80) /* not ascii */
+ mask |= 0x80;
+ }
+ else
+ {
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Character reference '%-.*s' does not "
+ "encode a permitted character"),
+ end - from, from);
+ return FALSE;
+ }
+ }
}
else if (strncmp (from, "lt;", 3) == 0)
- {
- *to = '<';
- from += 2;
- }
+ {
+ *to = '<';
+ from += 2;
+ }
else if (strncmp (from, "gt;", 3) == 0)
- {
- *to = '>';
- from += 2;
- }
+ {
+ *to = '>';
+ from += 2;
+ }
else if (strncmp (from, "amp;", 4) == 0)
- {
- *to = '&';
- from += 3;
- }
+ {
+ *to = '&';
+ from += 3;
+ }
else if (strncmp (from, "quot;", 5) == 0)
- {
- *to = '"';
- from += 4;
- }
- else if (strncmp (from, "apos;", 5) == 0)
- {
- *to = '\'';
- from += 4;
- }
- else
- {
- if (*from == ';')
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Empty entity '&;' seen; valid "
- "entities are: & " < > '"));
- else
- {
- const char *end = strchr (from, ';');
- if (end)
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Entity name '%-.*s' is not known"),
- end-from, from);
- else
- set_unescape_error (context, error,
- from, G_MARKUP_ERROR_PARSE,
- _("Entity did not end with a semicolon; "
- "most likely you used an ampersand "
- "character without intending to start "
- "an entity - escape ampersand as &"));
- }
- return FALSE;
- }
- }
+ {
+ *to = '"';
+ from += 4;
+ }
+ else if (strncmp (from, "apos;", 5) == 0)
+ {
+ *to = '\'';
+ from += 4;
+ }
+ else
+ {
+ if (*from == ';')
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Empty entity '&;' seen; valid "
+ "entities are: & " < > '"));
+ else
+ {
+ const char *end = strchr (from, ';');
+ if (end)
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Entity name '%-.*s' is not known"),
+ end-from, from);
+ else
+ set_unescape_error (context, error,
+ from, G_MARKUP_ERROR_PARSE,
+ _("Entity did not end with a semicolon; "
+ "most likely you used an ampersand "
+ "character without intending to start "
+ "an entity - escape ampersand as &"));
+ }
+ return FALSE;
+ }
+ }
}
g_assert (to - string->str <= string->len);
@@ -689,7 +744,7 @@ unescape_gstring_inplace (GMarkupParseContext *context,
static inline gboolean
advance_char (GMarkupParseContext *context)
-{
+{
context->iter++;
context->char_number++;
@@ -701,7 +756,7 @@ advance_char (GMarkupParseContext *context)
context->line_number++;
context->char_number = 1;
}
-
+
return TRUE;
}
@@ -730,7 +785,7 @@ advance_to_name_end (GMarkupParseContext *context)
if (IS_COMMON_NAME_END_CHAR (*(context->iter)))
return;
if (xml_isspace (*(context->iter)))
- return;
+ return;
}
while (advance_char (context));
}
@@ -760,19 +815,19 @@ add_to_partial (GMarkupParseContext *context,
{ /* allocate a new chunk to parse into */
if (context->spare_chunks != NULL)
- {
- GSList *node = context->spare_chunks;
- context->spare_chunks = g_slist_remove_link (context->spare_chunks, node);
- context->partial_chunk = node->data;
- free_list_node (context, node);
- }
+ {
+ GSList *node = context->spare_chunks;
+ context->spare_chunks = g_slist_remove_link (context->spare_chunks, node);
+ context->partial_chunk = node->data;
+ free_list_node (context, node);
+ }
else
- context->partial_chunk = g_string_sized_new (MAX (28, text_end - text_start));
+ context->partial_chunk = g_string_sized_new (MAX (28, text_end - text_start));
}
if (text_start != text_end)
g_string_insert_len (context->partial_chunk, -1,
- text_start, text_end - text_start);
+ text_start, text_end - text_start);
}
static inline void
@@ -845,10 +900,10 @@ ensure_no_outstanding_subparser (GMarkupParseContext *context)
{
if (context->awaiting_pop)
g_critical ("During the first end_element call after invoking a "
- "subparser you must pop the subparser stack and handle "
- "the freeing of the subparser user_data. This can be "
- "done by calling the end function of the subparser. "
- "Very probably, your program just leaked memory.");
+ "subparser you must pop the subparser stack and handle "
+ "the freeing of the subparser user_data. This can be "
+ "done by calling the end function of the subparser. "
+ "Very probably, your program just leaked memory.");
/* let valgrind watch the pointer disappear... */
context->held_user_data = NULL;
@@ -891,23 +946,25 @@ clear_attributes (GMarkupParseContext *context)
}
g_assert (context->cur_attr == -1);
g_assert (context->attr_names == NULL ||
- context->attr_names[0] == NULL);
+ context->attr_names[0] == NULL);
g_assert (context->attr_values == NULL ||
- context->attr_values[0] == NULL);
+ context->attr_values[0] == NULL);
}
/* This has to be a separate function to ensure the alloca's
- are unwound on exit - otherwise we grow & blow the stack
- with large documents */
+ * are unwound on exit - otherwise we grow & blow the stack
+ * with large documents
+ */
static inline void
-emit_start_element (GMarkupParseContext *context, GError **error)
+emit_start_element (GMarkupParseContext *context,
+ GError **error)
{
int i;
const gchar *start_name;
const gchar **attr_names;
const gchar **attr_values;
GError *tmp_error;
-
+
attr_names = g_newa (const gchar *, context->cur_attr + 2);
attr_values = g_newa (const gchar *, context->cur_attr + 2);
for (i = 0; i < context->cur_attr + 1; i++)
@@ -917,21 +974,21 @@ emit_start_element (GMarkupParseContext *context, GError **error)
}
attr_names[i] = NULL;
attr_values[i] = NULL;
-
+
/* Call user callback for element start */
tmp_error = NULL;
start_name = current_element (context);
-
+
if (context->parser->start_element &&
name_validate (context, start_name, error))
(* context->parser->start_element) (context,
- start_name,
- (const gchar **)attr_names,
- (const gchar **)attr_values,
- context->user_data,
- &tmp_error);
+ start_name,
+ (const gchar **)attr_names,
+ (const gchar **)attr_values,
+ context->user_data,
+ &tmp_error);
clear_attributes (context);
-
+
if (tmp_error != NULL)
propagate_error (context, error, tmp_error);
}
@@ -942,37 +999,39 @@ emit_start_element (GMarkupParseContext *context, GError **error)
* @text: chunk of text to parse
* @text_len: length of @text in bytes
* @error: return location for a #GError
- *
- * Feed some data to the #GMarkupParseContext. The data need not
- * be valid UTF-8; an error will be signaled if it's invalid.
- * The data need not be an entire document; you can feed a document
- * into the parser incrementally, via multiple calls to this function.
- * Typically, as you receive data from a network connection or file,
- * you feed each received chunk of data into this function, aborting
- * the process if an error occurs. Once an error is reported, no further
- * data may be fed to the #GMarkupParseContext; all errors are fatal.
- *
+ *
+ * Feed some data to the #GMarkupParseContext.
+ *
+ * The data need not be valid UTF-8; an error will be signaled if
+ * it's invalid. The data need not be an entire document; you can
+ * feed a document into the parser incrementally, via multiple calls
+ * to this function. Typically, as you receive data from a network
+ * connection or file, you feed each received chunk of data into this
+ * function, aborting the process if an error occurs. Once an error
+ * is reported, no further data may be fed to the #GMarkupParseContext;
+ * all errors are fatal.
+ *
* Return value: %FALSE if an error occurred, %TRUE on success
- **/
+ */
gboolean
-g_markup_parse_context_parse (GMarkupParseContext *context,
- const gchar *text,
- gssize text_len,
- GError **error)
+g_markup_parse_context_parse (GMarkupParseContext *context,
+ const gchar *text,
+ gssize text_len,
+ GError **error)
{
g_return_val_if_fail (context != NULL, FALSE);
g_return_val_if_fail (text != NULL, FALSE);
g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
g_return_val_if_fail (!context->parsing, FALSE);
-
+
if (text_len < 0)
text_len = strlen (text);
if (text_len == 0)
return TRUE;
-
+
context->parsing = TRUE;
-
+
context->current_text = text;
context->current_text_len = text_len;
@@ -1031,7 +1090,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
const gchar *openangle = "<";
add_to_partial (context, openangle, openangle + 1);
context->start = context->iter;
- context->balance = 1;
+ context->balance = 1;
context->state = STATE_INSIDE_PASSTHROUGH;
}
else if (*context->iter == '/')
@@ -1089,7 +1148,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
* function, since this is the close tag
*/
GError *tmp_error = NULL;
-
+
g_assert (context->tag_stack != NULL);
possibly_finish_subparser (context);
@@ -1097,17 +1156,17 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
tmp_error = NULL;
if (context->parser->end_element)
(* context->parser->end_element) (context,
- current_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 == '>')
@@ -1129,7 +1188,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
current_element (context));
}
}
- pop_tag (context);
+ pop_tag (context);
}
break;
@@ -1156,7 +1215,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
* if any; push it on the stack; enter next state.
*/
add_to_partial (context, context->start, context->iter);
- push_partial_as_tag (context);
+ push_partial_as_tag (context);
context->state = STATE_BETWEEN_ATTRIBUTES;
context->start = NULL;
@@ -1167,34 +1226,34 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
/* Possible next states: AFTER_ATTRIBUTE_NAME */
advance_to_name_end (context);
- add_to_partial (context, context->start, context->iter);
+ add_to_partial (context, context->start, context->iter);
/* read the full name, if we enter the equals sign state
* then add the attribute to the list (without the value),
* otherwise store a partial chunk to be prepended later.
*/
if (context->iter != context->current_text_end)
- context->state = STATE_AFTER_ATTRIBUTE_NAME;
- break;
+ context->state = STATE_AFTER_ATTRIBUTE_NAME;
+ break;
- case STATE_AFTER_ATTRIBUTE_NAME:
+ case STATE_AFTER_ATTRIBUTE_NAME:
/* Possible next states: AFTER_ATTRIBUTE_EQUALS_SIGN */
- skip_spaces (context);
+ 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.
- */
- if (!name_validate (context, context->partial_chunk->str, error))
- break;
+ 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.
+ */
+ if (!name_validate (context, context->partial_chunk->str, error))
+ break;
+
+ add_attribute (context, context->partial_chunk);
- add_attribute (context, context->partial_chunk);
-
context->partial_chunk = NULL;
context->start = NULL;
-
+
if (*context->iter == '=')
{
advance_char (context);
@@ -1212,7 +1271,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
utf8_str (context->iter, buf),
current_attribute (context),
current_element (context));
-
+
}
}
break;
@@ -1262,68 +1321,68 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
*/
if (context->state == STATE_AFTER_ELISION_SLASH ||
context->state == STATE_AFTER_CLOSE_ANGLE)
- emit_start_element (context, error);
+ emit_start_element (context, error);
}
break;
case STATE_AFTER_ATTRIBUTE_EQUALS_SIGN:
/* Possible next state: INSIDE_ATTRIBUTE_VALUE_[SQ/DQ] */
- skip_spaces (context);
+ skip_spaces (context);
- if (context->iter != context->current_text_end)
- {
- if (*context->iter == '"')
- {
- advance_char (context);
- context->state = STATE_INSIDE_ATTRIBUTE_VALUE_DQ;
- context->start = context->iter;
- }
- else if (*context->iter == '\'')
- {
- advance_char (context);
- context->state = STATE_INSIDE_ATTRIBUTE_VALUE_SQ;
- context->start = context->iter;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("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));
- }
- }
+ if (context->iter != context->current_text_end)
+ {
+ if (*context->iter == '"')
+ {
+ advance_char (context);
+ context->state = STATE_INSIDE_ATTRIBUTE_VALUE_DQ;
+ context->start = context->iter;
+ }
+ else if (*context->iter == '\'')
+ {
+ advance_char (context);
+ context->state = STATE_INSIDE_ATTRIBUTE_VALUE_SQ;
+ context->start = context->iter;
+ }
+ else
+ {
+ gchar buf[8];
+
+ set_error (context,
+ error,
+ G_MARKUP_ERROR_PARSE,
+ _("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;
case STATE_INSIDE_ATTRIBUTE_VALUE_SQ:
case STATE_INSIDE_ATTRIBUTE_VALUE_DQ:
/* Possible next states: BETWEEN_ATTRIBUTES */
- {
- gchar delim;
+ {
+ gchar delim;
- if (context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ)
- {
- delim = '\'';
- }
- else
- {
- delim = '"';
- }
+ if (context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ)
+ {
+ delim = '\'';
+ }
+ else
+ {
+ delim = '"';
+ }
- do
- {
- if (*context->iter == delim)
- break;
- }
- while (advance_char (context));
- }
+ do
+ {
+ if (*context->iter == delim)
+ break;
+ }
+ while (advance_char (context));
+ }
if (context->iter == context->current_text_end)
{
/* The value hasn't necessarily ended. Merge with
@@ -1333,7 +1392,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
}
else
{
- gboolean is_ascii;
+ gboolean is_ascii;
/* The value has ended at the quote mark. Combine it
* with the partial chunk if any; set it for the current
* attribute.
@@ -1341,19 +1400,19 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
add_to_partial (context, context->start, context->iter);
g_assert (context->cur_attr >= 0);
-
+
if (unescape_gstring_inplace (context, context->partial_chunk, &is_ascii, error) &&
- (is_ascii || text_validate (context, context->partial_chunk->str,
- context->partial_chunk->len, error)))
+ (is_ascii || text_validate (context, context->partial_chunk->str,
+ context->partial_chunk->len, error)))
{
/* success, advance past quote and set state. */
context->attr_values[context->cur_attr] = context->partial_chunk;
- context->partial_chunk = NULL;
+ context->partial_chunk = NULL;
advance_char (context);
context->state = STATE_BETWEEN_ATTRIBUTES;
context->start = NULL;
}
-
+
truncate_partial (context);
}
break;
@@ -1375,25 +1434,24 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
if (context->iter != context->current_text_end)
{
- gboolean is_ascii;
+ gboolean is_ascii;
/* The text has ended at the open angle. Call the text
* callback.
*/
-
if (unescape_gstring_inplace (context, context->partial_chunk, &is_ascii, error) &&
- (is_ascii || text_validate (context, context->partial_chunk->str,
- context->partial_chunk->len, error)))
+ (is_ascii || text_validate (context, context->partial_chunk->str,
+ context->partial_chunk->len, error)))
{
GError *tmp_error = NULL;
if (context->parser->text)
(*context->parser->text) (context,
- context->partial_chunk->str,
- context->partial_chunk->len,
+ context->partial_chunk->str,
+ context->partial_chunk->len,
context->user_data,
&tmp_error);
-
+
if (tmp_error == NULL)
{
/* advance past open angle and set state. */
@@ -1437,114 +1495,114 @@ g_markup_parse_context_parse (GMarkupParseContext *context,
case STATE_INSIDE_CLOSE_TAG_NAME:
/* Possible next state: AFTER_CLOSE_TAG_NAME */
advance_to_name_end (context);
- add_to_partial (context, context->start, context->iter);
+ add_to_partial (context, context->start, context->iter);
if (context->iter != context->current_text_end)
- context->state = STATE_AFTER_CLOSE_TAG_NAME;
- break;
+ context->state = STATE_AFTER_CLOSE_TAG_NAME;
+ break;
- case STATE_AFTER_CLOSE_TAG_NAME:
+ case STATE_AFTER_CLOSE_TAG_NAME:
/* Possible next state: AFTER_CLOSE_TAG_SLASH */
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- GString *close_name;
+ skip_spaces (context);
- close_name = context->partial_chunk;
- context->partial_chunk = NULL;
-
- if (*context->iter != '>')
- {
- gchar buf[8];
+ if (context->iter != context->current_text_end)
+ {
+ GString *close_name;
+
+ close_name = context->partial_chunk;
+ context->partial_chunk = NULL;
+
+ if (*context->iter != '>')
+ {
+ gchar buf[8];
+
+ set_error (context,
+ error,
+ G_MARKUP_ERROR_PARSE,
+ _("'%s' is not a valid character following "
+ "the close element name '%s'; the allowed "
+ "character is '>'"),
+ utf8_str (context->iter, buf),
+ close_name->str);
+ }
+ else if (context->tag_stack == NULL)
+ {
+ set_error (context,
+ error,
+ G_MARKUP_ERROR_PARSE,
+ _("Element '%s' was closed, no element "
+ "is currently open"),
+ close_name->str);
+ }
+ else if (strcmp (close_name->str, current_element (context)) != 0)
+ {
+ set_error (context,
+ error,
+ G_MARKUP_ERROR_PARSE,
+ _("Element '%s' was closed, but the currently "
+ "open element is '%s'"),
+ close_name->str,
+ current_element (context));
+ }
+ else
+ {
+ GError *tmp_error;
+ advance_char (context);
+ context->state = STATE_AFTER_CLOSE_ANGLE;
+ context->start = NULL;
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid character following "
- "the close element name '%s'; the allowed "
- "character is '>'"),
- utf8_str (context->iter, buf),
- close_name->str);
- }
- else if (context->tag_stack == NULL)
- {
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Element '%s' was closed, no element "
- "is currently open"),
- close_name->str);
- }
- else if (strcmp (close_name->str, current_element (context)) != 0)
- {
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Element '%s' was closed, but the currently "
- "open element is '%s'"),
- close_name->str,
- current_element (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);
-
+ /* 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)
+ pop_tag (context);
+
+ if (tmp_error)
propagate_error (context, error, tmp_error);
}
- context->partial_chunk = close_name;
- truncate_partial (context);
+ context->partial_chunk = close_name;
+ truncate_partial (context);
}
break;
-
+
case STATE_INSIDE_PASSTHROUGH:
/* Possible next state: AFTER_CLOSE_ANGLE */
do
{
- if (*context->iter == '<')
- context->balance++;
- if (*context->iter == '>')
- {
- gchar *str;
- gsize len;
+ if (*context->iter == '<')
+ context->balance++;
+ if (*context->iter == '>')
+ {
+ gchar *str;
+ gsize len;
- context->balance--;
- add_to_partial (context, context->start, context->iter);
- context->start = context->iter;
+ context->balance--;
+ add_to_partial (context, context->start, context->iter);
+ context->start = context->iter;
- str = context->partial_chunk->str;
- len = context->partial_chunk->len;
+ str = context->partial_chunk->str;
+ len = context->partial_chunk->len;
- if (str[1] == '?' && str[len - 1] == '?')
- break;
- if (strncmp (str, "