From 87189d03fd052873cd0fe9af83556c44b5f0689d Mon Sep 17 00:00:00 2001 From: Panos Karabelas Date: Mon, 25 Sep 2023 17:41:44 +0100 Subject: [PATCH] [XML] Deleted XmlDocument since it was wrapping pugixml for no good reason, pugxml is now used directly and it's has been include in the engine as source (not a dependency anymore) --- build_scripts/premake.lua | 1 - runtime/Core/Settings.cpp | 5 +- runtime/IO/XmlDocument.cpp | 356 ------------------ runtime/IO/XmlDocument.h | 107 ------ .../pugixml => runtime/IO}/pugiconfig.hpp | 6 +- .../pugixml => runtime/IO}/pugixml.cpp | 342 ++++++++++++----- .../pugixml => runtime/IO}/pugixml.hpp | 29 +- runtime/Rendering/Material.cpp | 146 +++---- third_party/pugixml/LICENSE.md | 24 -- third_party/pugixml/version.txt | 1 - 10 files changed, 347 insertions(+), 670 deletions(-) delete mode 100644 runtime/IO/XmlDocument.cpp delete mode 100644 runtime/IO/XmlDocument.h rename {third_party/pugixml => runtime/IO}/pugiconfig.hpp (95%) rename {third_party/pugixml => runtime/IO}/pugixml.cpp (97%) rename {third_party/pugixml => runtime/IO}/pugixml.hpp (98%) delete mode 100644 third_party/pugixml/LICENSE.md delete mode 100644 third_party/pugixml/version.txt diff --git a/build_scripts/premake.lua b/build_scripts/premake.lua index 4a82d0783..bfcedc513 100644 --- a/build_scripts/premake.lua +++ b/build_scripts/premake.lua @@ -191,7 +191,6 @@ function runtime_project_configuration() includedirs { "../third_party/free_type" } includedirs { "../third_party/compressonator" } includedirs { "../third_party/renderdoc" } - includedirs { "../third_party/pugixml" } includedirs(API_INCLUDES[ARG_API_GRAPHICS] or {}) includedirs { "../runtime/Core" } -- This is here because clang needs the full pre-compiled header path diff --git a/runtime/Core/Settings.cpp b/runtime/Core/Settings.cpp index 252c87c31..de2d185ce 100644 --- a/runtime/Core/Settings.cpp +++ b/runtime/Core/Settings.cpp @@ -25,8 +25,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "../Core/ThreadPool.h" #include "../Rendering/Renderer.h" #include "../Input/Input.h" -#include "../IO/XmlDocument.h" -#include "pugixml.hpp" +SP_WARNINGS_OFF +#include "../IO/pugixml.hpp" +SP_WARNINGS_ON //================================= //= NAMESPACES ================ diff --git a/runtime/IO/XmlDocument.cpp b/runtime/IO/XmlDocument.cpp deleted file mode 100644 index 9a88f7992..000000000 --- a/runtime/IO/XmlDocument.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* -Copyright(c) 2016-2023 Panos Karabelas - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -//= INCLUDES =========== -#include "pch.h" -#include "XmlDocument.h" -SP_WARNINGS_OFF -#include "pugixml.hpp" -SP_WARNINGS_ON -//====================== - -//= NAMESPACES ================ -using namespace std; -using namespace pugi; -using namespace Spartan::Math; -//============================= - -namespace Spartan -{ - XmlDocument::XmlDocument() - { - // generate new XML document within memory - m_document = make_unique(); - - // generate XML declaration - auto decleration_node = m_document->append_child(node_declaration); - decleration_node.append_attribute("version") = "1.0"; - decleration_node.append_attribute("encoding") = "ISO-8859-1"; - decleration_node.append_attribute("standalone") = "yes"; - } - - XmlDocument::~XmlDocument() - { - m_nodes.clear(); - } - - void XmlDocument::AddNode(const string& node_name) - { - if (!m_document) - return; - - const auto node = make_shared(m_document->append_child(node_name.c_str())); - m_nodes.push_back(node); - } - - bool XmlDocument::AddChildNode(const string& parent_node_name, const string& child_node_name) - { - auto parent_node = GetNodeByName(parent_node_name); - if (!parent_node) - { - SP_LOG_WARNING("Can't add child node \"%s\", parent node \"%s\" doesn't exist.", child_node_name.c_str(), parent_node_name.c_str()); - return false; - } - - const auto node = make_shared(parent_node->append_child(child_node_name.c_str())); - m_nodes.push_back(node); - - return true; - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, const string& value) - { - auto node = GetNodeByName(nodeName); - if (!node) - { - SP_LOG_WARNING("Can't add attribute \"%s\", node \"%s\" doesn't exist.", attributeName.c_str(), nodeName.c_str()); - return false; - } - - node->append_attribute(attributeName.c_str()) = value.c_str(); - - return true; - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, bool value) - { - const string valueStr = value ? "true" : "false"; - return AddAttribute(nodeName, attributeName, valueStr); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, int value) - { - return AddAttribute(nodeName, attributeName, to_string(value)); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, uint32_t value) - { - return AddAttribute(nodeName, attributeName, to_string(value)); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, float value) - { - return AddAttribute(nodeName, attributeName, to_string(value)); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, double value) - { - return AddAttribute(nodeName, attributeName, to_string(value)); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, Vector2& value) - { - return AddAttribute(nodeName, attributeName, value.ToString()); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, Vector3& value) - { - return AddAttribute(nodeName, attributeName, value.ToString()); - } - - bool XmlDocument::AddAttribute(const string& nodeName, const string& attributeName, Vector4& value) - { - return AddAttribute(nodeName, attributeName, value.ToString()); - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string& attributeName, string* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.value(); - - return true; - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string& attributeName, int* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.as_int(); - - return true; - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string&attributeName, uint32_t* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.as_uint(); - - return true; - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string& attributeName, bool* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.as_bool(); - - return true; - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string& attributeName, float* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.as_float(); - - return true; - } - - bool XmlDocument::GetAttribute(const string& nodeName, const string& attributeName, double* value) - { - const xml_attribute attribute = GetAttribute(nodeName, attributeName); - - if (!attribute) - return false; - - // Get value - (*value) = attribute.as_double(); - - return true; - } - - bool XmlDocument::GetAttribute(const std::string& nodeName, const std::string& attributeName, Vector2* value) - { - string valueStr; - if (!GetAttribute(nodeName, attributeName, &valueStr)) - return false; - - value->x = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "X:", ",").c_str())); - value->y = static_cast(atof(FileSystem::GetStringAfterExpression(valueStr, "Y:").c_str())); - - return true; - } - - bool XmlDocument::GetAttribute(const std::string& nodeName, const std::string& attributeName, Vector3* value) - { - string valueStr; - if (!GetAttribute(nodeName, attributeName, &valueStr)) - return false; - - value->x = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "X:", ",").c_str())); - value->y = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "Y:", ",").c_str())); - value->z = static_cast(atof(FileSystem::GetStringAfterExpression(valueStr, "Z:").c_str())); - - return true; - } - - bool XmlDocument::GetAttribute(const std::string& nodeName, const std::string& attributeName, Vector4* value) - { - string valueStr; - if (!GetAttribute(nodeName, attributeName, &valueStr)) - return false; - - value->x = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "X:", ",").c_str())); - value->y = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "Y:", ",").c_str())); - value->z = static_cast(atof(FileSystem::GetStringBetweenExpressions(valueStr, "Z:", ",").c_str())); - value->w = static_cast(atof(FileSystem::GetStringAfterExpression(valueStr, "W:").c_str())); - - return true; - } - //= IO ======================================= - bool XmlDocument::Load(const string& filePath) - { - m_document = make_unique(); - const xml_parse_result result = m_document->load_file(filePath.c_str()); - - if (result.status != status_ok) - { - if (result.status == status_file_not_found) - { - SP_LOG_ERROR("File \"%s\" was not found.", filePath.c_str()); - } - else - { - SP_LOG_ERROR("%s", result.description()); - } - - m_document.release(); - return false; - } - - GetAllNodes(); - - return true; - } - - bool XmlDocument::Save(const string& path) const - { - if (!m_document) - return false; - - if (FileSystem::Exists(path)) - { - FileSystem::Delete(path); - } - - return m_document->save_file(path.c_str()); - } - - xml_attribute XmlDocument::GetAttribute(const string& nodeName, const string& attributeName) - { - xml_attribute attribute; - - // Make sure the nod exists - const auto node = GetNodeByName(nodeName); - if (!node) - { - SP_LOG_WARNING("Can't get attribute \"%s\", node \"%s\" doesn't exist.", attributeName.c_str(), nodeName.c_str()); - return attribute; - } - - // Make sure the attribute exists - attribute = node->attribute(attributeName.c_str()); - if (!attribute) - { - SP_LOG_WARNING("Can't get attribute, attribute \"%s\" doesn't exist.", attributeName.c_str()); - } - - return attribute; - } - - shared_ptr XmlDocument::GetNodeByName(const string& name) - { - for (const auto& node : m_nodes) - { - if (node->name() == name) - { - return node; - } - } - - return shared_ptr(); - } - - void XmlDocument::GetAllNodes() - { - if (!m_document) - return; - - m_nodes.clear(); - m_nodes.shrink_to_fit(); - - for (xml_node child = m_document->first_child(); child; child = child.next_sibling()) - { - m_nodes.push_back(make_shared(child)); - if (child.last_child()) - { - GetNodes(child); - } - } - } - - void XmlDocument::GetNodes(xml_node node) - { - if (!node) - return; - - for (xml_node child = node.first_child(); child; child = child.next_sibling()) - { - m_nodes.push_back(make_shared(child)); - if (child.last_child()) - { - GetNodes(child); - } - } - } -} diff --git a/runtime/IO/XmlDocument.h b/runtime/IO/XmlDocument.h deleted file mode 100644 index 04799f203..000000000 --- a/runtime/IO/XmlDocument.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright(c) 2016-2023 Panos Karabelas - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#pragma once - -//= INCLUDES =================== -#include -#include -#include -#include "../Core/Definitions.h" -//============================== - -//= FORWARD DECLARATIONS = -namespace pugi -{ - class xml_document; - class xml_node; - class xml_attribute; -} -//======================== - -namespace Spartan -{ - //= FORWARD DECLARATIONS = - namespace Math - { - class Vector2; - class Vector3; - class Vector4; - } - //======================== - - class SP_CLASS XmlDocument - { - public: - XmlDocument(); - ~XmlDocument(); - - //= NODES ================================================================================= - void AddNode(const std::string& node_name); - bool AddChildNode(const std::string& parent_node_name, const std::string& child_node_name); - //========================================================================================= - - //= NODE ATTRIBUTES ========================================================================================= - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, const std::string& value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, bool value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, int value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, uint32_t value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, float value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, double value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector2& value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector3& value); - bool AddAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector4& value); - - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, std::string* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, int* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, uint32_t* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, bool* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, float* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, double* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector2* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector3* value); - bool GetAttribute(const std::string& node_name, const std::string& attribute_name, Math::Vector4* value); - - template - T GetAttributeAs(const std::string& node_name, const std::string& attribute_name) - { - T value; - GetAttribute(node_name, attribute_name, &value); - return value; - } - //=========================================================================================================== - - - //= IO ====================================== - bool Load(const std::string& filePath); - bool Save(const std::string& filePath) const; - //=========================================== - - private: - pugi::xml_attribute GetAttribute(const std::string& nodeName, const std::string& attributeName); - std::shared_ptr GetNodeByName(const std::string& name); - void GetAllNodes(); - void GetNodes(pugi::xml_node node); - - std::unique_ptr m_document; - std::vector> m_nodes; - }; -} diff --git a/third_party/pugixml/pugiconfig.hpp b/runtime/IO/pugiconfig.hpp similarity index 95% rename from third_party/pugixml/pugiconfig.hpp rename to runtime/IO/pugiconfig.hpp index 03f854bf1..9bf2efd39 100644 --- a/third_party/pugixml/pugiconfig.hpp +++ b/runtime/IO/pugiconfig.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -52,7 +52,7 @@ #endif /** - * Copyright (c) 2006-2020 Arseny Kapoulkine + * Copyright (c) 2006-2022 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/third_party/pugixml/pugixml.cpp b/runtime/IO/pugixml.cpp similarity index 97% rename from third_party/pugixml/pugixml.cpp rename to runtime/IO/pugixml.cpp index efdcdf699..c63645b67 100644 --- a/third_party/pugixml/pugixml.cpp +++ b/runtime/IO/pugixml.cpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -132,8 +132,10 @@ using std::memset; #endif // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features -#if defined(_MSC_VER) && !defined(__S3E__) +#if defined(_MSC_VER) && !defined(__S3E__) && !defined(_WIN32_WCE) # define PUGI__MSVC_CRT_VERSION _MSC_VER +#elif defined(_WIN32_WCE) +# define PUGI__MSVC_CRT_VERSION 1310 // MSVC7.1 #endif // Not all platforms have snprintf; we define a wrapper that uses snprintf if possible. This only works with buffers with a known size. @@ -526,7 +528,8 @@ PUGI__NS_BEGIN xml_memory_page* page = xml_memory_page::construct(memory); assert(page); - page->allocator = _root->allocator; + assert(this == _root->allocator); + page->allocator = this; return page; } @@ -1273,12 +1276,14 @@ PUGI__NS_BEGIN child->parent = parent; - if (node->next_sibling) - node->next_sibling->prev_sibling_c = child; + xml_node_struct* next = node->next_sibling; + + if (next) + next->prev_sibling_c = child; else parent->first_child->prev_sibling_c = child; - child->next_sibling = node->next_sibling; + child->next_sibling = next; child->prev_sibling_c = node; node->next_sibling = child; @@ -1290,12 +1295,14 @@ PUGI__NS_BEGIN child->parent = parent; - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = child; + xml_node_struct* prev = node->prev_sibling_c; + + if (prev->next_sibling) + prev->next_sibling = child; else parent->first_child = child; - child->prev_sibling_c = node->prev_sibling_c; + child->prev_sibling_c = prev; child->next_sibling = node; node->prev_sibling_c = child; @@ -1305,15 +1312,18 @@ PUGI__NS_BEGIN { xml_node_struct* parent = node->parent; - if (node->next_sibling) - node->next_sibling->prev_sibling_c = node->prev_sibling_c; + xml_node_struct* next = node->next_sibling; + xml_node_struct* prev = node->prev_sibling_c; + + if (next) + next->prev_sibling_c = prev; else - parent->first_child->prev_sibling_c = node->prev_sibling_c; + parent->first_child->prev_sibling_c = prev; - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = node->next_sibling; + if (prev->next_sibling) + prev->next_sibling = next; else - parent->first_child = node->next_sibling; + parent->first_child = next; node->parent = 0; node->prev_sibling_c = 0; @@ -1357,39 +1367,46 @@ PUGI__NS_BEGIN inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) { - if (place->next_attribute) - place->next_attribute->prev_attribute_c = attr; + xml_attribute_struct* next = place->next_attribute; + + if (next) + next->prev_attribute_c = attr; else node->first_attribute->prev_attribute_c = attr; - attr->next_attribute = place->next_attribute; + attr->next_attribute = next; attr->prev_attribute_c = place; place->next_attribute = attr; } inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) { - if (place->prev_attribute_c->next_attribute) - place->prev_attribute_c->next_attribute = attr; + xml_attribute_struct* prev = place->prev_attribute_c; + + if (prev->next_attribute) + prev->next_attribute = attr; else node->first_attribute = attr; - attr->prev_attribute_c = place->prev_attribute_c; + attr->prev_attribute_c = prev; attr->next_attribute = place; place->prev_attribute_c = attr; } inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) { - if (attr->next_attribute) - attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; + xml_attribute_struct* next = attr->next_attribute; + xml_attribute_struct* prev = attr->prev_attribute_c; + + if (next) + next->prev_attribute_c = prev; else - node->first_attribute->prev_attribute_c = attr->prev_attribute_c; + node->first_attribute->prev_attribute_c = prev; - if (attr->prev_attribute_c->next_attribute) - attr->prev_attribute_c->next_attribute = attr->next_attribute; + if (prev->next_attribute) + prev->next_attribute = next; else - node->first_attribute = attr->next_attribute; + node->first_attribute = next; attr->prev_attribute_c = 0; attr->next_attribute = 0; @@ -4704,6 +4721,9 @@ PUGI__NS_BEGIN // get actual encoding xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); + // if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it + auto_deleter contents_guard(own ? contents : 0, xml_memory::deallocate); + // get private buffer char_t* buffer = 0; size_t length = 0; @@ -4711,6 +4731,9 @@ PUGI__NS_BEGIN // coverity[var_deref_model] if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); + // after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it + contents_guard.release(); + // delete original buffer if we performed a conversion if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); @@ -4732,7 +4755,7 @@ PUGI__NS_BEGIN // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 // there are 64-bit versions of fseek/ftell, let's use them typedef __int64 length_type; @@ -5047,7 +5070,7 @@ PUGI__NS_BEGIN xml_writer_file writer(file); doc.save(writer, indent, flags, encoding); - return ferror(file) == 0; + return fflush(file) == 0 && ferror(file) == 0; } struct name_null_sentry @@ -5182,53 +5205,72 @@ namespace pugi PUGI__FN xml_attribute xml_attribute::next_attribute() const { - return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); + if (!_attr) return xml_attribute(); + return xml_attribute(_attr->next_attribute); } PUGI__FN xml_attribute xml_attribute::previous_attribute() const { - return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); + if (!_attr) return xml_attribute(); + xml_attribute_struct* prev = _attr->prev_attribute_c; + return prev->next_attribute ? xml_attribute(prev) : xml_attribute(); } PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const { - return (_attr && _attr->value) ? _attr->value + 0 : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? value : def; } PUGI__FN int xml_attribute::as_int(int def) const { - return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_int(value) : def; } PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const { - return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_uint(value) : def; } PUGI__FN double xml_attribute::as_double(double def) const { - return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_double(value) : def; } PUGI__FN float xml_attribute::as_float(float def) const { - return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_float(value) : def; } PUGI__FN bool xml_attribute::as_bool(bool def) const { - return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_bool(value) : def; } #ifdef PUGIXML_HAS_LONG_LONG PUGI__FN long long xml_attribute::as_llong(long long def) const { - return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_llong(value) : def; } PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const { - return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_ullong(value) : def; } #endif @@ -5239,12 +5281,16 @@ namespace pugi PUGI__FN const char_t* xml_attribute::name() const { - return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT(""); + if (!_attr) return PUGIXML_TEXT(""); + const char_t* name = _attr->name; + return name ? name : PUGIXML_TEXT(""); } PUGI__FN const char_t* xml_attribute::value() const { - return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT(""); + if (!_attr) return PUGIXML_TEXT(""); + const char_t* value = _attr->value; + return value ? value : PUGIXML_TEXT(""); } PUGI__FN size_t xml_attribute::hash_value() const @@ -5326,6 +5372,13 @@ namespace pugi return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } + PUGI__FN bool xml_attribute::set_value(const char_t* rhs, size_t sz) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, sz); + } + PUGI__FN bool xml_attribute::set_value(const char_t* rhs) { if (!_attr) return false; @@ -5518,7 +5571,9 @@ namespace pugi PUGI__FN const char_t* xml_node::name() const { - return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); + if (!_root) return PUGIXML_TEXT(""); + const char_t* name = _root->name; + return name ? name : PUGIXML_TEXT(""); } PUGI__FN xml_node_type xml_node::type() const @@ -5528,7 +5583,9 @@ namespace pugi PUGI__FN const char_t* xml_node::value() const { - return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); + if (!_root) return PUGIXML_TEXT(""); + const char_t* value = _root->value; + return value ? value : PUGIXML_TEXT(""); } PUGI__FN xml_node xml_node::child(const char_t* name_) const @@ -5536,7 +5593,11 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } @@ -5546,8 +5607,11 @@ namespace pugi if (!_root) return xml_attribute(); for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) return xml_attribute(i); + } return xml_attribute(); } @@ -5557,7 +5621,11 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } @@ -5572,7 +5640,11 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } @@ -5588,24 +5660,30 @@ namespace pugi // optimistically search from hint up until the end for (xml_attribute_struct* i = hint; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) { // update hint to maximize efficiency of searching for consecutive attributes hint_._attr = i->next_attribute; return xml_attribute(i); } + } // wrap around and search from the first attribute until the hint // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) - if (j->name && impl::strequal(name_, j->name)) + { + const char_t* jname = j->name; + if (jname && impl::strequal(name_, jname)) { // update hint to maximize efficiency of searching for consecutive attributes hint_._attr = j->next_attribute; return xml_attribute(j); } + } return xml_attribute(); } @@ -5613,9 +5691,8 @@ namespace pugi PUGI__FN xml_node xml_node::previous_sibling() const { if (!_root) return xml_node(); - - if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); - else return xml_node(); + xml_node_struct* prev = _root->prev_sibling_c; + return prev->next_sibling ? xml_node(prev) : xml_node(); } PUGI__FN xml_node xml_node::parent() const @@ -5642,8 +5719,11 @@ namespace pugi return _root->value; for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (impl::is_text_node(i) && i->value) - return i->value; + { + const char_t* ivalue = i->value; + if (impl::is_text_node(i) && ivalue) + return ivalue; + } return PUGIXML_TEXT(""); } @@ -5655,22 +5735,28 @@ namespace pugi PUGI__FN xml_attribute xml_node::first_attribute() const { - return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); + if (!_root) return xml_attribute(); + return xml_attribute(_root->first_attribute); } PUGI__FN xml_attribute xml_node::last_attribute() const { - return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); + if (!_root) return xml_attribute(); + xml_attribute_struct* first = _root->first_attribute; + return first ? xml_attribute(first->prev_attribute_c) : xml_attribute(); } PUGI__FN xml_node xml_node::first_child() const { - return _root ? xml_node(_root->first_child) : xml_node(); + if (!_root) return xml_node(); + return xml_node(_root->first_child); } PUGI__FN xml_node xml_node::last_child() const { - return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); + if (!_root) return xml_node(); + xml_node_struct* first = _root->first_child; + return first ? xml_node(first->prev_sibling_c) : xml_node(); } PUGI__FN bool xml_node::set_name(const char_t* rhs) @@ -5683,6 +5769,16 @@ namespace pugi return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } + PUGI__FN bool xml_node::set_value(const char_t* rhs, size_t sz) + { + xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; + + if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) + return false; + + return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, sz); + } + PUGI__FN bool xml_node::set_value(const char_t* rhs) { xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; @@ -6196,12 +6292,22 @@ namespace pugi if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) { for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); + { + const char_t* aname = a->name; + if (aname && impl::strequal(attr_name, aname)) + { + const char_t* avalue = a->value; + if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT(""))) + return xml_node(i); + } + } } + } return xml_node(); } @@ -6212,8 +6318,15 @@ namespace pugi for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); + { + const char_t* aname = a->name; + if (aname && impl::strequal(attr_name, aname)) + { + const char_t* avalue = a->value; + if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT(""))) + return xml_node(i); + } + } return xml_node(); } @@ -6227,8 +6340,9 @@ namespace pugi for (xml_node_struct* i = _root; i; i = i->parent) { + const char_t* iname = i->name; offset += (i != _root); - offset += i->name ? impl::strlength(i->name) : 0; + offset += iname ? impl::strlength(iname) : 0; } string_t result; @@ -6239,12 +6353,13 @@ namespace pugi if (j != _root) result[--offset] = delimiter; - if (j->name) + const char_t* jname = j->name; + if (jname) { - size_t length = impl::strlength(j->name); + size_t length = impl::strlength(jname); offset -= length; - memcpy(&result[offset], j->name, length * sizeof(char_t)); + memcpy(&result[offset], jname, length * sizeof(char_t)); } } @@ -6282,7 +6397,8 @@ namespace pugi { for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling) { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) + const char_t* jname = j->name; + if (jname && impl::strequalrange(jname, path_segment, static_cast(path_segment_end - path_segment))) { xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); @@ -6474,68 +6590,84 @@ namespace pugi PUGI__FN const char_t* xml_text::get() const { xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : PUGIXML_TEXT(""); + if (!d) return PUGIXML_TEXT(""); + const char_t* value = d->value; + return value ? value : PUGIXML_TEXT(""); } PUGI__FN const char_t* xml_text::as_string(const char_t* def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : def; + if (!d) return def; + const char_t* value = d->value; + return value ? value : def; } PUGI__FN int xml_text::as_int(int def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_int(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_int(value) : def; } PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_uint(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_uint(value) : def; } PUGI__FN double xml_text::as_double(double def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_double(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_double(value) : def; } PUGI__FN float xml_text::as_float(float def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_float(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_float(value) : def; } PUGI__FN bool xml_text::as_bool(bool def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_bool(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_bool(value) : def; } #ifdef PUGIXML_HAS_LONG_LONG PUGI__FN long long xml_text::as_llong(long long def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_llong(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_llong(value) : def; } PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_ullong(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_ullong(value) : def; } #endif + PUGI__FN bool xml_text::set(const char_t* rhs, size_t sz) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, sz) : false; + } + PUGI__FN bool xml_text::set(const char_t* rhs) { xml_node_struct* dn = _data_new(); @@ -6735,7 +6867,7 @@ namespace pugi return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() + PUGI__FN xml_node_iterator& xml_node_iterator::operator++() { assert(_wrap._root); _wrap._root = _wrap._root->next_sibling; @@ -6749,7 +6881,7 @@ namespace pugi return temp; } - PUGI__FN const xml_node_iterator& xml_node_iterator::operator--() + PUGI__FN xml_node_iterator& xml_node_iterator::operator--() { _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); return *this; @@ -6796,7 +6928,7 @@ namespace pugi return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() + PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator++() { assert(_wrap._attr); _wrap._attr = _wrap._attr->next_attribute; @@ -6810,7 +6942,7 @@ namespace pugi return temp; } - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator--() + PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator--() { _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); return *this; @@ -6857,7 +6989,7 @@ namespace pugi return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() + PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator++() { assert(_wrap._root); _wrap = _wrap.next_sibling(_name); @@ -6871,7 +7003,7 @@ namespace pugi return temp; } - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator--() + PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator--() { if (_wrap._root) _wrap = _wrap.previous_sibling(_name); @@ -7091,8 +7223,12 @@ namespace pugi #endif // move allocation state - doc->_root = other->_root; - doc->_busy_size = other->_busy_size; + // note that other->_root may point to the embedded document page, in which case we should keep original (empty) state + if (other->_root != PUGI__GETPAGE(other)) + { + doc->_root = other->_root; + doc->_busy_size = other->_busy_size; + } // move buffer state doc->buffer = other->buffer; @@ -7287,7 +7423,7 @@ namespace pugi using impl::auto_deleter; // MSVC7 workaround auto_deleter file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); - return impl::save_file_impl(*this, file.data, indent, flags, encoding); + return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0; } PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const @@ -7295,7 +7431,7 @@ namespace pugi using impl::auto_deleter; // MSVC7 workaround auto_deleter file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file); - return impl::save_file_impl(*this, file.data, indent, flags, encoding); + return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0; } PUGI__FN xml_node xml_document::document_element() const @@ -8265,7 +8401,7 @@ PUGI__NS_BEGIN } // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) { // get base values @@ -11822,15 +11958,17 @@ PUGI__NS_BEGIN lexeme_t l = _lexer.current(); _lexer.next(); - if (++_depth > xpath_ast_depth_limit) - return error_rec(); - if (l == lex_double_slash) { n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); if (!n) return 0; + + ++_depth; } + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + n = parse_step(n); if (!n) return 0; } @@ -12995,7 +13133,7 @@ namespace pugi #endif /** - * Copyright (c) 2006-2020 Arseny Kapoulkine + * Copyright (c) 2006-2022 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/third_party/pugixml/pugixml.hpp b/runtime/IO/pugixml.hpp similarity index 98% rename from third_party/pugixml/pugixml.hpp rename to runtime/IO/pugixml.hpp index 7e2ce7776..050df154c 100644 --- a/third_party/pugixml/pugixml.hpp +++ b/runtime/IO/pugixml.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.11 + * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -11,10 +11,10 @@ * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) */ -#ifndef PUGIXML_VERSION // Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons // Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits -# define PUGIXML_VERSION 1110 +#ifndef PUGIXML_VERSION +# define PUGIXML_VERSION 1130 // 1.13 #endif // Include user configuration file (this can define various configuration macros) @@ -115,6 +115,8 @@ #ifndef PUGIXML_NULL # if __cplusplus >= 201103 # define PUGIXML_NULL nullptr +# elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define PUGIXML_NULL nullptr # else # define PUGIXML_NULL 0 # endif @@ -312,6 +314,8 @@ namespace pugi It begin() const { return _begin; } It end() const { return _end; } + bool empty() const { return _begin == _end; } + private: It _begin, _end; }; @@ -414,6 +418,7 @@ namespace pugi // Set attribute name/value (returns false if attribute is empty or there is not enough memory) bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs, size_t sz); bool set_value(const char_t* rhs); // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") @@ -548,6 +553,7 @@ namespace pugi // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs, size_t sz); bool set_value(const char_t* rhs); // Add attribute with specified name. Returns added attribute, or empty attribute on errors. @@ -773,6 +779,7 @@ namespace pugi bool as_bool(bool def = false) const; // Set text (returns false if object is empty or there is not enough memory) + bool set(const char_t* rhs, size_t sz); bool set(const char_t* rhs); // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") @@ -851,10 +858,10 @@ namespace pugi xml_node& operator*() const; xml_node* operator->() const; - const xml_node_iterator& operator++(); + xml_node_iterator& operator++(); xml_node_iterator operator++(int); - const xml_node_iterator& operator--(); + xml_node_iterator& operator--(); xml_node_iterator operator--(int); }; @@ -893,10 +900,10 @@ namespace pugi xml_attribute& operator*() const; xml_attribute* operator->() const; - const xml_attribute_iterator& operator++(); + xml_attribute_iterator& operator++(); xml_attribute_iterator operator++(int); - const xml_attribute_iterator& operator--(); + xml_attribute_iterator& operator--(); xml_attribute_iterator operator--(int); }; @@ -929,10 +936,10 @@ namespace pugi xml_node& operator*() const; xml_node* operator->() const; - const xml_named_node_iterator& operator++(); + xml_named_node_iterator& operator++(); xml_named_node_iterator operator++(int); - const xml_named_node_iterator& operator--(); + xml_named_node_iterator& operator--(); xml_named_node_iterator operator--(int); private: @@ -1474,7 +1481,7 @@ namespace std #endif /** - * Copyright (c) 2006-2020 Arseny Kapoulkine + * Copyright (c) 2006-2022 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/runtime/Rendering/Material.cpp b/runtime/Rendering/Material.cpp index 91c7971b0..b423a5443 100644 --- a/runtime/Rendering/Material.cpp +++ b/runtime/Rendering/Material.cpp @@ -24,10 +24,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "Material.h" #include "Renderer.h" #include "../Resource/ResourceCache.h" -#include "../IO/XmlDocument.h" #include "../RHI/RHI_Texture2D.h" #include "../RHI/RHI_TextureCube.h" #include "../World/World.h" +SP_WARNINGS_OFF +#include "../IO/pugixml.hpp" +SP_WARNINGS_ON //==================================== //= NAMESPACES =============== @@ -37,6 +39,40 @@ using namespace Spartan::Math; namespace Spartan { + namespace + { + const char* material_property_to_char_ptr(MaterialProperty material_property) + { + switch (material_property) + { + case MaterialProperty::ColorR: return "color_r"; + case MaterialProperty::ColorG: return "color_g"; + case MaterialProperty::ColorB: return "color_b"; + case MaterialProperty::ColorA: return "color_a"; + case MaterialProperty::RoughnessMultiplier: return "roughness_multiplier"; + case MaterialProperty::MetalnessMultiplier: return "metalness_multiplier"; + case MaterialProperty::NormalMultiplier: return "normal_multiplier"; + case MaterialProperty::HeightMultiplier: return "height_multiplier"; + case MaterialProperty::Clearcoat: return "clearcoat_multiplier"; + case MaterialProperty::Clearcoat_Roughness: return "clearcoat_roughness_multiplier"; + case MaterialProperty::Anisotropic: return "anisotropic_multiplier"; + case MaterialProperty::AnisotropicRotation: return "anisotropic_rotation_multiplier"; + case MaterialProperty::Sheen: return "sheen_multiplier"; + case MaterialProperty::SheenTint: return "sheen_tint_multiplier"; + case MaterialProperty::UvTilingX: return "uv_tiling_x"; + case MaterialProperty::UvTilingY: return "uv_tiling_y"; + case MaterialProperty::UvOffsetX: return "uv_offset_x"; + case MaterialProperty::UvOffsetY: return "uv_offset_y"; + case MaterialProperty::CanBeEdited: return "can_be_edited"; + default: + { + SP_ASSERT_MSG(false, "Unknown material property"); + return nullptr; + } + } + } + } + Material::Material() : IResource(ResourceType::Material) { m_textures.fill(nullptr); @@ -53,41 +89,36 @@ namespace Spartan SetProperty(MaterialProperty::UvTilingY, 1.0f); } - bool Material::LoadFromFile(const string& file_path) + bool Material::LoadFromFile(const std::string& file_path) { - auto xml = make_unique(); - if (!xml->Load(file_path)) + pugi::xml_document doc; + if (!doc.load_file(file_path.c_str())) + { + SP_LOG_ERROR("Failed to load XML file"); return false; + } SetResourceFilePath(file_path); - xml->GetAttribute("Material", "color_r", &m_properties[static_cast(MaterialProperty::ColorR)]); - xml->GetAttribute("Material", "color_g", &m_properties[static_cast(MaterialProperty::ColorG)]); - xml->GetAttribute("Material", "color_b", &m_properties[static_cast(MaterialProperty::ColorB)]); - xml->GetAttribute("Material", "color_a", &m_properties[static_cast(MaterialProperty::ColorA)]); - xml->GetAttribute("Material", "roughness_multiplier", &m_properties[static_cast(MaterialProperty::RoughnessMultiplier)]); - xml->GetAttribute("Material", "metalness_multiplier", &m_properties[static_cast(MaterialProperty::MetalnessMultiplier)]); - xml->GetAttribute("Material", "normal_multiplier", &m_properties[static_cast(MaterialProperty::NormalMultiplier)]); - xml->GetAttribute("Material", "height_multiplier", &m_properties[static_cast(MaterialProperty::HeightMultiplier)]); - xml->GetAttribute("Material", "clearcoat_multiplier", &m_properties[static_cast(MaterialProperty::Clearcoat)]); - xml->GetAttribute("Material", "clearcoat_roughness_multiplier", &m_properties[static_cast(MaterialProperty::Clearcoat_Roughness)]); - xml->GetAttribute("Material", "anisotropic_multiplier", &m_properties[static_cast(MaterialProperty::Anisotropic)]); - xml->GetAttribute("Material", "anisotropic_rotation_multiplier", &m_properties[static_cast(MaterialProperty::AnisotropicRotation)]); - xml->GetAttribute("Material", "sheen_multiplier", &m_properties[static_cast(MaterialProperty::Sheen)]); - xml->GetAttribute("Material", "sheen_tint_multiplier", &m_properties[static_cast(MaterialProperty::SheenTint)]); - xml->GetAttribute("Material", "uv_tiling_x", &m_properties[static_cast(MaterialProperty::UvTilingX)]); - xml->GetAttribute("Material", "uv_tiling_y", &m_properties[static_cast(MaterialProperty::UvTilingY)]); - xml->GetAttribute("Material", "uv_offset_x", &m_properties[static_cast(MaterialProperty::UvOffsetX)]); - xml->GetAttribute("Material", "uv_offset_y", &m_properties[static_cast(MaterialProperty::UvOffsetY)]); - xml->GetAttribute("Material", "can_be_edited", &m_properties[static_cast(MaterialProperty::CanBeEdited)]); - - const uint32_t texture_count = xml->GetAttributeAs("textures", "count"); - for (uint32_t i = 0; i < texture_count; i++) + pugi::xml_node node_material = doc.child("Material"); + + // load properties + for (uint32_t i = 0; i < static_cast(MaterialProperty::Undefined); ++i) { - auto node_name = "texture_" + to_string(i); - const MaterialTexture tex_type = static_cast(xml->GetAttributeAs(node_name, "texture_type")); - auto tex_name = xml->GetAttributeAs(node_name, "texture_name"); - auto tex_path = xml->GetAttributeAs(node_name, "texture_path"); + const char* attribute_name = material_property_to_char_ptr(static_cast(i)); + m_properties[i] = node_material.child(attribute_name).text().as_float(); + } + + // load textures + uint32_t texture_count = node_material.child("textures").attribute("count").as_uint(); + for (uint32_t i = 0; i < texture_count; ++i) + { + string node_name = "texture_" + to_string(i); + pugi::xml_node node_texture = node_material.child("textures").child(node_name.c_str()); + + MaterialTexture tex_type = static_cast(node_texture.attribute("texture_type").as_uint()); + string tex_name = node_texture.attribute("texture_name").as_string(); + string tex_path = node_texture.attribute("texture_path").as_string(); // If the texture happens to be loaded, get a reference to it auto texture = ResourceCache::GetByName(tex_name); @@ -109,42 +140,31 @@ namespace Spartan { SetResourceFilePath(file_path); - XmlDocument xml_document; - - xml_document.AddNode("Material"); - xml_document.AddAttribute("Material", "color_r", GetProperty(MaterialProperty::ColorR)); - xml_document.AddAttribute("Material", "color_g", GetProperty(MaterialProperty::ColorG)); - xml_document.AddAttribute("Material", "color_b", GetProperty(MaterialProperty::ColorB)); - xml_document.AddAttribute("Material", "color_a", GetProperty(MaterialProperty::ColorA)); - xml_document.AddAttribute("Material", "roughness_multiplier", GetProperty(MaterialProperty::RoughnessMultiplier)); - xml_document.AddAttribute("Material", "metalness_multiplier", GetProperty(MaterialProperty::MetalnessMultiplier)); - xml_document.AddAttribute("Material", "normal_multiplier", GetProperty(MaterialProperty::NormalMultiplier)); - xml_document.AddAttribute("Material", "height_multiplier", GetProperty(MaterialProperty::HeightMultiplier)); - xml_document.AddAttribute("Material", "clearcoat_multiplier", GetProperty(MaterialProperty::Clearcoat)); - xml_document.AddAttribute("Material", "clearcoat_roughness_multiplier", GetProperty(MaterialProperty::Clearcoat_Roughness)); - xml_document.AddAttribute("Material", "anisotropic_multiplier", GetProperty(MaterialProperty::Anisotropic)); - xml_document.AddAttribute("Material", "anisotropic_rotation_multiplier", GetProperty(MaterialProperty::AnisotropicRotation)); - xml_document.AddAttribute("Material", "sheen_multiplier", GetProperty(MaterialProperty::Sheen)); - xml_document.AddAttribute("Material", "sheen_tint_multiplier", GetProperty(MaterialProperty::SheenTint)); - xml_document.AddAttribute("Material", "uv_tiling_x", GetProperty(MaterialProperty::UvTilingX)); - xml_document.AddAttribute("Material", "uv_tiling_y", GetProperty(MaterialProperty::UvTilingY)); - xml_document.AddAttribute("Material", "uv_offset_x", GetProperty(MaterialProperty::UvOffsetX)); - xml_document.AddAttribute("Material", "uv_offset_y", GetProperty(MaterialProperty::UvOffsetY)); - xml_document.AddAttribute("Material", "can_be_edited", GetProperty(MaterialProperty::CanBeEdited)); - - xml_document.AddChildNode("Material", "textures"); - xml_document.AddAttribute("textures", "count", static_cast(m_textures.size())); - uint32_t i = 0; - for (const auto& texture : m_textures) + pugi::xml_document doc; + pugi::xml_node materialNode = doc.append_child("Material"); + + // save properties + for (uint32_t i = 0; i < static_cast(MaterialProperty::Undefined); ++i) { - auto tex_node = "texture_" + to_string(i); - xml_document.AddChildNode("textures", tex_node); - xml_document.AddAttribute(tex_node, "texture_type", i++); - xml_document.AddAttribute(tex_node, "texture_name", texture ? texture->GetObjectName() : ""); - xml_document.AddAttribute(tex_node, "texture_path", texture ? texture->GetResourceFilePathNative() : ""); + const char* attributeName = material_property_to_char_ptr(static_cast(i)); + materialNode.append_child(attributeName).text().set(m_properties[i]); + } + + // save textures + pugi::xml_node texturesNode = materialNode.append_child("textures"); + texturesNode.append_attribute("count").set_value(static_cast(m_textures.size())); + + for (uint32_t i = 0; i < m_textures.size(); ++i) + { + string node_name = "texture_" + to_string(i); + pugi::xml_node textureNode = texturesNode.append_child(node_name.c_str()); + + textureNode.append_attribute("texture_type").set_value(i); + textureNode.append_attribute("texture_name").set_value(m_textures[i] ? m_textures[i]->GetObjectName().c_str() : ""); + textureNode.append_attribute("texture_path").set_value(m_textures[i] ? m_textures[i]->GetResourceFilePathNative().c_str() : ""); } - return xml_document.Save(GetResourceFilePathNative()); + return doc.save_file(file_path.c_str()); } void Material::SetTexture(const MaterialTexture texture_type, RHI_Texture* texture) diff --git a/third_party/pugixml/LICENSE.md b/third_party/pugixml/LICENSE.md deleted file mode 100644 index 2503b81eb..000000000 --- a/third_party/pugixml/LICENSE.md +++ /dev/null @@ -1,24 +0,0 @@ -MIT License - -Copyright (c) 2006-2020 Arseny Kapoulkine - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/third_party/pugixml/version.txt b/third_party/pugixml/version.txt deleted file mode 100644 index 674378088..000000000 --- a/third_party/pugixml/version.txt +++ /dev/null @@ -1 +0,0 @@ -1.11.4 \ No newline at end of file