#include "ui_core/layout_xml.h" #include "ui_core/layout_value.h" #include namespace pp::ui { namespace { [[nodiscard]] pp::foundation::Status visit_element(const tinyxml2::XMLElement& element, LayoutParseSummary& summary) { ++summary.node_count; for (const char* name : { "width", "height" }) { const char* value = element.Attribute(name); if (value == nullptr) { continue; } const auto length = parse_layout_length(value); if (!length) { return length.status(); } ++summary.length_attribute_count; } for (const tinyxml2::XMLElement* child = element.FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) { const auto status = visit_element(*child, summary); if (!status.ok()) { return status; } } return pp::foundation::Status::success(); } } pp::foundation::Result parse_layout_xml(std::string_view xml) { if (xml.empty()) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("layout XML must not be empty")); } tinyxml2::XMLDocument document; const auto error = document.Parse(xml.data(), xml.size()); if (error != tinyxml2::XML_SUCCESS) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("layout XML could not be parsed")); } const tinyxml2::XMLElement* root = document.RootElement(); if (root == nullptr) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("layout XML has no root element")); } LayoutParseSummary summary; const auto status = visit_element(*root, summary); if (!status.ok()) { return pp::foundation::Result::failure(status); } return pp::foundation::Result::success(summary); } }