| 3481 | } |
| 3482 | |
| 3483 | static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk) |
| 3484 | { |
| 3485 | // early-out for empty documents |
| 3486 | if (length == 0) |
| 3487 | return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); |
| 3488 | |
| 3489 | // get last child of the root before parsing |
| 3490 | xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0; |
| 3491 | |
| 3492 | // create parser on stack |
| 3493 | xml_parser parser(static_cast<xml_allocator*>(xmldoc)); |
| 3494 | |
| 3495 | // save last character and make buffer zero-terminated (speeds up parsing) |
| 3496 | char_t endch = buffer[length - 1]; |
| 3497 | buffer[length - 1] = 0; |
| 3498 | |
| 3499 | // skip BOM to make sure it does not end up as part of parse output |
| 3500 | char_t* buffer_data = parse_skip_bom(buffer); |
| 3501 | |
| 3502 | // perform actual parsing |
| 3503 | parser.parse_tree(buffer_data, root, optmsk, endch); |
| 3504 | |
| 3505 | xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); |
| 3506 | assert(result.offset >= 0 && static_cast<size_t>(result.offset) <= length); |
| 3507 | |
| 3508 | if (result) |
| 3509 | { |
| 3510 | // since we removed last character, we have to handle the only possible false positive (stray <) |
| 3511 | if (endch == '<') |
| 3512 | return make_parse_result(status_unrecognized_tag, length - 1); |
| 3513 | |
| 3514 | // check if there are any element nodes parsed |
| 3515 | xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0; |
| 3516 | |
| 3517 | if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) |
| 3518 | return make_parse_result(status_no_document_element, length - 1); |
| 3519 | } |
| 3520 | else |
| 3521 | { |
| 3522 | // roll back offset if it occurs on a null terminator in the source buffer |
| 3523 | if (result.offset > 0 && static_cast<size_t>(result.offset) == length - 1 && endch == 0) |
| 3524 | result.offset--; |
| 3525 | } |
| 3526 | |
| 3527 | return result; |
| 3528 | } |
| 3529 | }; |
| 3530 | |
| 3531 | // Output facilities |
no test coverage detected