Public Member Functions | Static Public Member Functions | Public Attributes
xml_parser Struct Reference
Collaboration diagram for xml_parser:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 xml_parser (const xml_allocator &alloc_)
char_t * parse_doctype_primitive (char_t *s)
char_t * parse_doctype_ignore (char_t *s)
char_t * parse_doctype_group (char_t *s, char_t endch, bool toplevel)
char_t * parse_exclamation (char_t *s, xml_node_struct *cursor, unsigned int optmsk, char_t endch)
char_t * parse_question (char_t *s, xml_node_struct *&ref_cursor, unsigned int optmsk, char_t endch)
char_t * parse_tree (char_t *s, xml_node_struct *root, unsigned int optmsk, char_t endch)

Static Public Member Functions

static char_t * parse_skip_bom (char_t *s)
static bool has_element_node_siblings (xml_node_struct *node)
static xml_parse_result parse (char_t *buffer, size_t length, xml_document_struct *xmldoc, xml_node_struct *root, unsigned int optmsk)

Public Attributes

xml_allocator alloc
char_t * error_offset
xml_parse_status error_status

Detailed Description

Definition at line 2224 of file pugixml.cpp.


Constructor & Destructor Documentation

xml_parser::xml_parser ( const xml_allocator alloc_) [inline]

Definition at line 2230 of file pugixml.cpp.

                                                       : alloc(alloc_), error_offset(0), error_status(status_ok)
                {
                }

Member Function Documentation

static bool xml_parser::has_element_node_siblings ( xml_node_struct *  node) [inline, static]

Definition at line 2793 of file pugixml.cpp.

References xml_memory_page_type_mask.

Referenced by parse().

                {
                        while (node)
                        {
                                xml_node_type type = static_cast<xml_node_type>((node->header & impl::xml_memory_page_type_mask) + 1);
                                if (type == node_element) return true;

                                node = node->next_sibling;
                        }

                        return false;
                }
static xml_parse_result xml_parser::parse ( char_t *  buffer,
size_t  length,
xml_document_struct xmldoc,
xml_node_struct *  root,
unsigned int  optmsk 
) [inline, static]

Definition at line 2806 of file pugixml.cpp.

References alloc, error_offset, error_status, has_element_node_siblings(), make_parse_result(), parse_skip_bom(), parse_tree(), and PUGI__OPTSET.

                {
                        // allocator object is a part of document object
                        xml_allocator& alloc = *static_cast<xml_allocator*>(xmldoc);

                        // early-out for empty documents
                        if (length == 0)
                                return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element);

                        // get last child of the root before parsing
                        xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c : 0;
        
                        // create parser on stack
                        xml_parser parser(alloc);

                        // save last character and make buffer zero-terminated (speeds up parsing)
                        char_t endch = buffer[length - 1];
                        buffer[length - 1] = 0;
                        
                        // skip BOM to make sure it does not end up as part of parse output
                        char_t* buffer_data = parse_skip_bom(buffer);

                        // perform actual parsing
                        parser.parse_tree(buffer_data, root, optmsk, endch);

                        // update allocator state
                        alloc = parser.alloc;

                        xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0);
                        assert(result.offset >= 0 && static_cast<size_t>(result.offset) <= length);

                        if (result)
                        {
                                // since we removed last character, we have to handle the only possible false positive (stray <)
                                if (endch == '<')
                                        return make_parse_result(status_unrecognized_tag, length - 1);

                                // check if there are any element nodes parsed
                                xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling : root->first_child;

                                if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed))
                                        return make_parse_result(status_no_document_element, length - 1);
                        }
                        else
                        {
                                // roll back offset if it occurs on a null terminator in the source buffer
                                if (result.offset > 0 && static_cast<size_t>(result.offset) == length - 1 && endch == 0)
                                        result.offset--;
                        }

                        return result;
                }
char_t* xml_parser::parse_doctype_group ( char_t *  s,
char_t  endch,
bool  toplevel 
) [inline]

Definition at line 2300 of file pugixml.cpp.

References parse_doctype_ignore(), parse_doctype_primitive(), and PUGI__THROW_ERROR.

