From: Matthias Clasen Date: Tue, 18 Jan 2011 04:46:20 +0000 (-0500) Subject: Move GMarkup docs inline X-Git-Tag: 2.27.92~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d2347f34fded2651e47a60814f600c173b8ca5e7;p=platform%2Fupstream%2Fglib.git Move GMarkup docs inline --- diff --git a/docs/reference/glib/tmpl/.gitignore b/docs/reference/glib/tmpl/.gitignore index 638e83e..8ad3a7d 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 7a14ecb..0000000 --- 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: &amp; &lt; &gt; &quot; &apos; - - - - -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 b9e8c31..ccdb500 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: + * &amp; &lt; &gt; &quot; &apos; + * + * 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 == '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; - } - } + { + from++; + if (*from == '#') + { + gboolean is_hex = FALSE; + gulong l; + gchar *end = NULL; + + 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; + } + } } 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); - - 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)); - } - } + 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)); + } + } break; case STATE_INSIDE_ATTRIBUTE_VALUE_SQ: case STATE_INSIDE_ATTRIBUTE_VALUE_DQ: /* Possible next states: BETWEEN_ATTRIBUTES */ - { - gchar delim; - - if (context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ) - { - delim = '\''; - } - else - { - delim = '"'; - } - - do - { - if (*context->iter == delim) - break; - } - while (advance_char (context)); - } + { + gchar delim; + + if (context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ) + { + delim = '\''; + } + else + { + delim = '"'; + } + + 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; - - 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; - + skip_spaces (context); + + 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; + 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; - - context->balance--; - add_to_partial (context, context->start, context->iter); - context->start = context->iter; - - str = context->partial_chunk->str; - len = context->partial_chunk->len; - - if (str[1] == '?' && str[len - 1] == '?') - break; - if (strncmp (str, "