diff --git a/CMakeLists.txt b/CMakeLists.txt index f7c2924b6..305f6d76b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,10 +105,15 @@ endif() if (WIN32) set(PLATFORM "Windows") add_compile_definitions(WIN32=1) + add_compile_definitions(_HAS_EXCEPTIONS=0) + if (MSVC) add_compile_options( - /W3 - /MP + /W3 # warning level 3 + /MP # multi-processor compilation + /EHsc- # exceptions disabled + /GR- # runtime type information disabled + $<$:/GS-> # security check disabled in Release ) endif() @@ -116,15 +121,27 @@ if (WIN32) elseif(UNIX) set(PLATFORM "SDL2") add_compile_definitions(SDL2=1) + add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1) # Common compiler options and warning level for CLANG and GCC: add_compile_options( - -Wall + -Wall # warning level: all + # some warnings are disabled to better match MSVC warning level 3: -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable -Wno-sign-compare + + $<$:-fno-exceptions> # exceptions disabled + $<$:-fno-rtti> # runtime type information disabled + + # security checks disabled in Release: + $<$:-fno-stack-protector> + $<$:-fcf-protection=none> + $<$:-fno-stack-clash-protection> + $<$:-fno-stack-check> + $<$:-fno-asynchronous-unwind-tables> ) endif() @@ -156,7 +173,6 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") ) endif() - add_subdirectory(WickedEngine) add_custom_target(Content COMMAND ${CMAKE_COMMAND} -E ${COPY_OR_SYMLINK_DIR_CMD} ${WICKED_ROOT_DIR}/Content ${CMAKE_CURRENT_BINARY_DIR}/Content diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index de9d78eb2..e71e63b0d 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -2967,7 +2967,6 @@ void EditorComponent::Update(float dt) camera.UpdateCamera(); } - wi::RenderPath3D_PathTracing* pathtracer = dynamic_cast(renderPath.get()); if (pathtracer != nullptr) { pathtracer->setTargetSampleCount((int)graphicsWnd.pathTraceTargetSlider.GetValue()); diff --git a/Editor/Editor.h b/Editor/Editor.h index f372e9734..7310ab160 100644 --- a/Editor/Editor.h +++ b/Editor/Editor.h @@ -88,6 +88,7 @@ public: wi::physics::PickDragOperation physicsDragOp; std::unique_ptr renderPath; + wi::RenderPath3D_PathTracing* pathtracer = nullptr; // This is not lifetime managing pointer, it will view renderPath if it's path tracing wi::graphics::Texture gui_background_effect; const wi::graphics::Texture* GetGUIBlurredBackground() const override { return renderPath->GetGUIBlurredBackground(); } diff --git a/Editor/Editor_Windows.vcxproj b/Editor/Editor_Windows.vcxproj index c85b79813..93f2374a7 100644 --- a/Editor/Editor_Windows.vcxproj +++ b/Editor/Editor_Windows.vcxproj @@ -63,13 +63,14 @@ Use Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pch true stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false Windows @@ -101,7 +102,7 @@ MaxSpeed true true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) true MultiThreaded @@ -110,6 +111,8 @@ stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false + false Windows diff --git a/Editor/GraphicsWindow.cpp b/Editor/GraphicsWindow.cpp index 260cdc09a..cbf8508ec 100644 --- a/Editor/GraphicsWindow.cpp +++ b/Editor/GraphicsWindow.cpp @@ -1748,13 +1748,19 @@ void GraphicsWindow::UpdateData() void GraphicsWindow::ChangeRenderPath(RENDERPATH path) { + editor->pathtracer = nullptr; + switch (path) { case RENDERPATH_DEFAULT: editor->renderPath = std::make_unique(); break; case RENDERPATH_PATHTRACING: - editor->renderPath = std::make_unique(); + { + std::unique_ptr pathtracing = std::make_unique(); + editor->pathtracer = pathtracing.get(); + editor->renderPath = std::move(pathtracing); + } break; default: assert(0); diff --git a/Editor/main_SDL2.cpp b/Editor/main_SDL2.cpp index 6ad91f132..e52737c8e 100644 --- a/Editor/main_SDL2.cpp +++ b/Editor/main_SDL2.cpp @@ -215,7 +215,7 @@ int main(int argc, char *argv[]) sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS); if (*system) { - throw sdl2::SDLError("Error creating SDL2 system"); + wilog_error("Error creating SDL2 system"); } int width = 1920; @@ -245,7 +245,7 @@ int main(int argc, char *argv[]) width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); if (!window) { - throw sdl2::SDLError("Error creating window"); + wilog_error("Error creating window"); } set_window_icon(window.get()); diff --git a/Samples/Example_ImGui/Example_ImGui.vcxproj b/Samples/Example_ImGui/Example_ImGui.vcxproj index 3d902f0b9..62a4e24f1 100644 --- a/Samples/Example_ImGui/Example_ImGui.vcxproj +++ b/Samples/Example_ImGui/Example_ImGui.vcxproj @@ -63,13 +63,15 @@ MaxSpeed true true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreaded true stdcpp17 AdvancedVectorExtensions + false + false Windows @@ -88,13 +90,14 @@ NotUsing Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL true stdcpp17 AdvancedVectorExtensions + false Windows diff --git a/Samples/Example_ImGui/main_SDL2.cpp b/Samples/Example_ImGui/main_SDL2.cpp index fb963a77d..9a71a418d 100644 --- a/Samples/Example_ImGui/main_SDL2.cpp +++ b/Samples/Example_ImGui/main_SDL2.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS); if (*system) { - throw sdl2::SDLError("Error creating SDL2 system"); + wilog_error("Error creating SDL2 system"); } sdl2::window_ptr_t window = sdl2::make_window( @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) 1280, 800, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); if (!window) { - throw sdl2::SDLError("Error creating window"); + wilog_error("Error creating window"); } exampleImGui.SetWindow(window.get()); diff --git a/Samples/Example_ImGui_Docking/Example_ImGui_Docking.vcxproj b/Samples/Example_ImGui_Docking/Example_ImGui_Docking.vcxproj index 0499a6ce2..201462bb8 100644 --- a/Samples/Example_ImGui_Docking/Example_ImGui_Docking.vcxproj +++ b/Samples/Example_ImGui_Docking/Example_ImGui_Docking.vcxproj @@ -63,13 +63,15 @@ MaxSpeed true true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreaded true stdcpp17 AdvancedVectorExtensions + false + false Windows @@ -88,13 +90,14 @@ NotUsing Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL true stdcpp17 AdvancedVectorExtensions + false Windows diff --git a/Samples/Example_ImGui_Docking/main_SDL2.cpp b/Samples/Example_ImGui_Docking/main_SDL2.cpp index ba8b27633..334dcafdf 100644 --- a/Samples/Example_ImGui_Docking/main_SDL2.cpp +++ b/Samples/Example_ImGui_Docking/main_SDL2.cpp @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS); if (*system) { - throw sdl2::SDLError("Error creating SDL2 system"); + wilog_error("Error creating SDL2 system"); } sdl2::window_ptr_t window = sdl2::make_window( @@ -79,7 +79,7 @@ int main(int argc, char *argv[]) 1280, 800, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); if (!window) { - throw sdl2::SDLError("Error creating window"); + wilog_error("Error creating window"); } exampleImGui.SetWindow(window.get()); diff --git a/Samples/Template_Windows/Template_Windows.vcxproj b/Samples/Template_Windows/Template_Windows.vcxproj index d18a414bd..ae2d29ea6 100644 --- a/Samples/Template_Windows/Template_Windows.vcxproj +++ b/Samples/Template_Windows/Template_Windows.vcxproj @@ -60,13 +60,15 @@ MaxSpeed true true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreaded true stdcpp17 AdvancedVectorExtensions + false + false Windows @@ -86,12 +88,13 @@ NotUsing Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) true stdcpp17 AdvancedVectorExtensions + false Windows diff --git a/Samples/Tests/Tests.vcxproj b/Samples/Tests/Tests.vcxproj index 79e172d62..c9c6bdd9e 100644 --- a/Samples/Tests/Tests.vcxproj +++ b/Samples/Tests/Tests.vcxproj @@ -63,14 +63,16 @@ MaxSpeed true true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreaded true stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false + false Windows @@ -90,14 +92,15 @@ Use Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 + false $(SolutionDir)WickedEngine;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL true stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false Windows diff --git a/Samples/Tests/main_SDL2.cpp b/Samples/Tests/main_SDL2.cpp index ea6490469..a871b2899 100644 --- a/Samples/Tests/main_SDL2.cpp +++ b/Samples/Tests/main_SDL2.cpp @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS); if (*system) { - throw sdl2::SDLError("Error creating SDL2 system"); + wilog_error("Error creating SDL2 system"); } sdl2::window_ptr_t window = sdl2::make_window( @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) 1280, 800, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); if (!window) { - throw sdl2::SDLError("Error creating window"); + wilog_error("Error creating window"); } tests.SetWindow(window.get()); diff --git a/WickedEngine/OfflineShaderCompiler.vcxproj b/WickedEngine/OfflineShaderCompiler.vcxproj index 066d4c50b..079345840 100644 --- a/WickedEngine/OfflineShaderCompiler.vcxproj +++ b/WickedEngine/OfflineShaderCompiler.vcxproj @@ -55,11 +55,12 @@ Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 true stdcpp17 AdvancedVectorExtensions + false Console @@ -76,12 +77,14 @@ Level3 true true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_HAS_EXCEPTIONS=0 true stdcpp17 MultiThreaded AdvancedVectorExtensions + false + false Console diff --git a/WickedEngine/Utility/cpuinfo.hpp b/WickedEngine/Utility/cpuinfo.hpp index 301c4f1fa..8a901a922 100644 --- a/WickedEngine/Utility/cpuinfo.hpp +++ b/WickedEngine/Utility/cpuinfo.hpp @@ -179,10 +179,6 @@ CPUInfo::CPUInfo() } } } - else - { - throw std::runtime_error{"Unknown vendor! Reported vendor name is: " + mVendorId}; - } // Get processor brand string // This seems to be working for both Intel & AMD vendors diff --git a/WickedEngine/Utility/flat_hash_map.hpp b/WickedEngine/Utility/flat_hash_map.hpp index 633bd4b47..7b6cb78cb 100644 --- a/WickedEngine/Utility/flat_hash_map.hpp +++ b/WickedEngine/Utility/flat_hash_map.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef _MSC_VER #define SKA_NOINLINE(...) __declspec(noinline) __VA_ARGS__ @@ -357,16 +358,16 @@ public: : EntryAlloc(alloc), Hasher(other), Equal(other), _max_load_factor(other._max_load_factor) { rehash_for_other_container(other); - try - { + //try + //{ insert(other.begin(), other.end()); - } - catch(...) - { - clear(); - deallocate_data(entries, num_slots_minus_one, max_lookups); - throw; - } + //} + //catch(...) + //{ + // clear(); + // deallocate_data(entries, num_slots_minus_one, max_lookups); + // throw; + //} } sherwood_v3_table(sherwood_v3_table && other) noexcept : EntryAlloc(std::move(other)), Hasher(std::move(other)), Equal(std::move(other)) @@ -1342,14 +1343,14 @@ public: { auto found = this->find(key); if (found == this->end()) - throw std::out_of_range("Argument passed to at() was not in the map."); + assert(0 && "Argument passed to at() was not in the map."); return found->second; } const V & at(const K & key) const { auto found = this->find(key); if (found == this->end()) - throw std::out_of_range("Argument passed to at() was not in the map."); + assert(0 && "Argument passed to at() was not in the map."); return found->second; } diff --git a/WickedEngine/Utility/pugiconfig.hpp b/WickedEngine/Utility/pugiconfig.hpp index 88b2f2aee..e47df4fc0 100644 --- a/WickedEngine/Utility/pugiconfig.hpp +++ b/WickedEngine/Utility/pugiconfig.hpp @@ -1,14 +1,12 @@ /** - * pugixml parser - version 1.13 + * pugixml parser - version 1.15 * -------------------------------------------------------- - * 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 - * of this file. + * SPDX-FileCopyrightText: Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * SPDX-License-Identifier: MIT * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + * See LICENSE.md or notice at the end of this file. */ #ifndef HEADER_PUGICONFIG_HPP @@ -27,7 +25,7 @@ // #define PUGIXML_NO_STL // Uncomment this to disable exceptions -// #define PUGIXML_NO_EXCEPTIONS +#define PUGIXML_NO_EXCEPTIONS // Set this to control attributes for public classes/functions, i.e.: // #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL @@ -46,13 +44,16 @@ // Uncomment this to switch to header-only version // #define PUGIXML_HEADER_ONLY -// Uncomment this to enable long long support +// Uncomment this to enable long long support (usually enabled automatically) // #define PUGIXML_HAS_LONG_LONG +// Uncomment this to enable support for std::string_view (usually enabled automatically) +// #define PUGIXML_HAS_STRING_VIEW + #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2025 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/WickedEngine/Utility/pugixml.cpp b/WickedEngine/Utility/pugixml.cpp index 2f15073f0..c314e315f 100644 --- a/WickedEngine/Utility/pugixml.cpp +++ b/WickedEngine/Utility/pugixml.cpp @@ -1,14 +1,12 @@ /** - * pugixml parser - version 1.13 + * pugixml parser - version 1.15 * -------------------------------------------------------- - * 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 - * of this file. + * SPDX-FileCopyrightText: Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * SPDX-License-Identifier: MIT * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + * See LICENSE.md or notice at the end of this file. */ #ifndef SOURCE_PUGIXML_CPP @@ -40,6 +38,11 @@ // For placement new #include +// For load_file +#if defined(__linux__) || defined(__APPLE__) +#include +#endif + #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4127) // conditional expression is constant @@ -48,6 +51,11 @@ # pragma warning(disable: 4996) // this function or variable may be unsafe #endif +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // NULL as null pointer constant +#endif + #if defined(_MSC_VER) && defined(__c2__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated" // this function or variable may be unsafe @@ -124,6 +132,12 @@ using std::memmove; using std::memset; #endif +// Old versions of GCC do not define ::malloc and ::free depending on header include order +#if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)) +using std::malloc; +using std::free; +#endif + // Some MinGW/GCC versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions from limits.h in some configurations #if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX) # define LLONG_MIN (-LLONG_MAX - 1LL) @@ -236,6 +250,24 @@ PUGI_IMPL_NS_BEGIN #endif } +#ifdef PUGIXML_HAS_STRING_VIEW + // Check if the null-terminated dst string is equal to the entire contents of srcview + PUGI_IMPL_FN bool stringview_equal(string_view_t srcview, const char_t* dst) + { + // std::basic_string_view::compare(const char*) has the right behavior, but it performs an + // extra traversal of dst to compute its length. + assert(dst); + const char_t* src = srcview.data(); + size_t srclen = srcview.size(); + + while (srclen && *dst && *src == *dst) + { + --srclen; ++dst; ++src; + } + return srclen == 0 && *dst == 0; + } +#endif + // Compare lhs with [rhs_begin, rhs_end) PUGI_IMPL_FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) { @@ -282,7 +314,7 @@ PUGI_IMPL_NS_BEGIN T* release() { T* result = data; - data = 0; + data = NULL; return result; } }; @@ -293,7 +325,7 @@ PUGI_IMPL_NS_BEGIN class compact_hash_table { public: - compact_hash_table(): _items(0), _capacity(0), _count(0) + compact_hash_table(): _items(NULL), _capacity(0), _count(0) { } @@ -302,7 +334,7 @@ PUGI_IMPL_NS_BEGIN if (_items) { xml_memory::deallocate(_items); - _items = 0; + _items = NULL; _capacity = 0; _count = 0; } @@ -310,11 +342,11 @@ PUGI_IMPL_NS_BEGIN void* find(const void* key) { - if (_capacity == 0) return 0; + if (_capacity == 0) return NULL; item_t* item = get_item(key); assert(item); - assert(item->key == key || (item->key == 0 && item->value == 0)); + assert(item->key == key || (item->key == NULL && item->value == NULL)); return item->value; } @@ -326,7 +358,7 @@ PUGI_IMPL_NS_BEGIN item_t* item = get_item(key); assert(item); - if (item->key == 0) + if (item->key == NULL) { _count++; item->key = key; @@ -369,7 +401,7 @@ PUGI_IMPL_NS_BEGIN { item_t& probe_item = _items[bucket]; - if (probe_item.key == key || probe_item.key == 0) + if (probe_item.key == key || probe_item.key == NULL) return &probe_item; // hash collision, quadratic probing @@ -377,7 +409,7 @@ PUGI_IMPL_NS_BEGIN } assert(false && "Hash table is full"); // unreachable - return 0; + return NULL; } static PUGI_IMPL_UNSIGNED_OVERFLOW unsigned int hash(const void* key) @@ -465,16 +497,16 @@ PUGI_IMPL_NS_BEGIN { xml_memory_page* result = static_cast(memory); - result->allocator = 0; - result->prev = 0; - result->next = 0; + result->allocator = NULL; + result->prev = NULL; + result->next = NULL; result->busy_size = 0; result->freed_size = 0; #ifdef PUGIXML_COMPACT - result->compact_string_base = 0; - result->compact_shared_parent = 0; - result->compact_page_marker = 0; + result->compact_string_base = NULL; + result->compact_shared_parent = NULL; + result->compact_page_marker = NULL; #endif return result; @@ -514,7 +546,7 @@ PUGI_IMPL_NS_BEGIN xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) { #ifdef PUGIXML_COMPACT - _hash = 0; + _hash = NULL; #endif } @@ -524,7 +556,7 @@ PUGI_IMPL_NS_BEGIN // allocate block with some alignment, leaving memory for worst-case padding void* memory = xml_memory::allocate(size); - if (!memory) return 0; + if (!memory) return NULL; // prepare page structure xml_memory_page* page = xml_memory_page::construct(memory); @@ -561,7 +593,7 @@ PUGI_IMPL_NS_BEGIN void* allocate_object(size_t size, xml_memory_page*& out_page) { void* result = allocate_memory(size + sizeof(uint32_t), out_page); - if (!result) return 0; + if (!result) return NULL; // adjust for marker ptrdiff_t offset = static_cast(result) - reinterpret_cast(out_page->compact_page_marker); @@ -607,7 +639,7 @@ PUGI_IMPL_NS_BEGIN if (page->freed_size == page->busy_size) { - if (page->next == 0) + if (page->next == NULL) { assert(_root == page); @@ -617,9 +649,9 @@ PUGI_IMPL_NS_BEGIN #ifdef PUGIXML_COMPACT // reset compact state to maximize efficiency - page->compact_string_base = 0; - page->compact_shared_parent = 0; - page->compact_page_marker = 0; + page->compact_string_base = NULL; + page->compact_shared_parent = NULL; + page->compact_page_marker = NULL; #endif _busy_size = 0; @@ -654,7 +686,7 @@ PUGI_IMPL_NS_BEGIN xml_memory_page* page; xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); - if (!header) return 0; + if (!header) return NULL; // setup header ptrdiff_t page_offset = reinterpret_cast(header) - reinterpret_cast(page) - sizeof(xml_memory_page); @@ -716,7 +748,7 @@ PUGI_IMPL_NS_BEGIN xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); out_page = page; - if (!page) return 0; + if (!page) return NULL; if (size <= large_allocation_threshold) { @@ -863,7 +895,7 @@ PUGI_IMPL_NS_BEGIN return compact_get_value(this); } else - return 0; + return NULL; } T* operator->() const @@ -906,7 +938,7 @@ PUGI_IMPL_NS_BEGIN { xml_memory_page* page = compact_get_page(this, header_offset); - if (PUGI_IMPL_UNLIKELY(page->compact_shared_parent == 0)) + if (PUGI_IMPL_UNLIKELY(page->compact_shared_parent == NULL)) page->compact_shared_parent = value; if (page->compact_shared_parent == value) @@ -943,7 +975,7 @@ PUGI_IMPL_NS_BEGIN return compact_get_value(this); } else - return 0; + return NULL; } T* operator->() const @@ -973,7 +1005,7 @@ PUGI_IMPL_NS_BEGIN { xml_memory_page* page = compact_get_page(this, header_offset); - if (PUGI_IMPL_UNLIKELY(page->compact_string_base == 0)) + if (PUGI_IMPL_UNLIKELY(page->compact_string_base == NULL)) page->compact_string_base = value; ptrdiff_t offset = value - page->compact_string_base; @@ -1039,7 +1071,7 @@ PUGI_IMPL_NS_BEGIN } } else - return 0; + return NULL; } private: @@ -1098,7 +1130,7 @@ namespace pugi { struct xml_attribute_struct { - xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0) + xml_attribute_struct(impl::xml_memory_page* page): name(NULL), value(NULL), prev_attribute_c(NULL), next_attribute(NULL) { header = PUGI_IMPL_GETHEADER_IMPL(this, page, 0); } @@ -1114,7 +1146,7 @@ namespace pugi struct xml_node_struct { - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) + xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(NULL), value(NULL), parent(NULL), first_child(NULL), prev_sibling_c(NULL), next_sibling(NULL), first_attribute(NULL) { header = PUGI_IMPL_GETHEADER_IMPL(this, page, type); } @@ -1145,7 +1177,7 @@ PUGI_IMPL_NS_BEGIN struct xml_document_struct: public xml_node_struct, public xml_allocator { - xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) + xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(NULL), extra_buffers(NULL) { } @@ -1179,7 +1211,7 @@ PUGI_IMPL_NS_BEGIN { xml_memory_page* page; void* memory = alloc.allocate_object(sizeof(xml_attribute_struct), page); - if (!memory) return 0; + if (!memory) return NULL; return new (memory) xml_attribute_struct(page); } @@ -1188,7 +1220,7 @@ PUGI_IMPL_NS_BEGIN { xml_memory_page* page; void* memory = alloc.allocate_object(sizeof(xml_node_struct), page); - if (!memory) return 0; + if (!memory) return NULL; return new (memory) xml_node_struct(page, type); } @@ -1327,9 +1359,9 @@ PUGI_IMPL_NS_BEGIN else parent->first_child = next; - node->parent = 0; - node->prev_sibling_c = 0; - node->next_sibling = 0; + node->parent = NULL; + node->prev_sibling_c = NULL; + node->next_sibling = NULL; } inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node) @@ -1410,16 +1442,16 @@ PUGI_IMPL_NS_BEGIN else node->first_attribute = next; - attr->prev_attribute_c = 0; - attr->next_attribute = 0; + attr->prev_attribute_c = NULL; + attr->next_attribute = NULL; } PUGI_IMPL_FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) { - if (!alloc.reserve()) return 0; + if (!alloc.reserve()) return NULL; xml_node_struct* child = allocate_node(alloc, type); - if (!child) return 0; + if (!child) return NULL; append_node(child, node); @@ -1428,10 +1460,10 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) { - if (!alloc.reserve()) return 0; + if (!alloc.reserve()) return NULL; xml_attribute_struct* attr = allocate_attribute(alloc); - if (!attr) return 0; + if (!attr) return NULL; append_attribute(attr, node); @@ -1558,8 +1590,8 @@ PUGI_IMPL_NS_BEGIN static value_type high(value_type result, uint32_t ch) { - uint32_t msh = static_cast(ch - 0x10000) >> 10; - uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; + uint32_t msh = (ch - 0x10000U) >> 10; + uint32_t lsh = (ch - 0x10000U) & 0x3ff; result[0] = static_cast(0xD800 + msh); result[1] = static_cast(0xDC00 + lsh); @@ -2013,7 +2045,7 @@ PUGI_IMPL_NS_BEGIN if (d0 == 0x3c && d1 == 0) return encoding_utf16_le; // no known BOM detected; parse declaration - const uint8_t* enc = 0; + const uint8_t* enc = NULL; size_t enc_length = 0; if (d0 == 0x3c && d1 == 0x3f && d2 == 0x78 && d3 == 0x6d && parse_declaration_encoding(data, size, enc, enc_length)) @@ -2384,7 +2416,7 @@ PUGI_IMPL_NS_BEGIN if (header & header_mask) alloc->deallocate_string(dest); // mark the string as not allocated - dest = 0; + dest = NULL; header &= ~header_mask; return true; @@ -2427,7 +2459,7 @@ PUGI_IMPL_NS_BEGIN char_t* end; size_t size; - gap(): end(0), size(0) + gap(): end(NULL), size(0) { } @@ -2439,7 +2471,7 @@ PUGI_IMPL_NS_BEGIN { // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + memmove(end - size, end, (s - end) * sizeof(char_t)); } s += count; // end of current gap @@ -2456,7 +2488,7 @@ PUGI_IMPL_NS_BEGIN { // Move [old_gap_end, current_pos) to [old_gap_start, ...) assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + memmove(end - size, end, (s - end) * sizeof(char_t)); return s - size; } @@ -2614,7 +2646,7 @@ PUGI_IMPL_NS_BEGIN #define PUGI_IMPL_SCANWHILE(X) { while (X) ++s; } #define PUGI_IMPL_SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI_IMPL_UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 3; break; } s += 4; } } #define PUGI_IMPL_ENDSEG() { ch = *s; *s = 0; ++s; } - #define PUGI_IMPL_THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) + #define PUGI_IMPL_THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(NULL) #define PUGI_IMPL_CHECK_ERROR(err, m) { if (*s == 0) PUGI_IMPL_THROW_ERROR(err, m); } PUGI_IMPL_FN char_t* strconv_comment(char_t* s, char_t endch) @@ -2639,7 +2671,7 @@ PUGI_IMPL_NS_BEGIN } else if (*s == 0) { - return 0; + return NULL; } else ++s; } @@ -2667,7 +2699,7 @@ PUGI_IMPL_NS_BEGIN } else if (*s == 0) { - return 0; + return NULL; } else ++s; } @@ -2740,7 +2772,7 @@ PUGI_IMPL_NS_BEGIN case 5: return strconv_pcdata_impl::parse; case 6: return strconv_pcdata_impl::parse; case 7: return strconv_pcdata_impl::parse; - default: assert(false); return 0; // unreachable + default: assert(false); return NULL; // unreachable } } @@ -2794,7 +2826,7 @@ PUGI_IMPL_NS_BEGIN } else if (!*s) { - return 0; + return NULL; } else ++s; } @@ -2830,7 +2862,7 @@ PUGI_IMPL_NS_BEGIN } else if (!*s) { - return 0; + return NULL; } else ++s; } @@ -2862,7 +2894,7 @@ PUGI_IMPL_NS_BEGIN } else if (!*s) { - return 0; + return NULL; } else ++s; } @@ -2888,7 +2920,7 @@ PUGI_IMPL_NS_BEGIN } else if (!*s) { - return 0; + return NULL; } else ++s; } @@ -2917,7 +2949,7 @@ PUGI_IMPL_NS_BEGIN case 13: return strconv_attribute_impl::parse_wnorm; case 14: return strconv_attribute_impl::parse_wnorm; case 15: return strconv_attribute_impl::parse_wnorm; - default: assert(false); return 0; // unreachable + default: assert(false); return NULL; // unreachable } } @@ -2936,7 +2968,7 @@ PUGI_IMPL_NS_BEGIN char_t* error_offset; xml_parse_status error_status; - xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) + xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(NULL), error_status(status_ok) { } @@ -3268,6 +3300,7 @@ PUGI_IMPL_NS_BEGIN char_t ch = 0; xml_node_struct* cursor = root; char_t* mark = s; + char_t* merged_pcdata = s; while (*s != 0) { @@ -3462,21 +3495,38 @@ PUGI_IMPL_NS_BEGIN if (cursor->parent || PUGI_IMPL_OPTSET(parse_fragment)) { + char_t* parsed_pcdata = s; + + s = strconv_pcdata(s); + if (PUGI_IMPL_OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value) { - cursor->value = s; // Save the offset. + cursor->value = parsed_pcdata; // Save the offset. + } + else if (PUGI_IMPL_OPTSET(parse_merge_pcdata) && cursor->first_child && PUGI_IMPL_NODETYPE(cursor->first_child->prev_sibling_c) == node_pcdata) + { + assert(merged_pcdata >= cursor->first_child->prev_sibling_c->value); + + // Catch up to the end of last parsed value; only needed for the first fragment. + merged_pcdata += strlength(merged_pcdata); + + size_t length = strlength(parsed_pcdata); + + // Must use memmove instead of memcpy as this move may overlap + memmove(merged_pcdata, parsed_pcdata, (length + 1) * sizeof(char_t)); + merged_pcdata += length; } else { + xml_node_struct* prev_cursor = cursor; PUGI_IMPL_PUSHNODE(node_pcdata); // Append a new node on the tree. - cursor->value = s; // Save the offset. + cursor->value = parsed_pcdata; // Save the offset. + merged_pcdata = parsed_pcdata; // Used for parse_merge_pcdata above, cheaper to save unconditionally - PUGI_IMPL_POPNODE(); // Pop since this is a standalone. + cursor = prev_cursor; // Pop since this is a standalone. } - s = strconv_pcdata(s); - if (!*s) break; } else @@ -3530,7 +3580,7 @@ PUGI_IMPL_NS_BEGIN return make_parse_result(PUGI_IMPL_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 : 0; + xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : NULL; // create parser on stack xml_parser parser(static_cast(xmldoc)); @@ -3555,7 +3605,7 @@ PUGI_IMPL_NS_BEGIN 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 + 0 : root->first_child+ 0; + xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child + 0; if (!PUGI_IMPL_OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) return make_parse_result(status_no_document_element, length - 1); @@ -4423,7 +4473,10 @@ PUGI_IMPL_NS_BEGIN source_header |= xml_memory_page_contents_shared_mask; } else - strcpy_insitu(dest, header, header_mask, source, strlength(source)); + { + // if strcpy_insitu fails (out of memory) we just leave the destination name/value empty + (void)strcpy_insitu(dest, header, header_mask, source, strlength(source)); + } } } @@ -4447,7 +4500,7 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) { xml_allocator& alloc = get_allocator(dn); - xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; + xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : NULL; node_copy_contents(dn, sn, shared_alloc); @@ -4501,7 +4554,7 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) { xml_allocator& alloc = get_allocator(da); - xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0; + xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : NULL; node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); @@ -4610,18 +4663,18 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN double get_value_double(const char_t* value) { #ifdef PUGIXML_WCHAR_MODE - return wcstod(value, 0); + return wcstod(value, NULL); #else - return strtod(value, 0); + return strtod(value, NULL); #endif } PUGI_IMPL_FN float get_value_float(const char_t* value) { #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstod(value, 0)); + return static_cast(wcstod(value, NULL)); #else - return static_cast(strtod(value, 0)); + return static_cast(strtod(value, NULL)); #endif } @@ -4726,13 +4779,15 @@ PUGI_IMPL_NS_BEGIN 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); + auto_deleter contents_guard(own ? contents : NULL, xml_memory::deallocate); + + // early-out for empty documents to avoid buffer allocation overhead + if (size == 0) return make_parse_result((options & parse_fragment) ? status_ok : status_no_document_element); // get private buffer - char_t* buffer = 0; + char_t* buffer = NULL; size_t length = 0; - // 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 @@ -4756,46 +4811,58 @@ PUGI_IMPL_NS_BEGIN return res; } - // 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_IMPL_FN xml_parse_status get_file_size(FILE* file, size_t& out_result) + template PUGI_IMPL_FN xml_parse_status convert_file_size(T length, size_t& out_result) { - #if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 - // there are 64-bit versions of fseek/ftell, let's use them - typedef __int64 length_type; - - _fseeki64(file, 0, SEEK_END); - length_type length = _ftelli64(file); - _fseeki64(file, 0, SEEK_SET); - #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) - // there are 64-bit versions of fseek/ftell, let's use them - typedef off64_t length_type; - - fseeko64(file, 0, SEEK_END); - length_type length = ftello64(file); - fseeko64(file, 0, SEEK_SET); - #else - // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. - typedef long length_type; - - fseek(file, 0, SEEK_END); - length_type length = ftell(file); - fseek(file, 0, SEEK_SET); - #endif - // check for I/O errors if (length < 0) return status_io_error; // check for overflow size_t result = static_cast(length); - if (static_cast(result) != length) return status_out_of_memory; + if (static_cast(result) != length) return status_out_of_memory; - // finalize out_result = result; - return status_ok; } + // 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_IMPL_FN xml_parse_status get_file_size(FILE* file, size_t& out_result) + { + #if defined(__linux__) || defined(__APPLE__) + // this simultaneously retrieves the file size and file mode (to guard against loading non-files) + struct stat st; + if (fstat(fileno(file), &st) != 0) return status_io_error; + + // anything that's not a regular file doesn't have a coherent length + if (!S_ISREG(st.st_mode)) return status_io_error; + + xml_parse_status status = convert_file_size(st.st_size, out_result); + #elif defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 + // there are 64-bit versions of fseek/ftell, let's use them + _fseeki64(file, 0, SEEK_END); + __int64 length = _ftelli64(file); + _fseeki64(file, 0, SEEK_SET); + + xml_parse_status status = convert_file_size(length, out_result); + #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) + // there are 64-bit versions of fseek/ftell, let's use them + fseeko64(file, 0, SEEK_END); + off64_t length = ftello64(file); + fseeko64(file, 0, SEEK_SET); + + xml_parse_status status = convert_file_size(length, out_result); + #else + // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. + fseek(file, 0, SEEK_END); + long length = ftell(file); + fseek(file, 0, SEEK_SET); + + xml_parse_status status = convert_file_size(length, out_result); + #endif + + return status; + } + // This function assumes that buffer has extra sizeof(char_t) writable bytes after size PUGI_IMPL_FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) { @@ -4861,7 +4928,7 @@ PUGI_IMPL_NS_BEGIN static xml_stream_chunk* create() { void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); - if (!memory) return 0; + if (!memory) return NULL; return new (memory) xml_stream_chunk(); } @@ -4879,7 +4946,7 @@ PUGI_IMPL_NS_BEGIN } } - xml_stream_chunk(): next(0), size(0) + xml_stream_chunk(): next(NULL), size(0) { } @@ -4891,11 +4958,11 @@ PUGI_IMPL_NS_BEGIN template PUGI_IMPL_FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) { - auto_deleter > chunks(0, xml_stream_chunk::destroy); + auto_deleter > chunks(NULL, xml_stream_chunk::destroy); // read file to a chunk list size_t total = 0; - xml_stream_chunk* last = 0; + xml_stream_chunk* last = NULL; while (!stream.eof()) { @@ -4981,7 +5048,7 @@ PUGI_IMPL_NS_BEGIN template PUGI_IMPL_FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) { - void* buffer = 0; + void* buffer = NULL; size_t size = 0; xml_parse_status status = status_ok; @@ -5008,9 +5075,17 @@ PUGI_IMPL_NS_BEGIN #if defined(PUGI_IMPL_MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) PUGI_IMPL_FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) { +#ifdef PUGIXML_NO_STL + // ensure these symbols are consistently referenced to avoid 'unreferenced function' warnings + // note that generally these functions are used in STL builds, but PUGIXML_NO_STL leaves the only usage in convert_path_heap + (void)&as_utf8_begin; + (void)&as_utf8_end; + (void)&strlength_wide; +#endif + #if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 - FILE* file = 0; - return _wfopen_s(&file, path, mode) == 0 ? file : 0; + FILE* file = NULL; + return _wfopen_s(&file, path, mode) == 0 ? file : NULL; #else return _wfopen(path, mode); #endif @@ -5026,7 +5101,7 @@ PUGI_IMPL_NS_BEGIN // allocate resulting string char* result = static_cast(xml_memory::allocate(size + 1)); - if (!result) return 0; + if (!result) return NULL; // second pass: convert to utf8 as_utf8_end(result, size, str, length); @@ -5041,7 +5116,7 @@ PUGI_IMPL_NS_BEGIN { // there is no standard function to open wide paths, so our best bet is to try utf8 path char* path_utf8 = convert_path_heap(path); - if (!path_utf8) return 0; + if (!path_utf8) return NULL; // convert mode to ASCII (we mirror _wfopen interface) char mode_ascii[4] = {0}; @@ -5060,8 +5135,8 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN FILE* open_file(const char* path, const char* mode) { #if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 - FILE* file = 0; - return fopen_s(&file, path, mode) == 0 ? file : 0; + FILE* file = NULL; + return fopen_s(&file, path, mode) == 0 ? file : NULL; #else return fopen(path, mode); #endif @@ -5084,7 +5159,7 @@ PUGI_IMPL_NS_BEGIN name_null_sentry(xml_node_struct* node_): node(node_), name(node_->name) { - node->name = 0; + node->name = NULL; } ~name_null_sentry() @@ -5096,6 +5171,10 @@ PUGI_IMPL_NS_END namespace pugi { + PUGI_IMPL_FN xml_writer::~xml_writer() + { + } + PUGI_IMPL_FN xml_writer_file::xml_writer_file(void* file_): file(file_) { } @@ -5107,11 +5186,11 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream& stream): narrow_stream(&stream), wide_stream(NULL) { } - PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream& stream): narrow_stream(NULL), wide_stream(&stream) { } @@ -5155,7 +5234,7 @@ namespace pugi return true; } - PUGI_IMPL_FN xml_attribute::xml_attribute(): _attr(0) + PUGI_IMPL_FN xml_attribute::xml_attribute(): _attr(NULL) { } @@ -5169,7 +5248,7 @@ namespace pugi PUGI_IMPL_FN xml_attribute::operator xml_attribute::unspecified_bool_type() const { - return _attr ? unspecified_bool_xml_attribute : 0; + return _attr ? unspecified_bool_xml_attribute : NULL; } PUGI_IMPL_FN bool xml_attribute::operator!() const @@ -5299,7 +5378,7 @@ namespace pugi PUGI_IMPL_FN size_t xml_attribute::hash_value() const { - return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); + return reinterpret_cast(_attr) / sizeof(xml_attribute_struct); } PUGI_IMPL_FN xml_attribute_struct* xml_attribute::internal_object() const @@ -5355,6 +5434,14 @@ namespace pugi return *this; } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(string_view_t rhs) + { + set_value(rhs); + return *this; + } +#endif + #ifdef PUGIXML_HAS_LONG_LONG PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(long long rhs) { @@ -5376,13 +5463,22 @@ namespace pugi return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI_IMPL_FN bool xml_attribute::set_value(const char_t* rhs, size_t sz) + PUGI_IMPL_FN bool xml_attribute::set_name(const char_t* rhs, size_t size) { if (!_attr) return false; - return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, sz); + return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, size); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_attribute::set_name(string_view_t rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs.data(), rhs.size()); + } +#endif + PUGI_IMPL_FN bool xml_attribute::set_value(const char_t* rhs) { if (!_attr) return false; @@ -5390,6 +5486,22 @@ namespace pugi return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); } + PUGI_IMPL_FN bool xml_attribute::set_value(const char_t* rhs, size_t size) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, size); + } + +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_attribute::set_value(string_view_t rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs.data(), rhs.size()); + } +#endif + PUGI_IMPL_FN bool xml_attribute::set_value(int rhs) { if (!_attr) return false; @@ -5481,7 +5593,7 @@ namespace pugi } #endif - PUGI_IMPL_FN xml_node::xml_node(): _root(0) + PUGI_IMPL_FN xml_node::xml_node(): _root(NULL) { } @@ -5495,7 +5607,7 @@ namespace pugi PUGI_IMPL_FN xml_node::operator xml_node::unspecified_bool_type() const { - return _root ? unspecified_bool_xml_node : 0; + return _root ? unspecified_bool_xml_node : NULL; } PUGI_IMPL_FN bool xml_node::operator!() const @@ -5505,22 +5617,22 @@ namespace pugi PUGI_IMPL_FN xml_node::iterator xml_node::begin() const { - return iterator(_root ? _root->first_child + 0 : 0, _root); + return iterator(_root ? _root->first_child + 0 : NULL, _root); } PUGI_IMPL_FN xml_node::iterator xml_node::end() const { - return iterator(0, _root); + return iterator(NULL, _root); } PUGI_IMPL_FN xml_node::attribute_iterator xml_node::attributes_begin() const { - return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root); + return attribute_iterator(_root ? _root->first_attribute + 0 : NULL, _root); } PUGI_IMPL_FN xml_node::attribute_iterator xml_node::attributes_end() const { - return attribute_iterator(0, _root); + return attribute_iterator(NULL, _root); } PUGI_IMPL_FN xml_object_range xml_node::children() const @@ -5530,7 +5642,7 @@ namespace pugi PUGI_IMPL_FN xml_object_range xml_node::children(const char_t* name_) const { - return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); + return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(NULL, _root, name_)); } PUGI_IMPL_FN xml_object_range xml_node::attributes() const @@ -5653,6 +5765,64 @@ namespace pugi return xml_node(); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_node xml_node::child(string_view_t name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + { + const char_t* iname = i->name; + if (iname && impl::stringview_equal(name_, iname)) + return xml_node(i); + } + + return xml_node(); + } + + PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) + { + const char_t* iname = i->name; + if (iname && impl::stringview_equal(name_, iname)) + return xml_attribute(i); + } + + return xml_attribute(); + } + + PUGI_IMPL_FN xml_node xml_node::next_sibling(string_view_t name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) + { + const char_t* iname = i->name; + if (iname && impl::stringview_equal(name_, iname)) + return xml_node(i); + } + + return xml_node(); + } + + PUGI_IMPL_FN xml_node xml_node::previous_sibling(string_view_t name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) + { + const char_t* iname = i->name; + if (iname && impl::stringview_equal(name_, iname)) + return xml_node(i); + } + + return xml_node(); + } +#endif + PUGI_IMPL_FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const { xml_attribute_struct* hint = hint_._attr; @@ -5692,6 +5862,47 @@ namespace pugi return xml_attribute(); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_, xml_attribute& hint_) const + { + xml_attribute_struct* hint = hint_._attr; + + // if hint is not an attribute of node, behavior is not defined + assert(!hint || (_root && impl::is_attribute_of(hint, _root))); + + if (!_root) return xml_attribute(); + + // optimistically search from hint up until the end + for (xml_attribute_struct* i = hint; i; i = i->next_attribute) + { + const char_t* iname = i->name; + if (iname && impl::stringview_equal(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) + { + const char_t* jname = j->name; + if (jname && impl::stringview_equal(name_, jname)) + { + // update hint to maximize efficiency of searching for consecutive attributes + hint_._attr = j->next_attribute; + + return xml_attribute(j); + } + } + + return xml_attribute(); + } +#endif + PUGI_IMPL_FN xml_node xml_node::previous_sibling() const { if (!_root) return xml_node(); @@ -5773,16 +5984,28 @@ namespace pugi return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI_IMPL_FN bool xml_node::set_value(const char_t* rhs, size_t sz) + PUGI_IMPL_FN bool xml_node::set_name(const char_t* rhs, size_t size) { xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; - if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) + if (type_ != node_element && type_ != node_pi && type_ != node_declaration) return false; - return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, sz); + return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, size); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_node::set_name(string_view_t rhs) + { + xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; + + if (type_ != node_element && type_ != node_pi && type_ != node_declaration) + return false; + + return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs.data(), rhs.size()); + } +#endif + PUGI_IMPL_FN bool xml_node::set_value(const char_t* rhs) { xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; @@ -5793,6 +6016,28 @@ namespace pugi return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); } + PUGI_IMPL_FN bool xml_node::set_value(const char_t* rhs, size_t size) + { + xml_node_type type_ = _root ? PUGI_IMPL_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, size); + } + +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_node::set_value(string_view_t rhs) + { + xml_node_type type_ = _root ? PUGI_IMPL_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.data(), rhs.size()); + } +#endif + PUGI_IMPL_FN xml_attribute xml_node::append_attribute(const char_t* name_) { if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5863,6 +6108,78 @@ namespace pugi return a; } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_attribute xml_node::append_attribute(string_view_t name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::append_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI_IMPL_FN xml_attribute xml_node::prepend_attribute(string_view_t name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::prepend_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_after(string_view_t name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_after(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_before(string_view_t name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_before(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } +#endif + PUGI_IMPL_FN xml_attribute xml_node::append_copy(const xml_attribute& proto) { if (!proto) return xml_attribute(); @@ -6039,6 +6356,44 @@ namespace pugi return result; } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_node xml_node::append_child(string_view_t name_) + { + xml_node result = append_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI_IMPL_FN xml_node xml_node::prepend_child(string_view_t name_) + { + xml_node result = prepend_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI_IMPL_FN xml_node xml_node::insert_child_after(string_view_t name_, const xml_node& node) + { + xml_node result = insert_child_after(node_element, node); + + result.set_name(name_); + + return result; + } + + PUGI_IMPL_FN xml_node xml_node::insert_child_before(string_view_t name_, const xml_node& node) + { + xml_node result = insert_child_before(node_element, node); + + result.set_name(name_); + + return result; + } +#endif + PUGI_IMPL_FN xml_node xml_node::append_copy(const xml_node& proto) { xml_node_type type_ = proto.type(); @@ -6182,6 +6537,13 @@ namespace pugi return remove_attribute(attribute(name_)); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_node::remove_attribute(string_view_t name_) + { + return remove_attribute(attribute(name_)); + } +#endif + PUGI_IMPL_FN bool xml_node::remove_attribute(const xml_attribute& a) { if (!_root || !a._attr) return false; @@ -6212,7 +6574,7 @@ namespace pugi attr = next; } - _root->first_attribute = 0; + _root->first_attribute = NULL; return true; } @@ -6222,6 +6584,13 @@ namespace pugi return remove_child(child(name_)); } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_node::remove_child(string_view_t name_) + { + return remove_child(child(name_)); + } +#endif + PUGI_IMPL_FN bool xml_node::remove_child(const xml_node& n) { if (!_root || !n._root || n._root->parent != _root) return false; @@ -6251,7 +6620,7 @@ namespace pugi cur = next; } - _root->first_child = 0; + _root->first_child = NULL; return true; } @@ -6261,6 +6630,9 @@ namespace pugi // append_buffer is only valid for elements/documents if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); + // append buffer can not merge PCDATA into existing PCDATA nodes + if ((options & parse_merge_pcdata) != 0 && last_child().type() == node_pcdata) return impl::make_parse_result(status_append_invalid_root); + // get document node impl::xml_document_struct* doc = &impl::get_document(_root); @@ -6268,7 +6640,7 @@ namespace pugi doc->header |= impl::xml_memory_page_contents_shared_mask; // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) - impl::xml_memory_page* page = 0; + impl::xml_memory_page* page = NULL; impl::xml_extra_buffer* extra = static_cast(doc->allocate_memory(sizeof(impl::xml_extra_buffer) + sizeof(void*), page)); (void)page; @@ -6281,7 +6653,7 @@ namespace pugi #endif // add extra buffer to the list - extra->buffer = 0; + extra->buffer = NULL; extra->next = doc->extra_buffers; doc->extra_buffers = extra; @@ -6421,7 +6793,7 @@ namespace pugi xml_node arg_begin(_root); if (!walker.begin(arg_begin)) return false; - xml_node_struct* cur = _root ? _root->first_child + 0 : 0; + xml_node_struct* cur = _root ? _root->first_child + 0 : NULL; if (cur) { @@ -6463,7 +6835,7 @@ namespace pugi PUGI_IMPL_FN size_t xml_node::hash_value() const { - return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); + return reinterpret_cast(_root) / sizeof(xml_node_struct); } PUGI_IMPL_FN xml_node_struct* xml_node::internal_object() const @@ -6483,14 +6855,14 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI_IMPL_FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(std::basic_ostream& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const { xml_writer_stream writer(stream); print(writer, indent, flags, encoding, depth); } - PUGI_IMPL_FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(std::basic_ostream& stream, const char_t* indent, unsigned int flags, unsigned int depth) const { xml_writer_stream writer(stream); @@ -6557,7 +6929,7 @@ namespace pugi if (impl::is_text_node(node)) return node; - return 0; + return NULL; } PUGI_IMPL_FN xml_node_struct* xml_text::_data_new() @@ -6568,7 +6940,7 @@ namespace pugi return xml_node(_root).append_child(node_pcdata).internal_object(); } - PUGI_IMPL_FN xml_text::xml_text(): _root(0) + PUGI_IMPL_FN xml_text::xml_text(): _root(NULL) { } @@ -6578,7 +6950,7 @@ namespace pugi PUGI_IMPL_FN xml_text::operator xml_text::unspecified_bool_type() const { - return _data() ? unspecified_bool_xml_text : 0; + return _data() ? unspecified_bool_xml_text : NULL; } PUGI_IMPL_FN bool xml_text::operator!() const @@ -6588,7 +6960,7 @@ namespace pugi PUGI_IMPL_FN bool xml_text::empty() const { - return _data() == 0; + return _data() == NULL; } PUGI_IMPL_FN const char_t* xml_text::get() const @@ -6665,13 +7037,6 @@ namespace pugi } #endif - PUGI_IMPL_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_IMPL_FN bool xml_text::set(const char_t* rhs) { xml_node_struct* dn = _data_new(); @@ -6679,6 +7044,22 @@ namespace pugi return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) : false; } + PUGI_IMPL_FN bool xml_text::set(const char_t* rhs, size_t size) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, size) : false; + } + +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN bool xml_text::set(string_view_t rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs.data(), rhs.size()) : false; + } +#endif + PUGI_IMPL_FN bool xml_text::set(int rhs) { xml_node_struct* dn = _data_new(); @@ -6806,6 +7187,14 @@ namespace pugi return *this; } +#ifdef PUGIXML_HAS_STRING_VIEW + PUGI_IMPL_FN xml_text& xml_text::operator=(string_view_t rhs) + { + set(rhs); + return *this; + } +#endif + #ifdef PUGIXML_HAS_LONG_LONG PUGI_IMPL_FN xml_text& xml_text::operator=(long long rhs) { @@ -6868,7 +7257,7 @@ namespace pugi PUGI_IMPL_FN xml_node* xml_node_iterator::operator->() const { assert(_wrap._root); - return const_cast(&_wrap); // BCC5 workaround + return &_wrap; } PUGI_IMPL_FN xml_node_iterator& xml_node_iterator::operator++() @@ -6929,7 +7318,7 @@ namespace pugi PUGI_IMPL_FN xml_attribute* xml_attribute_iterator::operator->() const { assert(_wrap._attr); - return const_cast(&_wrap); // BCC5 workaround + return &_wrap; } PUGI_IMPL_FN xml_attribute_iterator& xml_attribute_iterator::operator++() @@ -6959,7 +7348,7 @@ namespace pugi return temp; } - PUGI_IMPL_FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) + PUGI_IMPL_FN xml_named_node_iterator::xml_named_node_iterator(): _name(NULL) { } @@ -6990,7 +7379,7 @@ namespace pugi PUGI_IMPL_FN xml_node* xml_named_node_iterator::operator->() const { assert(_wrap._root); - return const_cast(&_wrap); // BCC5 workaround + return &_wrap; } PUGI_IMPL_FN xml_named_node_iterator& xml_named_node_iterator::operator++() @@ -7069,7 +7458,7 @@ namespace pugi } } - PUGI_IMPL_FN xml_document::xml_document(): _buffer(0) + PUGI_IMPL_FN xml_document::xml_document(): _buffer(NULL) { _create(); } @@ -7080,7 +7469,7 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI_IMPL_FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(0) + PUGI_IMPL_FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(NULL) { _create(); _move(rhs); @@ -7162,7 +7551,7 @@ namespace pugi if (_buffer) { impl::xml_memory::deallocate(_buffer); - _buffer = 0; + _buffer = NULL; } // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator) @@ -7190,7 +7579,7 @@ namespace pugi static_cast(_root)->hash.clear(); #endif - _root = 0; + _root = NULL; } #ifdef PUGIXML_HAS_MOVE @@ -7245,7 +7634,7 @@ namespace pugi doc->_hash = &doc->hash; // make sure we don't access other hash up until the end when we reinitialize other document - other->_hash = 0; + other->_hash = NULL; #endif // move page structure @@ -7263,7 +7652,7 @@ namespace pugi page->prev = doc_page; doc_page->next = page; - other_page->next = 0; + other_page->next = NULL; } // make sure pages point to the correct document state @@ -7300,19 +7689,19 @@ namespace pugi // reset other document new (other) impl::xml_document_struct(PUGI_IMPL_GETPAGE(other)); - rhs._buffer = 0; + rhs._buffer = NULL; } #endif #ifndef PUGIXML_NO_STL - PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream& stream, unsigned int options, xml_encoding encoding) { reset(); return impl::load_stream_impl(static_cast(_root), stream, options, encoding, &_buffer); } - PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream& stream, unsigned int options) { reset(); @@ -7382,7 +7771,7 @@ namespace pugi { impl::xml_buffered_writer buffered_writer(writer, encoding); - if ((flags & format_write_bom) && encoding != encoding_latin1) + if ((flags & format_write_bom) && buffered_writer.encoding != encoding_latin1) { // BOM always represents the codepoint U+FEFF, so just write it in native encoding #ifdef PUGIXML_WCHAR_MODE @@ -7396,7 +7785,7 @@ namespace pugi if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) { buffered_writer.write_string(PUGIXML_TEXT("'); if (!(flags & format_raw)) buffered_writer.write('\n'); } @@ -7407,14 +7796,14 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI_IMPL_FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const { xml_writer_stream writer(stream); save(writer, indent, flags, encoding); } - PUGI_IMPL_FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream& stream, const char_t* indent, unsigned int flags) const { xml_writer_stream writer(stream); @@ -7727,7 +8116,7 @@ PUGI_IMPL_NS_BEGIN for (size_t probe = 0; probe <= hashmod; ++probe) { - if (table[bucket] == 0) + if (table[bucket] == NULL) { table[bucket] = key; return true; @@ -7775,7 +8164,7 @@ PUGI_IMPL_NS_BEGIN size_t _root_size; bool* _error; - xpath_allocator(xpath_memory_block* root, bool* error = 0): _root(root), _root_size(0), _error(error) + xpath_allocator(xpath_memory_block* root, bool* error = NULL): _root(root), _root_size(0), _error(error) { } @@ -7803,7 +8192,7 @@ PUGI_IMPL_NS_BEGIN if (!block) { if (_error) *_error = true; - return 0; + return NULL; } block->next = _root; @@ -7823,7 +8212,7 @@ PUGI_IMPL_NS_BEGIN new_size = (new_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); // we can only reallocate the last object - assert(ptr == 0 || static_cast(ptr) + old_size == &_root->data[0] + _root_size); + assert(ptr == NULL || static_cast(ptr) + old_size == &_root->data[0] + _root_size); // try to reallocate the object inplace if (ptr && _root_size - old_size + new_size <= _root->capacity) @@ -7834,7 +8223,7 @@ PUGI_IMPL_NS_BEGIN // allocate a new block void* result = allocate(new_size); - if (!result) return 0; + if (!result) return NULL; // we have a new block if (ptr) @@ -7929,7 +8318,7 @@ PUGI_IMPL_NS_BEGIN xpath_stack_data(): result(blocks + 0, &oom), temp(blocks + 1, &oom), oom(false) { - blocks[0].next = blocks[1].next = 0; + blocks[0].next = blocks[1].next = NULL; blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data); stack.result = &result; @@ -7955,7 +8344,7 @@ PUGI_IMPL_NS_BEGIN static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) { char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); - if (!result) return 0; + if (!result) return NULL; memcpy(result, string, length * sizeof(char_t)); result[length] = 0; @@ -8015,7 +8404,7 @@ PUGI_IMPL_NS_BEGIN size_t result_length = target_length + source_length; // allocate new buffer - char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); + char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : NULL, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); if (!result) return; // append first string to the new buffer in case there was no reallocation @@ -8050,7 +8439,7 @@ PUGI_IMPL_NS_BEGIN size_t length_ = strlength(_buffer); const char_t* data_ = duplicate_string(_buffer, length_, alloc); - if (!data_) return 0; + if (!data_) return NULL; _buffer = data_; _uses_heap = true; @@ -8259,7 +8648,7 @@ PUGI_IMPL_NS_BEGIN if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; } - return 0; + return NULL; } xml_attribute_struct* attr = xnode.attribute().internal_object(); @@ -8272,10 +8661,10 @@ PUGI_IMPL_NS_BEGIN if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; } - return 0; + return NULL; } - return 0; + return NULL; } struct document_order_comparator @@ -8388,7 +8777,7 @@ PUGI_IMPL_NS_BEGIN if (v == 0) return PUGIXML_TEXT("0"); if (v != v) return PUGIXML_TEXT("NaN"); if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - return 0; + return NULL; #endif } @@ -8433,7 +8822,7 @@ PUGI_IMPL_NS_BEGIN // extract mantissa string: skip sign char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; - assert(mantissa[0] != '0' && mantissa[1] == '.'); + assert(mantissa[0] != '0' && (mantissa[1] == '.' || mantissa[1] == ',')); // divide mantissa by 10 to eliminate integer part mantissa[1] = mantissa[0]; @@ -8553,9 +8942,9 @@ PUGI_IMPL_NS_BEGIN // parse string #ifdef PUGIXML_WCHAR_MODE - return wcstod(string, 0); + return wcstod(string, NULL); #else - return strtod(string, 0); + return strtod(string, NULL); #endif } @@ -8617,7 +9006,7 @@ PUGI_IMPL_NS_BEGIN { const char_t* pos = find_char(name, ':'); - prefix = pos ? name : 0; + prefix = pos ? name : NULL; prefix_length = pos ? static_cast(pos - name) : 0; } @@ -8735,7 +9124,7 @@ PUGI_IMPL_NS_BEGIN unsigned int tc = static_cast(*to); if (fc >= 128 || tc >= 128) - return 0; + return NULL; // code=128 means "skip character" if (!table[fc]) @@ -8750,7 +9139,7 @@ PUGI_IMPL_NS_BEGIN table[i] = static_cast(i); void* result = alloc->allocate(sizeof(table)); - if (!result) return 0; + if (!result) return NULL; memcpy(result, table, sizeof(table)); @@ -8814,7 +9203,7 @@ PUGI_IMPL_NS_BEGIN struct xpath_variable_string: xpath_variable { - xpath_variable_string(): xpath_variable(xpath_type_string), value(0) + xpath_variable_string(): xpath_variable(xpath_type_string), value(NULL) { } @@ -8837,8 +9226,6 @@ PUGI_IMPL_NS_BEGIN char_t name[1]; }; - static const xpath_node_set dummy_node_set; - PUGI_IMPL_FN PUGI_IMPL_UNSIGNED_OVERFLOW unsigned int hash_string(const char_t* str) { // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) @@ -8861,11 +9248,11 @@ PUGI_IMPL_NS_BEGIN template PUGI_IMPL_FN T* new_xpath_variable(const char_t* name) { size_t length = strlength(name); - if (length == 0) return 0; // empty variable names are invalid + if (length == 0) return NULL; // empty variable names are invalid // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t)); - if (!memory) return 0; + if (!memory) return NULL; T* result = new (memory) T(); @@ -8891,7 +9278,7 @@ PUGI_IMPL_NS_BEGIN return new_xpath_variable(name); default: - return 0; + return NULL; } } @@ -9044,7 +9431,7 @@ PUGI_IMPL_NS_BEGIN xpath_node* _eos; public: - xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) + xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(NULL), _end(NULL), _eos(NULL) { } @@ -9130,10 +9517,10 @@ PUGI_IMPL_NS_BEGIN size_t hash_size = 1; while (hash_size < size_ + size_ / 2) hash_size *= 2; - const void** hash_data = static_cast(alloc->allocate(hash_size * sizeof(void**))); + const void** hash_data = static_cast(alloc->allocate(hash_size * sizeof(void*))); if (!hash_data) return; - memset(hash_data, 0, hash_size * sizeof(const void**)); + memset(hash_data, 0, hash_size * sizeof(void*)); xpath_node* write = _begin; @@ -9236,7 +9623,7 @@ PUGI_IMPL_NS_BEGIN const char_t* begin; const char_t* end; - xpath_lexer_string(): begin(0), end(0) + xpath_lexer_string(): begin(NULL), end(NULL) { } @@ -9931,7 +10318,8 @@ PUGI_IMPL_NS_BEGIN xpath_node* last = ns.begin() + first; - xpath_context c(xpath_node(), 1, size); + xpath_node cn; + xpath_context c(cn, 1, size); double er = expr->eval_number(c, stack); @@ -10423,40 +10811,40 @@ PUGI_IMPL_NS_BEGIN public: xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(NULL), _right(NULL), _next(NULL) { assert(type == ast_string_constant); _data.string = value; } xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(NULL), _right(NULL), _next(NULL) { assert(type == ast_number_constant); _data.number = value; } xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(NULL), _right(NULL), _next(NULL) { assert(type == ast_variable); _data.variable = value; } - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = NULL, xpath_ast_node* right = NULL): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(NULL) { } xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): - _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(0), _next(0) + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(NULL), _next(NULL) { assert(type == ast_step); _data.nodetest = contents; } xpath_ast_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test): - _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast(test)), _left(left), _right(right), _next(0) + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast(test)), _left(left), _right(right), _next(NULL) { assert(type == ast_filter || type == ast_predicate); } @@ -10516,7 +10904,7 @@ PUGI_IMPL_NS_BEGIN xpath_string lr = _left->eval_string(c, stack); xpath_string rr = _right->eval_string(c, stack); - return find_substring(lr.c_str(), rr.c_str()) != 0; + return find_substring(lr.c_str(), rr.c_str()) != NULL; } case ast_func_boolean: @@ -10730,13 +11118,7 @@ PUGI_IMPL_NS_BEGIN return eval_boolean(c, stack) ? 1 : 0; case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - case xpath_type_node_set: + case xpath_type_node_set: // implicit conversion to string { xpath_allocator_capture cr(stack.result); @@ -11325,7 +11707,7 @@ PUGI_IMPL_NS_BEGIN _result->error = message; _result->offset = _lexer.current_pos() - _query; - return 0; + return NULL; } xpath_ast_node* error_oom() @@ -11333,7 +11715,7 @@ PUGI_IMPL_NS_BEGIN assert(_alloc->_error); *_alloc->_error = true; - return 0; + return NULL; } xpath_ast_node* error_rec() @@ -11349,37 +11731,37 @@ PUGI_IMPL_NS_BEGIN xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, const char_t* value) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + return memory ? new (memory) xpath_ast_node(type, rettype, value) : NULL; } xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, double value) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + return memory ? new (memory) xpath_ast_node(type, rettype, value) : NULL; } xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_variable* value) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + return memory ? new (memory) xpath_ast_node(type, rettype, value) : NULL; } - xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node* left = 0, xpath_ast_node* right = 0) + xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node* left = NULL, xpath_ast_node* right = NULL) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, rettype, left, right) : 0; + return memory ? new (memory) xpath_ast_node(type, rettype, left, right) : NULL; } xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, left, axis, test, contents) : 0; + return memory ? new (memory) xpath_ast_node(type, left, axis, test, contents) : NULL; } xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test) { void* memory = alloc_node(); - return memory ? new (memory) xpath_ast_node(type, left, right, test) : 0; + return memory ? new (memory) xpath_ast_node(type, left, right, test) : NULL; } const char_t* alloc_string(const xpath_lexer_string& value) @@ -11390,7 +11772,7 @@ PUGI_IMPL_NS_BEGIN size_t length = static_cast(value.end - value.begin); char_t* c = static_cast(_alloc->allocate((length + 1) * sizeof(char_t))); - if (!c) return 0; + if (!c) return NULL; memcpy(c, value.begin, length * sizeof(char_t)); c[length] = 0; @@ -11633,7 +12015,7 @@ PUGI_IMPL_NS_BEGIN if (!_variables) return error("Unknown variable: variable set is not provided"); - xpath_variable* var = 0; + xpath_variable* var = NULL; if (!get_variable_scratch(_scratch, _variables, name.begin, name.end, &var)) return error_oom(); @@ -11650,7 +12032,7 @@ PUGI_IMPL_NS_BEGIN _lexer.next(); xpath_ast_node* n = parse_expression(); - if (!n) return 0; + if (!n) return NULL; if (_lexer.current() != lex_close_brace) return error("Expected ')' to match an opening '('"); @@ -11663,7 +12045,7 @@ PUGI_IMPL_NS_BEGIN case lex_quoted_string: { const char_t* value = alloc_string(_lexer.contents()); - if (!value) return 0; + if (!value) return NULL; _lexer.next(); @@ -11684,13 +12066,13 @@ PUGI_IMPL_NS_BEGIN case lex_string: { - xpath_ast_node* args[2] = {0}; + xpath_ast_node* args[2] = {NULL}; size_t argc = 0; xpath_lexer_string function = _lexer.contents(); _lexer.next(); - xpath_ast_node* last_arg = 0; + xpath_ast_node* last_arg = NULL; if (_lexer.current() != lex_open_brace) return error("Unrecognized function call"); @@ -11711,7 +12093,7 @@ PUGI_IMPL_NS_BEGIN return error_rec(); xpath_ast_node* n = parse_expression(); - if (!n) return 0; + if (!n) return NULL; if (argc < 2) args[argc] = n; else last_arg->set_next(n); @@ -11738,7 +12120,7 @@ PUGI_IMPL_NS_BEGIN xpath_ast_node* parse_filter_expression() { xpath_ast_node* n = parse_primary_expression(); - if (!n) return 0; + if (!n) return NULL; size_t old_depth = _depth; @@ -11753,10 +12135,10 @@ PUGI_IMPL_NS_BEGIN return error("Predicate has to be applied to node set"); xpath_ast_node* expr = parse_expression(); - if (!expr) return 0; + if (!expr) return NULL; n = alloc_node(ast_filter, n, expr, predicate_default); - if (!n) return 0; + if (!n) return NULL; if (_lexer.current() != lex_close_square_brace) return error("Expected ']' to match an opening '['"); @@ -11796,7 +12178,7 @@ PUGI_IMPL_NS_BEGIN if (_lexer.current() == lex_open_square_brace) return error("Predicates are not allowed after an abbreviated step"); - return alloc_node(ast_step, set, axis_self, nodetest_type_node, 0); + return alloc_node(ast_step, set, axis_self, nodetest_type_node, NULL); } else if (_lexer.current() == lex_double_dot) { @@ -11805,7 +12187,7 @@ PUGI_IMPL_NS_BEGIN if (_lexer.current() == lex_open_square_brace) return error("Predicates are not allowed after an abbreviated step"); - return alloc_node(ast_step, set, axis_parent, nodetest_type_node, 0); + return alloc_node(ast_step, set, axis_parent, nodetest_type_node, NULL); } nodetest_t nt_type = nodetest_none; @@ -11912,14 +12294,14 @@ PUGI_IMPL_NS_BEGIN } const char_t* nt_name_copy = alloc_string(nt_name); - if (!nt_name_copy) return 0; + if (!nt_name_copy) return NULL; xpath_ast_node* n = alloc_node(ast_step, set, axis, nt_type, nt_name_copy); - if (!n) return 0; + if (!n) return NULL; size_t old_depth = _depth; - xpath_ast_node* last = 0; + xpath_ast_node* last = NULL; while (_lexer.current() == lex_open_square_brace) { @@ -11929,10 +12311,10 @@ PUGI_IMPL_NS_BEGIN return error_rec(); xpath_ast_node* expr = parse_expression(); - if (!expr) return 0; + if (!expr) return NULL; - xpath_ast_node* pred = alloc_node(ast_predicate, 0, expr, predicate_default); - if (!pred) return 0; + xpath_ast_node* pred = alloc_node(ast_predicate, NULL, expr, predicate_default); + if (!pred) return NULL; if (_lexer.current() != lex_close_square_brace) return error("Expected ']' to match an opening '['"); @@ -11953,7 +12335,7 @@ PUGI_IMPL_NS_BEGIN xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) { xpath_ast_node* n = parse_step(set); - if (!n) return 0; + if (!n) return NULL; size_t old_depth = _depth; @@ -11964,8 +12346,8 @@ PUGI_IMPL_NS_BEGIN if (l == lex_double_slash) { - n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - if (!n) return 0; + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, NULL); + if (!n) return NULL; ++_depth; } @@ -11974,7 +12356,7 @@ PUGI_IMPL_NS_BEGIN return error_rec(); n = parse_step(n); - if (!n) return 0; + if (!n) return NULL; } _depth = old_depth; @@ -11991,7 +12373,7 @@ PUGI_IMPL_NS_BEGIN _lexer.next(); xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set); - if (!n) return 0; + if (!n) return NULL; // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path lexeme_t l = _lexer.current(); @@ -12006,16 +12388,16 @@ PUGI_IMPL_NS_BEGIN _lexer.next(); xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set); - if (!n) return 0; + if (!n) return NULL; - n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - if (!n) return 0; + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, NULL); + if (!n) return NULL; return parse_relative_location_path(n); } // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 - return parse_relative_location_path(0); + return parse_relative_location_path(NULL); } // PathExpr ::= LocationPath @@ -12052,7 +12434,7 @@ PUGI_IMPL_NS_BEGIN } xpath_ast_node* n = parse_filter_expression(); - if (!n) return 0; + if (!n) return NULL; if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) { @@ -12064,8 +12446,8 @@ PUGI_IMPL_NS_BEGIN if (n->rettype() != xpath_type_node_set) return error("Step has to be applied to node set"); - n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - if (!n) return 0; + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, NULL); + if (!n) return NULL; } // select from location path @@ -12080,7 +12462,7 @@ PUGI_IMPL_NS_BEGIN // precedence 7+ - only parses union expressions xpath_ast_node* n = parse_expression(7); - if (!n) return 0; + if (!n) return NULL; return alloc_node(ast_op_negate, xpath_type_number, n); } @@ -12168,14 +12550,14 @@ PUGI_IMPL_NS_BEGIN return error_rec(); xpath_ast_node* rhs = parse_path_or_unary_expression(); - if (!rhs) return 0; + if (!rhs) return NULL; binary_op_t nextop = binary_op_t::parse(_lexer); while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence) { rhs = parse_expression_rec(rhs, nextop.precedence); - if (!rhs) return 0; + if (!rhs) return NULL; nextop = binary_op_t::parse(_lexer); } @@ -12184,7 +12566,7 @@ PUGI_IMPL_NS_BEGIN return error("Union operator has to be applied to node sets"); lhs = alloc_node(op.asttype, op.rettype, lhs, rhs); - if (!lhs) return 0; + if (!lhs) return NULL; op = binary_op_t::parse(_lexer); } @@ -12218,7 +12600,7 @@ PUGI_IMPL_NS_BEGIN return error_rec(); xpath_ast_node* n = parse_path_or_unary_expression(); - if (!n) return 0; + if (!n) return NULL; n = parse_expression_rec(n, limit); @@ -12234,7 +12616,7 @@ PUGI_IMPL_NS_BEGIN xpath_ast_node* parse() { xpath_ast_node* n = parse_expression(); - if (!n) return 0; + if (!n) return NULL; assert(_depth == 0); @@ -12258,7 +12640,7 @@ PUGI_IMPL_NS_BEGIN static xpath_query_impl* create() { void* memory = xml_memory::allocate(sizeof(xpath_query_impl)); - if (!memory) return 0; + if (!memory) return NULL; return new (memory) xpath_query_impl(); } @@ -12272,9 +12654,9 @@ PUGI_IMPL_NS_BEGIN xml_memory::deallocate(impl); } - xpath_query_impl(): root(0), alloc(&block, &oom), oom(false) + xpath_query_impl(): root(NULL), alloc(&block, &oom), oom(false) { - block.next = 0; + block.next = NULL; block.capacity = sizeof(block.data); } @@ -12286,7 +12668,7 @@ PUGI_IMPL_NS_BEGIN PUGI_IMPL_FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) { - if (!impl) return 0; + if (!impl) return NULL; if (impl->root->rettype() != xpath_type_node_set) { @@ -12312,7 +12694,7 @@ namespace pugi assert(_result.error); } - PUGI_IMPL_FN const char* xpath_exception::what() const throw() + PUGI_IMPL_FN const char* xpath_exception::what() const PUGIXML_NOEXCEPT { return _result.error; } @@ -12356,7 +12738,7 @@ namespace pugi PUGI_IMPL_FN xpath_node::operator xpath_node::unspecified_bool_type() const { - return (_node || _attribute) ? unspecified_bool_xpath_node : 0; + return (_node || _attribute) ? unspecified_bool_xpath_node : NULL; } PUGI_IMPL_FN bool xpath_node::operator!() const @@ -12526,7 +12908,7 @@ namespace pugi PUGI_IMPL_FN xpath_parse_result::operator bool() const { - return error == 0; + return error == NULL; } PUGI_IMPL_FN const char* xpath_parse_result::description() const @@ -12534,7 +12916,7 @@ namespace pugi return error ? error : "No error"; } - PUGI_IMPL_FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) + PUGI_IMPL_FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(NULL) { } @@ -12556,7 +12938,7 @@ namespace pugi default: assert(false && "Invalid variable type"); // unreachable - return 0; + return NULL; } } @@ -12577,13 +12959,16 @@ namespace pugi PUGI_IMPL_FN const char_t* xpath_variable::get_string() const { - const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; + const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : NULL; return value ? value : PUGIXML_TEXT(""); } PUGI_IMPL_FN const xpath_node_set& xpath_variable::get_node_set() const { - return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; + if (_type == xpath_type_node_set) + return static_cast(this)->value; + static const xpath_node_set dummy_node_set; + return dummy_node_set; } PUGI_IMPL_FN bool xpath_variable::set(bool value) @@ -12634,7 +13019,7 @@ namespace pugi PUGI_IMPL_FN xpath_variable_set::xpath_variable_set() { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - _data[i] = 0; + _data[i] = NULL; } PUGI_IMPL_FN xpath_variable_set::~xpath_variable_set() @@ -12646,7 +13031,7 @@ namespace pugi PUGI_IMPL_FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - _data[i] = 0; + _data[i] = NULL; _assign(rhs); } @@ -12666,7 +13051,7 @@ namespace pugi for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) { _data[i] = rhs._data[i]; - rhs._data[i] = 0; + rhs._data[i] = NULL; } } @@ -12677,7 +13062,7 @@ namespace pugi _destroy(_data[i]); _data[i] = rhs._data[i]; - rhs._data[i] = 0; + rhs._data[i] = NULL; } return *this; @@ -12713,15 +13098,18 @@ namespace pugi // look for existing variable for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) + { + const char_t* vn = var->name(); + if (vn && impl::strequal(vn, name)) return var; + } - return 0; + return NULL; } PUGI_IMPL_FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) { - xpath_variable* last = 0; + xpath_variable* last = NULL; while (var) { @@ -12765,8 +13153,11 @@ namespace pugi // look for existing variable for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) - return var->type() == type ? var : 0; + { + const char_t* vn = var->name(); + if (vn && impl::strequal(vn, name)) + return var->type() == type ? var : NULL; + } // add new variable xpath_variable* result = impl::new_xpath_variable(type, name); @@ -12815,7 +13206,7 @@ namespace pugi return _find(name); } - PUGI_IMPL_FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) + PUGI_IMPL_FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(NULL) { impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); @@ -12839,7 +13230,7 @@ namespace pugi qimpl->root->optimize(&qimpl->alloc); _impl = impl.release(); - _result.error = 0; + _result.error = NULL; } else { @@ -12853,7 +13244,7 @@ namespace pugi } } - PUGI_IMPL_FN xpath_query::xpath_query(): _impl(0) + PUGI_IMPL_FN xpath_query::xpath_query(): _impl(NULL) { } @@ -12868,7 +13259,7 @@ namespace pugi { _impl = rhs._impl; _result = rhs._result; - rhs._impl = 0; + rhs._impl = NULL; rhs._result = xpath_parse_result(); } @@ -12881,7 +13272,7 @@ namespace pugi _impl = rhs._impl; _result = rhs._result; - rhs._impl = 0; + rhs._impl = NULL; rhs._result = xpath_parse_result(); return *this; @@ -13045,7 +13436,7 @@ namespace pugi PUGI_IMPL_FN xpath_query::operator xpath_query::unspecified_bool_type() const { - return _impl ? unspecified_bool_xpath_query : 0; + return _impl ? unspecified_bool_xpath_query : NULL; } PUGI_IMPL_FN bool xpath_query::operator!() const @@ -13093,16 +13484,20 @@ namespace pugi # pragma option pop #endif +#if defined(_MSC_VER) && defined(__c2__) +# pragma clang diagnostic pop +#endif + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + // Intel C++ does not properly keep warning state for function templates, // so popping warning state at the end of translation unit leads to warnings in the middle. #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) # pragma warning(pop) #endif -#if defined(_MSC_VER) && defined(__c2__) -# pragma clang diagnostic pop -#endif - // Undefine all local macros (makes sure we're not leaking macros in header-only mode) #undef PUGI_IMPL_NO_INLINE #undef PUGI_IMPL_UNLIKELY @@ -13137,7 +13532,7 @@ namespace pugi #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2025 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/WickedEngine/Utility/pugixml.hpp b/WickedEngine/Utility/pugixml.hpp index bdeb52e0c..c5744e720 100644 --- a/WickedEngine/Utility/pugixml.hpp +++ b/WickedEngine/Utility/pugixml.hpp @@ -1,20 +1,18 @@ /** - * pugixml parser - version 1.13 + * pugixml parser - version 1.15 * -------------------------------------------------------- - * 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 - * of this file. + * SPDX-FileCopyrightText: Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * SPDX-License-Identifier: MIT * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + * See LICENSE.md or notice at the end of this file. */ // 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 #ifndef PUGIXML_VERSION -# define PUGIXML_VERSION 1130 // 1.13 +# define PUGIXML_VERSION 1150 // 1.15 #endif // Include user configuration file (this can define various configuration macros) @@ -38,6 +36,20 @@ # include #endif +// Check if std::string_view is available +#if !defined(PUGIXML_HAS_STRING_VIEW) && !defined(PUGIXML_NO_STL) +# if __cplusplus >= 201703L +# define PUGIXML_HAS_STRING_VIEW +# elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L +# define PUGIXML_HAS_STRING_VIEW +# endif +#endif + +// Include string_view if appropriate +#ifdef PUGIXML_HAS_STRING_VIEW +# include +#endif + // Macro for deprecated features #ifndef PUGIXML_DEPRECATED # if defined(__GNUC__) @@ -82,14 +94,14 @@ # endif #endif -// If C++ is 2011 or higher, add 'noexcept' specifiers +// If C++ is 2011 or higher, use 'noexcept' specifiers #ifndef PUGIXML_NOEXCEPT # if __cplusplus >= 201103 # define PUGIXML_NOEXCEPT noexcept # elif defined(_MSC_VER) && _MSC_VER >= 1900 # define PUGIXML_NOEXCEPT noexcept # else -# define PUGIXML_NOEXCEPT +# define PUGIXML_NOEXCEPT throw() # endif #endif @@ -138,7 +150,12 @@ namespace pugi #ifndef PUGIXML_NO_STL // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE - typedef std::basic_string, std::allocator > string_t; + typedef std::basic_string string_t; +#endif + +#ifdef PUGIXML_HAS_STRING_VIEW + // String view type used for operations that can work with a length delimited string; depends on PUGIXML_WCHAR_MODE + typedef std::basic_string_view string_view_t; #endif } @@ -213,6 +230,10 @@ namespace pugi // This flag is off by default. const unsigned int parse_embed_pcdata = 0x2000; + // This flag determines whether determines whether the the two pcdata should be merged or not, if no intermediatory data are parsed in the document. + // This flag is off by default. + const unsigned int parse_merge_pcdata = 0x4000; + // The default parsing mode. // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. @@ -324,7 +345,7 @@ namespace pugi class PUGIXML_CLASS xml_writer { public: - virtual ~xml_writer() {} + virtual ~xml_writer(); // Write memory chunk into stream/file/whatever virtual void write(const void* data, size_t size) = 0; @@ -349,14 +370,14 @@ namespace pugi { public: // Construct writer from an output stream object - xml_writer_stream(std::basic_ostream >& stream); - xml_writer_stream(std::basic_ostream >& stream); + xml_writer_stream(std::basic_ostream& stream); + xml_writer_stream(std::basic_ostream& stream); virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; private: - std::basic_ostream >* narrow_stream; - std::basic_ostream >* wide_stream; + std::basic_ostream* narrow_stream; + std::basic_ostream* wide_stream; }; #endif @@ -392,7 +413,7 @@ namespace pugi bool operator<=(const xml_attribute& r) const; bool operator>=(const xml_attribute& r) const; - // Check if attribute is empty + // Check if attribute is empty (null) bool empty() const; // Get attribute name/value, or "" if attribute is empty @@ -418,8 +439,15 @@ 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_name(const char_t* rhs, size_t size); + #ifdef PUGIXML_HAS_STRING_VIEW + bool set_name(string_view_t rhs); + #endif bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); + #ifdef PUGIXML_HAS_STRING_VIEW + bool set_value(string_view_t rhs); + #endif // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") bool set_value(int rhs); @@ -447,6 +475,10 @@ namespace pugi xml_attribute& operator=(float rhs); xml_attribute& operator=(bool rhs); + #ifdef PUGIXML_HAS_STRING_VIEW + xml_attribute& operator=(string_view_t rhs); + #endif + #ifdef PUGIXML_HAS_LONG_LONG xml_attribute& operator=(long long rhs); xml_attribute& operator=(unsigned long long rhs); @@ -502,7 +534,7 @@ namespace pugi bool operator<=(const xml_node& r) const; bool operator>=(const xml_node& r) const; - // Check if node is empty. + // Check if node is empty (null) bool empty() const; // Get node type @@ -541,9 +573,18 @@ namespace pugi xml_attribute attribute(const char_t* name) const; xml_node next_sibling(const char_t* name) const; xml_node previous_sibling(const char_t* name) const; + #ifdef PUGIXML_HAS_STRING_VIEW + xml_node child(string_view_t name) const; + xml_attribute attribute(string_view_t name) const; + xml_node next_sibling(string_view_t name) const; + xml_node previous_sibling(string_view_t name) const; + #endif // Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast) xml_attribute attribute(const char_t* name, xml_attribute& hint) const; + #ifdef PUGIXML_HAS_STRING_VIEW + xml_attribute attribute(string_view_t name, xml_attribute& hint) const; + #endif // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA const char_t* child_value() const; @@ -553,14 +594,27 @@ 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_name(const char_t* rhs, size_t size); + #ifdef PUGIXML_HAS_STRING_VIEW + bool set_name(string_view_t rhs); + #endif bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); + #ifdef PUGIXML_HAS_STRING_VIEW + bool set_value(string_view_t rhs); + #endif // Add attribute with specified name. Returns added attribute, or empty attribute on errors. xml_attribute append_attribute(const char_t* name); xml_attribute prepend_attribute(const char_t* name); xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); + #ifdef PUGIXML_HAS_STRING_VIEW + xml_attribute append_attribute(string_view_t name); + xml_attribute prepend_attribute(string_view_t name); + xml_attribute insert_attribute_after(string_view_t name, const xml_attribute& attr); + xml_attribute insert_attribute_before(string_view_t name, const xml_attribute& attr); + #endif // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. xml_attribute append_copy(const xml_attribute& proto); @@ -579,6 +633,12 @@ namespace pugi xml_node prepend_child(const char_t* name); xml_node insert_child_after(const char_t* name, const xml_node& node); xml_node insert_child_before(const char_t* name, const xml_node& node); + #ifdef PUGIXML_HAS_STRING_VIEW + xml_node append_child(string_view_t name); + xml_node prepend_child(string_view_t name); + xml_node insert_child_after(string_view_t, const xml_node& node); + xml_node insert_child_before(string_view_t name, const xml_node& node); + #endif // Add a copy of the specified node as a child. Returns added node, or empty node on errors. xml_node append_copy(const xml_node& proto); @@ -595,6 +655,9 @@ namespace pugi // Remove specified attribute bool remove_attribute(const xml_attribute& a); bool remove_attribute(const char_t* name); + #ifdef PUGIXML_HAS_STRING_VIEW + bool remove_attribute(string_view_t name); + #endif // Remove all attributes bool remove_attributes(); @@ -602,6 +665,9 @@ namespace pugi // Remove specified child bool remove_child(const xml_node& n); bool remove_child(const char_t* name); + #ifdef PUGIXML_HAS_STRING_VIEW + bool remove_child(string_view_t name); + #endif // Remove all children bool remove_children(); @@ -694,8 +760,8 @@ namespace pugi #ifndef PUGIXML_NO_STL // Print subtree to stream - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; + void print(std::basic_ostream& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + void print(std::basic_ostream& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; #endif // Child nodes iterators @@ -758,7 +824,7 @@ namespace pugi // Borland C++ workaround bool operator!() const; - // Check if text object is empty + // Check if text object is empty (null) bool empty() const; // Get text, or "" if object is empty @@ -782,8 +848,11 @@ 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); + bool set(const char_t* rhs, size_t size); + #ifdef PUGIXML_HAS_STRING_VIEW + bool set(string_view_t rhs); + #endif // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") bool set(int rhs); @@ -811,6 +880,10 @@ namespace pugi xml_text& operator=(float rhs); xml_text& operator=(bool rhs); + #ifdef PUGIXML_HAS_STRING_VIEW + xml_text& operator=(string_view_t rhs); + #endif + #ifdef PUGIXML_HAS_LONG_LONG xml_text& operator=(long long rhs); xml_text& operator=(unsigned long long rhs); @@ -1066,8 +1139,8 @@ namespace pugi #ifndef PUGIXML_NO_STL // Load document from stream. - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); + xml_parse_result load(std::basic_istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load(std::basic_istream& stream, unsigned int options = parse_default); #endif // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. @@ -1096,8 +1169,8 @@ namespace pugi #ifndef PUGIXML_NO_STL // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; + void save(std::basic_ostream& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + void save(std::basic_ostream& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; #endif // Save XML to file @@ -1308,7 +1381,7 @@ namespace pugi explicit xpath_exception(const xpath_parse_result& result); // Get error message - virtual const char* what() const throw() PUGIXML_OVERRIDE; + virtual const char* what() const PUGIXML_NOEXCEPT PUGIXML_OVERRIDE; // Get parse result const xpath_parse_result& result() const; @@ -1433,12 +1506,12 @@ namespace pugi #ifndef PUGIXML_NO_STL // Convert wide string to UTF8 - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); + std::basic_string PUGIXML_FUNCTION as_utf8(const wchar_t* str); + std::basic_string PUGIXML_FUNCTION as_utf8(const std::basic_string& str); // Convert UTF8 to wide string - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); + std::basic_string PUGIXML_FUNCTION as_wide(const char* str); + std::basic_string PUGIXML_FUNCTION as_wide(const std::basic_string& str); #endif // Memory allocation function interface; returns pointer to allocated memory or NULL on failure @@ -1485,7 +1558,7 @@ namespace std #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2025 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/WickedEngine/WickedEngine_Windows.vcxproj b/WickedEngine/WickedEngine_Windows.vcxproj index 38a95ca2d..e4e5c9f8c 100644 --- a/WickedEngine/WickedEngine_Windows.vcxproj +++ b/WickedEngine/WickedEngine_Windows.vcxproj @@ -62,7 +62,7 @@ Level3 Disabled - _DEBUG;_LIB;%(PreprocessorDefinitions);JPH_DEBUG_RENDERER;JPH_USE_F16C;JPH_USE_FMADD + _DEBUG;_LIB;%(PreprocessorDefinitions);JPH_DEBUG_RENDERER;JPH_USE_F16C;JPH_USE_FMADD;_HAS_EXCEPTIONS=0 %(AdditionalIncludeDirectories) true false @@ -74,6 +74,7 @@ stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false Windows @@ -104,7 +105,7 @@ MaxSpeed true true - NDEBUG;_LIB;%(PreprocessorDefinitions);JPH_DEBUG_RENDERER;JPH_USE_F16C;JPH_USE_FMADD + NDEBUG;_LIB;%(PreprocessorDefinitions);JPH_DEBUG_RENDERER;JPH_USE_F16C;JPH_USE_FMADD;_HAS_EXCEPTIONS=0 %(AdditionalIncludeDirectories) MultiThreaded true @@ -114,6 +115,8 @@ stdcpp17 AdvancedVectorExtensions /bigobj %(AdditionalOptions) + false + false Windows diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp index 015c3677f..4c1b02f60 100644 --- a/WickedEngine/wiApplication.cpp +++ b/WickedEngine/wiApplication.cpp @@ -499,18 +499,7 @@ namespace wi infodisplay_str += "[32-bit]"; #endif // _ARM -#ifdef WICKEDENGINE_BUILD_DX12 - if (dynamic_cast(graphicsDevice.get())) - { - infodisplay_str += "[DX12]"; - } -#endif // WICKEDENGINE_BUILD_DX12 -#ifdef WICKEDENGINE_BUILD_VULKAN - if (dynamic_cast(graphicsDevice.get())) - { - infodisplay_str += "[Vulkan]"; - } -#endif // WICKEDENGINE_BUILD_VULKAN + infodisplay_str += graphicsDevice->GetTag(); #ifdef _DEBUG infodisplay_str += "[DEBUG]"; diff --git a/WickedEngine/wiApplication_BindLua.cpp b/WickedEngine/wiApplication_BindLua.cpp index 128bf783b..377440dcf 100644 --- a/WickedEngine/wiApplication_BindLua.cpp +++ b/WickedEngine/wiApplication_BindLua.cpp @@ -58,35 +58,33 @@ namespace wi::lua return 0; } + wi::RenderPath* renderpath = component->GetActivePath(); + //return 3d component if the active one is of that type - RenderPath3D* comp3D = dynamic_cast(component->GetActivePath()); - if (comp3D != nullptr) + if (renderpath->GetScriptBindingID() == wi::RenderPath3D::script_check_identifier) { - Luna::push(L, comp3D); + Luna::push(L, (wi::RenderPath3D*)renderpath); return 1; } //return loading component if the active one is of that type - LoadingScreen* compLoad = dynamic_cast(component->GetActivePath()); - if (compLoad != nullptr) + if (renderpath->GetScriptBindingID() == wi::LoadingScreen::script_check_identifier) { - Luna::push(L, compLoad); + Luna::push(L, (wi::LoadingScreen*)renderpath); return 1; } //return 2d component if the active one is of that type - RenderPath2D* comp2D = dynamic_cast(component->GetActivePath()); - if (comp2D != nullptr) + if (renderpath->GetScriptBindingID() == wi::RenderPath2D::script_check_identifier) { - Luna::push(L, comp2D); + Luna::push(L, (wi::RenderPath2D*)renderpath); return 1; } //return component if the active one is of that type - RenderPath* comp = dynamic_cast(component->GetActivePath()); - if (comp != nullptr) + if (renderpath->GetScriptBindingID() == wi::RenderPath::script_check_identifier) { - Luna::push(L, comp); + Luna::push(L, (wi::RenderPath*)renderpath); return 1; } diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index e67f7be70..b521e8cb6 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -173,6 +173,9 @@ namespace wi::graphics // Performs a batched mapping of sparse resource pages to a tile pool virtual void SparseUpdate(QUEUE_TYPE queue, const SparseUpdateCommand* commands, uint32_t command_count) {}; + // Returns an identifier string for the graphics device subclass + virtual const char* GetTag() const { return ""; } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Command List functions are below: // - These are used to record rendering commands to a CommandList diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index ce4dd51b4..74aa248b5 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -380,6 +380,8 @@ namespace wi::graphics void SparseUpdate(QUEUE_TYPE queue, const SparseUpdateCommand* commands, uint32_t command_count) override; + const char* GetTag() const override { return "[DX12]"; } + ///////////////Thread-sensitive//////////////////////// void WaitCommandList(CommandList cmd, CommandList wait_for) override; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 2c154fdbc..09dc74cd4 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -3794,7 +3794,8 @@ using namespace vulkan_internal; #elif defined(SDL2) if (!SDL_Vulkan_CreateSurface(window, instance, &internal_state->surface)) { - throw sdl2::SDLError("Error creating a vulkan surface"); + wilog_messagebox("Error creating a vulkan surface with SDL_Vulkan_CreateSurface!"); + wi::platform::Exit(); } #else #error WICKEDENGINE VULKAN DEVICE ERROR: PLATFORM NOT SUPPORTED diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index bd4f0316d..d2b9eda27 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -496,6 +496,8 @@ namespace wi::graphics void SparseUpdate(QUEUE_TYPE queue, const SparseUpdateCommand* commands, uint32_t command_count) override; + const char* GetTag() const override { return "[Vulkan]"; } + ///////////////Thread-sensitive//////////////////////// void WaitCommandList(CommandList cmd, CommandList wait_for) override; diff --git a/WickedEngine/wiLoadingScreen.h b/WickedEngine/wiLoadingScreen.h index 20199ed9a..410807b8e 100644 --- a/WickedEngine/wiLoadingScreen.h +++ b/WickedEngine/wiLoadingScreen.h @@ -47,6 +47,10 @@ namespace wi void Start() override; void Compose(wi::graphics::CommandList cmd) const override; + + // This is an identifier of RenderPath subtype that is used for lua binding. + static constexpr const char* script_check_identifier = relative_path(__FILE__); + virtual const char* GetScriptBindingID() const { return script_check_identifier; } }; } diff --git a/WickedEngine/wiLoadingScreen_BindLua.cpp b/WickedEngine/wiLoadingScreen_BindLua.cpp index 639fe562d..de21036c4 100644 --- a/WickedEngine/wiLoadingScreen_BindLua.cpp +++ b/WickedEngine/wiLoadingScreen_BindLua.cpp @@ -47,7 +47,7 @@ namespace wi::lua int LoadingScreen_BindLua::AddLoadModelTask(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "AddLoadModelTask(Scene scene, string fileName, opt Matrix transform): loading screen is invalid!"); @@ -137,7 +137,7 @@ namespace wi::lua } int LoadingScreen_BindLua::AddRenderPathActivationTask(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "AddRenderPathActivationTask(RenderPath path, opt float fadeSeconds = 0, opt int fadeR = 0,fadeG = 0,fadeB = 0, opt FadeType fadetype = FadeType.FadeToColor): loading screen is invalid!"); @@ -224,7 +224,7 @@ namespace wi::lua } int LoadingScreen_BindLua::IsFinished(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading != nullptr) { wi::lua::SSetBool(L, loading->isFinished()); @@ -235,7 +235,7 @@ namespace wi::lua } int LoadingScreen_BindLua::GetProgress(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading != nullptr) { wi::lua::SSetInt(L, loading->getProgress()); @@ -246,7 +246,7 @@ namespace wi::lua } int LoadingScreen_BindLua::SetBackgroundTexture(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "SetBackgroundTexture(Texture tex): loading screen is not valid!"); @@ -269,7 +269,7 @@ namespace wi::lua } int LoadingScreen_BindLua::GetBackgroundTexture(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "GetBackgroundTexture(): loading screen is not valid!"); @@ -280,7 +280,7 @@ namespace wi::lua } int LoadingScreen_BindLua::SetBackgroundMode(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "SetBackgroundMode(int mode): loading screen is not valid!"); @@ -297,7 +297,7 @@ namespace wi::lua } int LoadingScreen_BindLua::GetBackgroundMode(lua_State* L) { - LoadingScreen* loading = dynamic_cast(component); + LoadingScreen* loading = static_cast(component); if (loading == nullptr) { wi::lua::SError(L, "GetBackgroundMode(): loading screen is not valid!"); diff --git a/WickedEngine/wiRenderPath.h b/WickedEngine/wiRenderPath.h index e8c758723..e19a34116 100644 --- a/WickedEngine/wiRenderPath.h +++ b/WickedEngine/wiRenderPath.h @@ -43,5 +43,9 @@ namespace wi inline void setlayerMask(uint32_t value) { layerMask = value; } wi::graphics::ColorSpace colorspace = wi::graphics::ColorSpace::SRGB; + + // This is an identifier of RenderPath subtype that is used for lua binding. + static constexpr const char* script_check_identifier = relative_path(__FILE__); + virtual const char* GetScriptBindingID() const { return script_check_identifier; } }; } diff --git a/WickedEngine/wiRenderPath2D.h b/WickedEngine/wiRenderPath2D.h index 5e9bae7ae..8033e3766 100644 --- a/WickedEngine/wiRenderPath2D.h +++ b/WickedEngine/wiRenderPath2D.h @@ -11,8 +11,7 @@ namespace wi class Sprite; class SpriteFont; - class RenderPath2D : - public RenderPath + class RenderPath2D : public RenderPath { protected: wi::graphics::Texture rtStencilExtracted; @@ -104,6 +103,10 @@ namespace wi float GetHDRScaling() const { return hdr_scaling; } void SetHDRScaling(float value) { hdr_scaling = value; } + + // This is an identifier of RenderPath subtype that is used for lua binding. + static constexpr const char* script_check_identifier = relative_path(__FILE__); + virtual const char* GetScriptBindingID() const { return script_check_identifier; } }; } diff --git a/WickedEngine/wiRenderPath2D_BindLua.cpp b/WickedEngine/wiRenderPath2D_BindLua.cpp index 7ff1f67bc..bad46c2da 100644 --- a/WickedEngine/wiRenderPath2D_BindLua.cpp +++ b/WickedEngine/wiRenderPath2D_BindLua.cpp @@ -49,7 +49,7 @@ namespace wi::lua wi::lua::Sprite_BindLua* sprite = Luna::lightcheck(L, 1); if (sprite != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { if (argc > 1) @@ -94,7 +94,7 @@ namespace wi::lua return 0; } - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { if (argc > 1) @@ -126,7 +126,7 @@ namespace wi::lua wi::lua::SpriteFont_BindLua* font = Luna::lightcheck(L, 1); if (font != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { if (argc > 1) @@ -161,7 +161,7 @@ namespace wi::lua wi::lua::Sprite_BindLua* sprite = Luna::lightcheck(L, 1); if (sprite != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->RemoveSprite(&sprite->sprite); @@ -193,7 +193,7 @@ namespace wi::lua wi::lua::SpriteFont_BindLua* font = Luna::lightcheck(L, 1); if (font != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->RemoveFont(&font->font); @@ -219,7 +219,7 @@ namespace wi::lua wi::lua::SError(L, "ClearSprites() component is empty!"); return 0; } - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->ClearSprites(); @@ -237,7 +237,7 @@ namespace wi::lua wi::lua::SError(L, "ClearFonts() component is empty!"); return 0; } - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->ClearFonts(); @@ -261,7 +261,7 @@ namespace wi::lua wi::lua::Sprite_BindLua* sprite = Luna::lightcheck(L, 1); if (sprite != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { wi::lua::SSetInt(L, ccomp->GetSpriteOrder(&sprite->sprite)); @@ -294,7 +294,7 @@ namespace wi::lua wi::lua::SpriteFont_BindLua* font = Luna::lightcheck(L, 1); if (font != nullptr) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { wi::lua::SSetInt(L, ccomp->GetFontOrder(&font->font)); @@ -325,7 +325,7 @@ namespace wi::lua int argc = wi::lua::SGetArgCount(L); if (argc > 0) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->AddLayer(wi::lua::SGetString(L, 1)); @@ -349,7 +349,7 @@ namespace wi::lua return 0; } - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { std::string ss; @@ -377,7 +377,7 @@ namespace wi::lua int argc = wi::lua::SGetArgCount(L); if (argc > 1) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->SetLayerOrder(wi::lua::SGetString(L, 1), wi::lua::SGetInt(L, 2)); @@ -403,7 +403,7 @@ namespace wi::lua int argc = wi::lua::SGetArgCount(L); if (argc > 1) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { wi::lua::Sprite_BindLua* sprite = Luna::lightcheck(L, 1); @@ -437,7 +437,7 @@ namespace wi::lua int argc = wi::lua::SGetArgCount(L); if (argc > 1) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { wi::lua::SpriteFont_BindLua* font = Luna::lightcheck(L, 1); @@ -469,7 +469,7 @@ namespace wi::lua wi::lua::SError(L, "GetHDRScaling() component is empty!"); return 0; } - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { wi::lua::SSetFloat(L, ccomp->GetHDRScaling()); @@ -491,7 +491,7 @@ namespace wi::lua int argc = wi::lua::SGetArgCount(L); if (argc > 1) { - RenderPath2D* ccomp = dynamic_cast(component); + RenderPath2D* ccomp = static_cast(component); if (ccomp != nullptr) { ccomp->SetHDRScaling(wi::lua::SGetFloat(L, 1)); diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h index f9a69cc07..bb942d4cb 100644 --- a/WickedEngine/wiRenderPath3D.h +++ b/WickedEngine/wiRenderPath3D.h @@ -9,8 +9,7 @@ namespace wi { - class RenderPath3D : - public RenderPath2D + class RenderPath3D : public RenderPath2D { public: enum AO @@ -367,6 +366,10 @@ namespace wi // Creates screenshot of the render result and replaces background (sky) pixels with transparency wi::graphics::Texture CreateScreenshotWithAlphaBackground(); + + // This is an identifier of RenderPath subtype that is used for lua binding. + static constexpr const char* script_check_identifier = relative_path(__FILE__); + virtual const char* GetScriptBindingID() const { return script_check_identifier; } }; } diff --git a/WickedEngine/wiRenderPath3D_PathTracing.h b/WickedEngine/wiRenderPath3D_PathTracing.h index 3b7c763a8..36a130b7f 100644 --- a/WickedEngine/wiRenderPath3D_PathTracing.h +++ b/WickedEngine/wiRenderPath3D_PathTracing.h @@ -5,8 +5,7 @@ namespace wi { - class RenderPath3D_PathTracing : - public RenderPath3D + class RenderPath3D_PathTracing : public RenderPath3D { protected: int sam = -1; @@ -45,6 +44,10 @@ namespace wi void resetProgress() { wi::jobsystem::Wait(denoiserContext); sam = -1; denoiserProgress = 0; volumetriccloudResources.ResetFrame(); } uint8_t instanceInclusionMask_PathTrace = 0xFF; + + // This is an identifier of RenderPath subtype that is used for lua binding. + static constexpr const char* script_check_identifier = relative_path(__FILE__); + virtual const char* GetScriptBindingID() const { return script_check_identifier; } }; }