Referenced by parse_exclamation().

                {
                        assert((s[0] == '<' || s[0] == 0) && s[1] == '!');
                        s++;

                        while (*s)
                        {
                                if (s[0] == '<' && s[1] == '!' && s[2] != '-')
                                {
                                        if (s[2] == '[')
                                        {
                                                // ignore
                                                s = parse_doctype_ignore(s);
                                                if (!s) return s;
                                        }
                                        else
                                        {
                                                // some control group
                                                s = parse_doctype_group(s, endch, false);
                                                if (!s) return s;

                                                // skip >
                                                assert(*s == '>');
                                                s++;
                                        }
                                }
                                else if (s[0] == '<' || s[0] == '"' || s[0] == '\'')
                                {
                                        // unknown tag (forbidden), or some primitive group
                                        s = parse_doctype_primitive(s);
                                        if (!s) return s;
                                }
                                else if (*s == '>')
                                {
                                        return s;
                                }
                                else s++;
                        }

                        if (!toplevel || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s);

                        return s;
                }
char_t* xml_parser::parse_doctype_ignore ( char_t *  s) [inline]

Definition at line 2274 of file pugixml.cpp.

References PUGI__THROW_ERROR.

Referenced by parse_doctype_group().

                {
                        assert(s[0] == '<' && s[1] == '!' && s[2] == '[');
                        s++;

                        while (*s)
                        {
                                if (s[0] == '<' && s[1] == '!' && s[2] == '[')
                                {
                                        // nested ignore section
                                        s = parse_doctype_ignore(s);
                                        if (!s) return s;
                                }
                                else if (s[0] == ']' && s[1] == ']' && s[2] == '>')
                                {
                                        // ignore section end
                                        s += 3;

                                        return s;
                                }
                                else s++;
                        }

                        PUGI__THROW_ERROR(status_bad_doctype, s);
                }
char_t* xml_parser::parse_doctype_primitive ( char_t *  s) [inline]

Definition at line 2241 of file pugixml.cpp.

References PUGI__SCANFOR, and PUGI__THROW_ERROR.

Referenced by parse_doctype_group().

                {
                        if (*s == '"' || *s == '\'')
                        {
                                // quoted string
                                char_t ch = *s++;
                                PUGI__SCANFOR(*s == ch);
                                if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);

                                s++;
                        }
                        else if (s[0] == '<' && s[1] == '?')
                        {
                                // <? ... ?>
                                s += 2;
                                PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype
                                if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);

                                s += 2;
                        }
                        else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-')
                        {
                                s += 4;
                                PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype
                                if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);

                                s += 4;
                        }
                        else PUGI__THROW_ERROR(status_bad_doctype, s);

                        return s;
                }
char_t* xml_parser::parse_exclamation ( char_t *  s,
xml_node_struct *  cursor,
unsigned int  optmsk,
char_t  endch 
) [inline]

Definition at line 2344 of file pugixml.cpp.

References ct_space, parse_doctype_group(), PUGI__CHECK_ERROR, PUGI__ENDSWITH, PUGI__IS_CHARTYPE, PUGI__OPTSET, PUGI__POPNODE, PUGI__PUSHNODE, PUGI__SCANFOR, PUGI__THROW_ERROR, strconv_cdata(), and strconv_comment().

Referenced by parse_tree().

                {
                        // parse node contents, starting with exclamation mark
                        ++s;

                        if (*s == '-') // '<!-...'
                        {
                                ++s;

                                if (*s == '-') // '<!--...'
                                {
                                        ++s;

                                        if (PUGI__OPTSET(parse_comments))
                                        {
                                                PUGI__PUSHNODE(node_comment); // Append a new node on the tree.
                                                cursor->value = s; // Save the offset.
                                        }

                                        if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments))
                                        {
                                                s = strconv_comment(s, endch);

                                                if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value);
                                        }
                                        else
                                        {
                                                // Scan for terminating '-->'.
                                                PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>'));
                                                PUGI__CHECK_ERROR(status_bad_comment, s);

                                                if (PUGI__OPTSET(parse_comments))
                                                        *s = 0; // Zero-terminate this segment at the first terminating '-'.

                                                s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'.
                                        }
                                }
                                else PUGI__THROW_ERROR(status_bad_comment, s);
                        }
                        else if (*s == '[')
                        {
                                // '<![CDATA[...'
                                if (*++s=='C' && *++s=='D' && *++s=='A' && *++s=='T' && *++s=='A' && *++s == '[')
                                {
                                        ++s;

                                        if (PUGI__OPTSET(parse_cdata))
                                        {
                                                PUGI__PUSHNODE(node_cdata); // Append a new node on the tree.
                                                cursor->value = s; // Save the offset.

                                                if (PUGI__OPTSET(parse_eol))
                                                {
                                                        s = strconv_cdata(s, endch);

                                                        if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value);
                                                }
                                                else
                                                {
                                                        // Scan for terminating ']]>'.
                                                        PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>'));
                                                        PUGI__CHECK_ERROR(status_bad_cdata, s);

                                                        *s++ = 0; // Zero-terminate this segment.
                                                }
                                        }
                                        else // Flagged for discard, but we still have to scan for the terminator.
                                        {
                                                // Scan for terminating ']]>'.
                                                PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>'));
                                                PUGI__CHECK_ERROR(status_bad_cdata, s);

                                                ++s;
                                        }

                                        s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'.
                                }
                                else PUGI__THROW_ERROR(status_bad_cdata, s);
                        }
                        else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E'))
                        {
                                s -= 2;

                                if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s);

                                char_t* mark = s + 9;

                                s = parse_doctype_group(s, endch, true);
                                if (!s) return s;

                                assert((*s == 0 && endch == '>') || *s == '>');
                                if (*s) *s++ = 0;

                                if (PUGI__OPTSET(parse_doctype))
                                {
                                        while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark;

                                        PUGI__PUSHNODE(node_doctype);

                                        cursor->value = mark;

                                        PUGI__POPNODE();
                                }
                        }
                        else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s);
                        else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s);
                        else PUGI__THROW_ERROR(status_unrecognized_tag, s);

                        return s;
                }
char_t* xml_parser::parse_question ( char_t *  s,
xml_node_struct *&  ref_cursor,
unsigned int  optmsk,
char_t  endch 
) [inline]

Definition at line 2455 of file pugixml.cpp.

References ct_space, ct_start_symbol, ct_symbol, PUGI__CHECK_ERROR, PUGI__ENDSEG, PUGI__ENDSWITH, PUGI__IS_CHARTYPE, PUGI__OPTSET, PUGI__POPNODE, PUGI__PUSHNODE, PUGI__SCANFOR, PUGI__SCANWHILE, PUGI__SKIPWS, and PUGI__THROW_ERROR.

Referenced by parse_tree().

                {
                        // load into registers
                        xml_node_struct* cursor = ref_cursor;
                        char_t ch = 0;

                        // parse node contents, starting with question mark
                        ++s;

                        // read PI target
                        char_t* target = s;

                        if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s);

                        PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol));
                        PUGI__CHECK_ERROR(status_bad_pi, s);

                        // determine node type; stricmp / strcasecmp is not portable
                        bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s;

                        if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi))
                        {
                                if (declaration)
                                {
                                        // disallow non top-level declarations
                                        if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s);

                                        PUGI__PUSHNODE(node_declaration);
                                }
                                else
                                {
                                        PUGI__PUSHNODE(node_pi);
                                }

                                cursor->name = target;

                                PUGI__ENDSEG();

                                // parse value/attributes
                                if (ch == '?')
                                {
                                        // empty node
                                        if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s);
                                        s += (*s == '>');

                                        PUGI__POPNODE();
                                }
                                else if (PUGI__IS_CHARTYPE(ch, ct_space))
                                {
                                        PUGI__SKIPWS();

                                        // scan for tag end
                                        char_t* value = s;

                                        PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>'));
                                        PUGI__CHECK_ERROR(status_bad_pi, s);

                                        if (declaration)
                                        {
                                                // replace ending ? with / so that 'element' terminates properly
                                                *s = '/';

                                                // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES
                                                s = value;
                                        }
                                        else
                                        {
                                                // store value and step over >
                                                cursor->value = value;
                                                PUGI__POPNODE();

                                                PUGI__ENDSEG();

                                                s += (*s == '>');
                                        }
                                }
                                else PUGI__THROW_ERROR(status_bad_pi, s);
                        }
                        else
                        {
                                // scan for tag end
                                PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>'));
                                PUGI__CHECK_ERROR(status_bad_pi, s);

                                s += (s[1] == '>' ? 2 : 1);
                        }

                        // store from registers
                        ref_cursor = cursor;

                        return s;
                }
static char_t* xml_parser::parse_skip_bom ( char_t *  s) [inline, static]

Definition at line 2787 of file pugixml.cpp.

Referenced by parse().

                {
                        return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s;
                }
char_t* xml_parser::parse_tree ( char_t *  s,
xml_node_struct *  root,
unsigned int  optmsk,
char_t  endch 
) [inline]

Definition at line 2548 of file pugixml.cpp.

References alloc, append_new_attribute(), ct_space, ct_start_symbol, ct_symbol, get_strconv_attribute(), get_strconv_pcdata(), parse_exclamation(), parse_question(), PUGI__CHECK_ERROR, PUGI__ENDSEG, PUGI__ENDSWITH, PUGI__IS_CHARTYPE, PUGI__OPTSET, PUGI__POPNODE, PUGI__PUSHNODE, PUGI__SCANFOR, PUGI__SCANWHILE_UNROLL, PUGI__SKIPWS, and PUGI__THROW_ERROR.

Referenced by parse().

                {
                        strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk);
                        strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk);
                        
                        char_t ch = 0;
                        xml_node_struct* cursor = root;
                        char_t* mark = s;

                        while (*s != 0)
                        {
                                if (*s == '<')
                                {
                                        ++s;

                                LOC_TAG:
                                        if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...'
                                        {
                                                PUGI__PUSHNODE(node_element); // Append a new node to the tree.

                                                cursor->name = s;

                                                PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator.
                                                PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.

                                                if (ch == '>')
                                                {
                                                        // end of tag
                                                }
                                                else if (PUGI__IS_CHARTYPE(ch, ct_space))
                                                {
                                                LOC_ATTRIBUTES:
                                                        while (true)
                                                        {
                                                                PUGI__SKIPWS(); // Eat any whitespace.
                                                
                                                                if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #...
                                                                {
                                                                        xml_attribute_struct* a = append_new_attribute(cursor, alloc); // Make space for this attribute.
                                                                        if (!a) PUGI__THROW_ERROR(status_out_of_memory, s);

                                                                        a->name = s; // Save the offset.

                                                                        PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator.
                                                                        PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance

                                                                        PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
                                                                        PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance

                                                                        if (PUGI__IS_CHARTYPE(ch, ct_space))
                                                                        {
                                                                                PUGI__SKIPWS(); // Eat any whitespace.
                                                                                PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance

                                                                                ch = *s;
                                                                                ++s;
                                                                        }
                                                                        
                                                                        if (ch == '=') // '<... #=...'
                                                                        {
                                                                                PUGI__SKIPWS(); // Eat any whitespace.

                                                                                if (*s == '"' || *s == '\'') // '<... #="...'
                                                                                {
                                                                                        ch = *s; // Save quote char to avoid breaking on "''" -or- '""'.
                                                                                        ++s; // Step over the quote.
                                                                                        a->value = s; // Save the offset.

                                                                                        s = strconv_attribute(s, ch);
                                                                                
                                                                                        if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value);

                                                                                        // After this line the loop continues from the start;
                                                                                        // Whitespaces, / and > are ok, symbols and EOF are wrong,
                                                                                        // everything else will be detected
                                                                                        if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s);
                                                                                }
                                                                                else PUGI__THROW_ERROR(status_bad_attribute, s);
                                                                        }
                                                                        else PUGI__THROW_ERROR(status_bad_attribute, s);
                                                                }
                                                                else if (*s == '/')
                                                                {
                                                                        ++s;
                                                                        
                                                                        if (*s == '>')
                                                                        {
                                                                                PUGI__POPNODE();
                                                                                s++;
                                                                                break;
                                                                        }
                                                                        else if (*s == 0 && endch == '>')
                                                                        {
                                                                                PUGI__POPNODE();
                                                                                break;
                                                                        }
                                                                        else PUGI__THROW_ERROR(status_bad_start_element, s);
                                                                }
                                                                else if (*s == '>')
                                                                {
                                                                        ++s;

                                                                        break;
                                                                }
                                                                else if (*s == 0 && endch == '>')
                                                                {
                                                                        break;
                                                                }
                                                                else PUGI__THROW_ERROR(status_bad_start_element, s);
                                                        }

                                                        // !!!
                                                }
                                                else if (ch == '/') // '<#.../'
                                                {
                                                        if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s);

                                                        PUGI__POPNODE(); // Pop.

                                                        s += (*s == '>');
                                                }
                                                else if (ch == 0)
                                                {
                                                        // we stepped over null terminator, backtrack & handle closing tag
                                                        --s;
                                                        
                                                        if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s);
                                                }
                                                else PUGI__THROW_ERROR(status_bad_start_element, s);
                                        }
                                        else if (*s == '/')
                                        {
                                                ++s;

                                                char_t* name = cursor->name;
                                                if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s);
                                                
                                                while (PUGI__IS_CHARTYPE(*s, ct_symbol))
                                                {
                                                        if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, s);
                                                }

                                                if (*name)
                                                {
                                                        if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s);
                                                        else PUGI__THROW_ERROR(status_end_element_mismatch, s);
                                                }
                                                        
                                                PUGI__POPNODE(); // Pop.

                                                PUGI__SKIPWS();

                                                if (*s == 0)
                                                {
                                                        if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s);
                                                }
                                                else
                                                {
                                                        if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s);
                                                        ++s;
                                                }
                                        }
                                        else if (*s == '?') // '<?...'
                                        {
                                                s = parse_question(s, cursor, optmsk, endch);
                                                if (!s) return s;

                                                assert(cursor);
                                                if ((cursor->header & xml_memory_page_type_mask) + 1 == node_declaration) goto LOC_ATTRIBUTES;
                                        }
                                        else if (*s == '!') // '<!...'
                                        {
                                                s = parse_exclamation(s, cursor, optmsk, endch);
                                                if (!s) return s;
                                        }
                                        else if (*s == 0 && endch == '?') PUGI__THROW_ERROR(status_bad_pi, s);
                                        else PUGI__THROW_ERROR(status_unrecognized_tag, s);
                                }
                                else
                                {
                                        mark = s; // Save this offset while searching for a terminator.

                                        PUGI__SKIPWS(); // Eat whitespace if no genuine PCDATA here.

                                        if (*s == '<' || !*s)
                                        {
                                                // We skipped some whitespace characters because otherwise we would take the tag branch instead of PCDATA one
                                                assert(mark != s);

                                                if (!PUGI__OPTSET(parse_ws_pcdata | parse_ws_pcdata_single) || PUGI__OPTSET(parse_trim_pcdata))
                                                {
                                                        continue;
                                                }
                                                else if (PUGI__OPTSET(parse_ws_pcdata_single))
                                                {
                                                        if (s[0] != '<' || s[1] != '/' || cursor->first_child) continue;
                                                }
                                        }

                                        if (!PUGI__OPTSET(parse_trim_pcdata))
                                                s = mark;
                                                        
                                        if (cursor->parent || PUGI__OPTSET(parse_fragment))
                                        {
                                                PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree.
                                                cursor->value = s; // Save the offset.

                                                s = strconv_pcdata(s);
                                                                
                                                PUGI__POPNODE(); // Pop since this is a standalone.
                                                
                                                if (!*s) break;
                                        }
                                        else
                                        {
                                                PUGI__SCANFOR(*s == '<'); // '...<'
                                                if (!*s) break;
                                                
                                                ++s;
                                        }

                                        // We're after '<'
                                        goto LOC_TAG;
                                }
                        }

                        // check that last tag is closed
                        if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s);

                        return s;
                }

Member Data Documentation

Definition at line 2226 of file pugixml.cpp.

Referenced by parse(), and parse_tree().

Definition at line 2227 of file pugixml.cpp.

Referenced by parse().

xml_parse_status xml_parser::error_status

Definition at line 2228 of file pugixml.cpp.

Referenced by parse().


The documentation for this struct was generated from the following file:

Generated on Mon Sep 15 2014 01:23:55 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001