From 0fc21f2f4e0e647423a516e32abeae6167d439fe Mon Sep 17 00:00:00 2001 From: James Gangur Date: Mon, 4 Mar 2024 18:25:09 +1100 Subject: [PATCH] apparently its 2024? - vk::throwResultException got moved to vk::detail::throwResultException - not sure why, it's convenient so I'm gonna keep using it anyway - update fmtlib to latest release - clean up Logging and make it use vformat to improve compile times and code bloat - added a format_consteval function to Strings.hpp that formats a stack string at compile time - update imgui to a merged version of docking/string_view - FINALLY I could remove most of the string_view wrappers as ImStrv makes them redundant - CStrView is gone, the few remaining functions that take c strings are still re-implemented - merged HoverTooltip and HoverTooltipFixed, pass dir=None for automatic placement - added a "delay" param to handle the new delay feature in imgui - added a "dir" param that specifies where the tooltip should appear - take format str and args as params so that the format string can be lazily evaluated - added a new function "AutoArrange" that automatically arranges widgets over one or more lines - added "if_Table" helper for BeginTable/EndTable - added IMPLUS_WITH macro for use with Scope/Style helpers - automatically generates a variable name so you don't need to come up with one - update miniaudio, update sound file loading to match new api - removed lean mean cpp option parser, which I don't think I ever used - there are much better newer libs to use for when I eventually need option parsing - update catch, update the tests - Approx was depreciated, replaced sq::Approx with new Matchers - added tl::expected to redist, a std::expected implementation for c++20 - added *_config.hpp files for miniaudio, stb_image, and yyjson with defines for each lib - print out basic platform/compiler info when running an Application - rework ResourceCache/Handle - renamed try_acquire to acquire_safe for consistency with other sqee functions - added an error string member to Resource - instead of returning a null handle on failure, an error resource is created - error resources have no value, instead they have an error string - added basic support for c++ class inheritence to WrenPlus - current implementation just dynamic_casts to every type listed until something works - no support for multiple inheritence or multiple levels of inheritence - changed Exception to just inherit from runtime_error instead of storing a std::string - new features for DrawItem - added a check_visibility method, along with visDataType and visSampleOffset fields - this allows animations to disable items completely - added ConstPackedBits as a new ParamType - this is intended for use with "ubershaders", like the one for brawl effects in STS - added ConstTexTransform as a new ParamType - so far only used for identity transforms to reduce shader permutations - added an order field that can be used to explicitly sort items within a pass - Pipeline now checks that push constants with the same name or offset match between stages - cleaned up maths code and made a bunch more things constexpr - finally removed the non-standard anonymous structs - fixed maths::srgb_to_linear - didn't touch Culling or Volumes coz that stuff needs a lot more work - added split_string utility function to Parsing that takes delimiters as template args - added acquire_safe method to ResourceCache that returns an expected - replace nlohmann json with yyjson + custom c++ wrappers - parsing is now much, much faster, and the api is also more convenient - PipelineCache now uses a minified string as a key rather than a json value - added three new core headers, TypeAliases, TypeTraits, and TypeNames - TypeAliases is similar to the old Types.hpp, except: - where possible, things are forward declarations instead of full includes - does not include random non-alias types like std::vector or std::map - I do want phase out Types.hpp, but don't want to bloat this commit even more - TypeTraits.hpp is a centralised place for concepts and variable templates - TypeNames.hpp replaces the old type_to_string functions that were all over the place - uses format_consteval to support arbitary template params - greatly simplified SQEE_ENUM_HELPER - added new generic SQEE_COUNT_ARGS and SQEE_STRINGIFY_ARGS macros to Macros.hpp - with these + cpp20 using enum it's possible to get rid of the EnumTraits struct completely - replaced has_enum_traits_v with a HasEnumHelper concept - fixed building with clang/libc++ - build sqee with -wpedantic now that the anonymous structs are gone - added support to Application for reducing update rate after a period of inactivity - currently very basic and a bit smelly, but solves the immediate issue of my laptop overheating --- .gitmodules | 6 +- CMakeLists.txt | 7 +- include/sqee/app/Application.hpp | 12 + include/sqee/app/GuiWidgets.hpp | 435 +- include/sqee/app/WrenForward.hpp | 36 +- include/sqee/app/WrenPlus.hpp | 98 +- include/sqee/core/EnumHelper.hpp | 115 +- include/sqee/core/Macros.hpp | 8 + include/sqee/core/Strings.hpp | 70 +- include/sqee/core/TypeAliases.hpp | 78 + include/sqee/core/TypeNames.hpp | 72 + include/sqee/core/TypeTraits.hpp | 47 + include/sqee/core/Types.hpp | 60 +- include/sqee/debug/Assert.hpp | 2 +- include/sqee/debug/Logging.hpp | 126 +- include/sqee/maths/Approx.hpp | 104 - include/sqee/maths/Colours.hpp | 64 +- include/sqee/maths/Functions.hpp | 292 +- include/sqee/maths/Matrices.hpp | 455 +- include/sqee/maths/Quaternion.hpp | 315 +- include/sqee/maths/Random.hpp | 163 +- include/sqee/maths/Scalar.hpp | 91 +- include/sqee/maths/Vectors.hpp | 678 +- include/sqee/misc/Files.hpp | 2 +- include/sqee/misc/Json.hpp | 734 +- include/sqee/misc/JsonFwd.hpp | 31 - include/sqee/misc/Parsing.hpp | 39 +- include/sqee/misc/ResourceCache.hpp | 18 +- include/sqee/misc/ResourceHandle.hpp | 59 +- include/sqee/misc/StackString.hpp | 80 +- include/sqee/misc/StackVector.hpp | 78 +- include/sqee/objects/Armature.hpp | 43 +- include/sqee/objects/DrawItem.hpp | 34 +- include/sqee/objects/Mesh.hpp | 9 +- include/sqee/objects/Pipeline.hpp | 12 +- include/sqee/redist/expected.hpp | 2444 + include/sqee/redist/json.hpp | 24611 ---- include/sqee/redist/json_fwd.hpp | 175 - include/sqee/redist/lmccop.hpp | 2802 - include/sqee/redist/miniaudio.hpp | 11082 +- include/sqee/redist/miniaudio_config.hpp | 5 + include/sqee/redist/stb_image.hpp | 22 +- include/sqee/redist/stb_image_config.hpp | 18 + include/sqee/redist/yyjson.hpp | 7911 ++ include/sqee/redist/yyjson_config.hpp | 3 + include/sqee/setup.hpp | 6 +- libs/dearimgui/include/dearimgui/imconfig.h | 44 +- libs/dearimgui/include/dearimgui/imgui.h | 1256 +- .../include/dearimgui/imgui_internal.h | 1214 +- .../include/dearimgui/imstb_textedit.h | 39 +- .../include/dearimgui/imstb_truetype.h | 2 +- libs/dearimgui/source/imgui.cpp | 7389 +- libs/dearimgui/source/imgui_demo.cpp | 1897 +- libs/dearimgui/source/imgui_draw.cpp | 575 +- libs/dearimgui/source/imgui_tables.cpp | 775 +- libs/dearimgui/source/imgui_widgets.cpp | 2156 +- libs/fmt | 2 +- libs/yyjson | 1 + source/sqee/app/Application.cpp | 48 +- source/sqee/app/DebugOverlay.cpp | 40 +- source/sqee/app/GuiSystem.cpp | 32 +- source/sqee/app/GuiWidgets.cpp | 275 +- source/sqee/app/Window.cpp | 30 +- source/sqee/app/WrenPlus.cpp | 26 +- source/sqee/debug/Logging.cpp | 100 +- source/sqee/misc/Json.cpp | 379 +- source/sqee/objects/Armature.cpp | 171 +- source/sqee/objects/DrawItem.cpp | 292 +- source/sqee/objects/Mesh.cpp | 15 +- source/sqee/objects/Pipeline.cpp | 191 +- source/sqee/objects/Sound.cpp | 23 +- source/sqee/objects/Texture.cpp | 159 +- source/sqee/redist/miniaudio.cpp | 100678 +++++++++------ source/sqee/redist/stb_image.cpp | 322 +- source/sqee/redist/yyjson.cpp | 9447 ++ source/sqee/vk/Helpers.cpp | 6 +- source/sqee/vk/VulkanContext.cpp | 2 +- testing/CMakeLists.txt | 2 + testing/Common.hpp | 132 +- testing/catch.hpp | 17970 --- testing/catch_amalgamated.cpp | 11484 ++ testing/catch_amalgamated.hpp | 13748 ++ testing/main.cpp | 2 +- testing/tests/maths/matrices.cpp | 12 +- testing/tests/maths/quaternion.cpp | 51 +- .../tests/maths/{scalars.cpp => scalar.cpp} | 19 +- testing/tests/maths/vectors.cpp | 85 +- testing/tests/misc/json.cpp | 73 + testing/tests/misc/stackstring.cpp | 29 +- testing/tests/misc/stackvector.cpp | 5 +- testing/tests/wrenplus.cpp | 4 +- tests/vkdemo/assets/pipelines/Dice.json | 6 +- tests/vkdemo/src/DemoApp.cpp | 2 +- tests/vkdemo/src/Resources.cpp | 4 +- tests/vkdemo/src/Resources.hpp | 4 +- tests/vkdemo/src/setup.hpp | 6 +- 96 files changed, 126654 insertions(+), 98122 deletions(-) create mode 100644 include/sqee/core/TypeAliases.hpp create mode 100644 include/sqee/core/TypeNames.hpp create mode 100644 include/sqee/core/TypeTraits.hpp delete mode 100644 include/sqee/maths/Approx.hpp delete mode 100644 include/sqee/misc/JsonFwd.hpp create mode 100644 include/sqee/redist/expected.hpp delete mode 100644 include/sqee/redist/json.hpp delete mode 100644 include/sqee/redist/json_fwd.hpp delete mode 100644 include/sqee/redist/lmccop.hpp create mode 100644 include/sqee/redist/miniaudio_config.hpp create mode 100644 include/sqee/redist/stb_image_config.hpp create mode 100644 include/sqee/redist/yyjson.hpp create mode 100644 include/sqee/redist/yyjson_config.hpp create mode 160000 libs/yyjson create mode 100644 source/sqee/redist/yyjson.cpp delete mode 100644 testing/catch.hpp create mode 100644 testing/catch_amalgamated.cpp create mode 100644 testing/catch_amalgamated.hpp rename testing/tests/maths/{scalars.cpp => scalar.cpp} (67%) create mode 100644 testing/tests/misc/json.cpp diff --git a/.gitmodules b/.gitmodules index 5277b8d4..e412a57b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,4 +5,8 @@ [submodule "libs/fmt"] path = libs/fmt url = https://github.com/fmtlib/fmt - branch = 9.0.0 + branch = 10.1.1 +[submodule "libs/yyjson"] + path = libs/yyjson + url = https://github.com/ibireme/yyjson.git + branch = master diff --git a/CMakeLists.txt b/CMakeLists.txt index e01fc3f7..ce379d25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,8 +90,11 @@ endif () if (SQEE_GNU OR SQEE_CLANG) - target_compile_options(sqee PRIVATE -Wall -Wextra) - #target_compile_options(sqee PRIVATE -Wall -Wextra -Wpedantic) + target_compile_options(sqee PRIVATE -Wall -Wextra -Wpedantic) + + if (SQEE_GNU) + target_compile_options(sqee PRIVATE -fconcepts-diagnostics-depth=2) + endif () if (NOT SQEE_STATIC_LIB) target_compile_options(sqee PRIVATE -fvisibility=hidden) diff --git a/include/sqee/app/Application.hpp b/include/sqee/app/Application.hpp index d1612552..edd50a87 100644 --- a/include/sqee/app/Application.hpp +++ b/include/sqee/app/Application.hpp @@ -31,6 +31,9 @@ class SQEE_API Application /// Close the application. void quit() { mReturnCode = 0; } + /// Reset timer for going into inactive mode. + void reset_inactivity() { mElapsedSinceActivity = 0.0; } + protected: //=================================================// /// Called once before the main loop starts. @@ -41,6 +44,15 @@ class SQEE_API Application //--------------------------------------------------------// + /// How long to go without user input before limiting update rate. + double mMaxInactivePeriod = INFINITY; + + /// How often should we update when inactive. + double mMinSleepUpdatePeriod = 0.0; + + /// Set to zero when the user interacts with the application. + double mElapsedSinceActivity = 0.0; + /// Set to a non-negative value to quit. int mReturnCode = -1; diff --git a/include/sqee/app/GuiWidgets.hpp b/include/sqee/app/GuiWidgets.hpp index 792dbbb1..f6aecf5c 100644 --- a/include/sqee/app/GuiWidgets.hpp +++ b/include/sqee/app/GuiWidgets.hpp @@ -6,8 +6,15 @@ #include #include +#include #include -#include + +// defined here instead of in imconfig.h so that we have access to StackString +#define IM_STRV_CLASS_EXTRA \ + ImStrv(const std::string& s) : Begin(s.data()), End(s.data() + s.length()) {} \ + ImStrv(const std::string_view& s) : Begin(s.data()), End(s.data() + s.length()) {} \ + template \ + ImStrv(const sq::StackString& s) : Begin(s.data()), End(s.data() + s.length()) {} #include // IWYU pragma: export #include // IWYU pragma: export @@ -20,7 +27,7 @@ namespace ImGui { // Like DragIntRange2 or DragFloatRange2, but supporting other types. // todo: get this merged into imgui itself -SQEE_API bool DragScalarRange2(const char* label, ImGuiDataType data_type, void* p_current_min, void* p_current_max, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, const char* format_max = NULL, ImGuiSliderFlags flags = 0); +SQEE_API bool DragScalarRange2(ImStrv label, ImGuiDataType data_type, void* p_current_min, void* p_current_max, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, const char* format_max = NULL, ImGuiSliderFlags flags = 0); } // namespace ImGui @@ -30,26 +37,6 @@ namespace ImPlus { //----------------------------------------------------------------------------// -/// Allows ImPlus functions to take either std or c strings. -/// Can't use std::string_view everywhere because it doesn't guarentee null termination. -class CStrView final -{ -public: - constexpr CStrView() = delete; - constexpr CStrView(const CStrView&) = default; - - constexpr CStrView(const char* str) : mCharPtr(str) {} - CStrView(const std::string& str) : mCharPtr(str.c_str()) {} - - constexpr const char* c_str() const { return mCharPtr; } - constexpr operator const char*() const { return mCharPtr; } - -private: - const char* const mCharPtr; -}; - -//----------------------------------------------------------------------------// - constexpr const int FONT_REGULAR = 0; constexpr const int FONT_BOLD = 1; constexpr const int FONT_ITALIC = 2; @@ -60,175 +47,66 @@ constexpr const int MOUSE_RIGHT = 1; enum class DialogResult { None, Confirm, Cancel }; -//============================================================================// - -// Here we have c++ friendly overloads for any functions taking c strings as arguments. -// If a function here is not inline, it is because the ImGui func does string formatting, which we don't want. -// Use something like fmt::literals::_format to format your strings. -// -// Any functions that I don't currently use are commented out until I need them, -// and begin* functions are also not here, as they have special wrappers. -// This stuff was originally generated with a python script. +/// Only perform formatting and constexpr checking if arguments are given. +template +using FormatString = std::conditional_t, fmt::string_view>; +//----------------------------------------------------------------------------// -// ID stack/scopes -inline void PushID(std::string_view id) { ImGui::PushID(id.data(), id.data() + id.length()); } -inline ImGuiID GetID(std::string_view id) { return ImGui::GetID(id.data(), id.data() + id.length()); } +inline void Text(std::string_view text) { ImGui::TextUnformatted(text); } -// Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). -//inline void SetWindowPos(CStrView name, ImVec2 pos, ImGuiCond cond = 0) { ImGui::SetWindowPos(name, pos, cond); } -//inline void SetWindowSize(CStrView name, ImVec2 size, ImGuiCond cond = 0) { ImGui::SetWindowSize(name, size, cond); } -//inline void SetWindowCollapsed(CStrView name, bool collapsed, ImGuiCond cond = 0) { ImGui::SetWindowCollapsed(name, collapsed, cond); } -//inline void SetWindowFocus(CStrView name) { ImGui::SetWindowFocus(name); } +SQEE_API void TextColored(const ImVec4& col, std::string_view text); -// Widgets: Text -inline void Text(std::string_view text) { ImGui::TextUnformatted(text.data(), text.data() + text.length()); } -SQEE_API void TextColored(ImVec4 col, std::string_view text); SQEE_API void TextDisabled(std::string_view text); -SQEE_API void TextWrapped(std::string_view text); -SQEE_API void LabelText(CStrView label, std::string_view text); -SQEE_API void BulletText(std::string_view text); - -// Widgets: Main -inline bool Button(CStrView label, ImVec2 size = {0,0}) { return ImGui::Button(label, size); } -inline bool SmallButton(CStrView label) { return ImGui::SmallButton(label); } -inline bool InvisibleButton(CStrView str_id, ImVec2 size) { return ImGui::InvisibleButton(str_id, size); } -inline bool ArrowButton(CStrView str_id, ImGuiDir dir) { return ImGui::ArrowButton(str_id, dir); } -inline bool Checkbox(CStrView label, bool* v) { return ImGui::Checkbox(label, v); } -//inline bool CheckboxFlags(CStrView label, unsigned int* flags, unsigned int flags_value) { return ImGui::CheckboxFlags(label, flags, flags_value); } -inline bool RadioButton(CStrView label, bool active) { return ImGui::RadioButton(label, active); } -//inline bool RadioButton(CStrView label, int* v, int v_button) { return ImGui::RadioButton(label, v, v_button); } -inline void ProgressBar(float fraction, ImVec2 size_arg = {-1,0}, CStrView overlay = nullptr) { ImGui::ProgressBar(fraction, size_arg, overlay); } - -// Widgets: Combo Box -//inline bool Combo(CStrView label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1) { return ImGui::Combo(label, current_item, items, items_count, popup_max_height_in_items); } -//inline bool Combo(CStrView label, int* current_item, CStrView items_separated_by_zeros, int popup_max_height_in_items = -1) { return ImGui::Combo(label, current_item, items_separated_by_zeros, popup_max_height_in_items); } -//inline bool Combo(CStrView label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1) { return ImGui::Combo(label, current_item, items_getter, data, items_count, popup_max_height_in_items); } - -// Widgets: Color Editor/Picker -//inline bool ColorEdit3(CStrView label, float col[3], ImGuiColorEditFlags flags = 0) { return ImGui::ColorEdit3(label, col, flags); } -//inline bool ColorEdit4(CStrView label, float col[4], ImGuiColorEditFlags flags = 0) { return ImGui::ColorEdit4(label, col, flags); } -//inline bool ColorPicker3(CStrView label, float col[3], ImGuiColorEditFlags flags = 0) { return ImGui::ColorPicker3(label, col, flags); } -//inline bool ColorPicker4(CStrView label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = nullptr) { return ImGui::ColorPicker4(label, col, flags, ref_col); } -//inline bool ColorButton(CStrView desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = {0,0}) { return ImGui::ColorButton(desc_id, col, flags, size); } - -// Widgets: Trees -inline bool TreeNode(CStrView label) { return ImGui::TreeNode(label); } -//SQEE_API bool TreeNode(CStrView str_id, CStrView text); -//SQEE_API bool TreeNode(const void* ptr_id, CStrView text); -//inline bool TreeNodeEx(CStrView label, ImGuiTreeNodeFlags flags = 0) { return ImGui::TreeNodeEx(label, flags); } -//SQEE_API bool TreeNodeEx(CStrView str_id, ImGuiTreeNodeFlags flags, CStrView text); -//SQEE_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, CStrView text); -//inline void TreePush(CStrView str_id) { ImGui::TreePush(str_id); } -inline bool CollapsingHeader(CStrView label, ImGuiTreeNodeFlags flags = 0) { return ImGui::CollapsingHeader(label, flags); } -//inline bool CollapsingHeader(CStrView label, bool* p_open, ImGuiTreeNodeFlags flags = 0) { return ImGui::CollapsingHeader(label, p_open, flags); } - -// Widgets: Selectables -inline bool Selectable(CStrView label, bool selected = false, ImGuiSelectableFlags flags = 0, ImVec2 size = {0,0}) { return ImGui::Selectable(label, selected, flags, size); } -//inline bool Selectable(CStrView label, bool* p_selected, ImGuiSelectableFlags flags = 0, ImVec2 size = {0,0}) { return ImGui::Selectable(label, p_selected, flags, size); } - -// Widgets: List Boxes -//inline bool ListBox(CStrView label, int* current_item, const char* const items[], int items_count, int height_in_items = -1) { return ImGui::ListBox(label, current_item, items, items_count, height_in_items); } -//inline bool ListBox(CStrView label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1) { return ImGui::ListBox(label, current_item, items_getter, data, items_count, height_in_items); } - -// Widgets: Data Plotting -//inline void PlotLines(CStrView label, const float* values, int values_count, int values_offset = 0, CStrView overlay_text = nullptr, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = {0,0}, int stride = sizeof(float)) { ImGui::PlotLines(label, values, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, stride); } -//inline void PlotLines(CStrView label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, CStrView overlay_text = nullptr, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = {0,0}) { ImGui::PlotLines(label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } -//inline void PlotHistogram(CStrView label, const float* values, int values_count, int values_offset = 0, CStrView overlay_text = nullptr, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = {0,0}, int stride = sizeof(float)) { ImGui::PlotHistogram(label, values, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, stride); } -//inline void PlotHistogram(CStrView label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, CStrView overlay_text = nullptr, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = {0,0}) { ImGui::PlotHistogram(label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } - -// Widgets: Menus -inline bool MenuItem(CStrView label, CStrView shortcut = nullptr, bool selected = false, bool enabled = true) { return ImGui::MenuItem(label, shortcut, selected, enabled); } -//inline bool MenuItem(CStrView label, CStrView shortcut, bool* p_selected, bool enabled = true) { return ImGui::MenuItem(label, shortcut, p_selected, enabled); } - -// Tooltips -SQEE_API void SetTooltip(std::string_view text); - -// Popups, Modals -inline void OpenPopup(CStrView str_id) { ImGui::OpenPopup(str_id); } -//inline bool OpenPopupOnItemClick(CStrView str_id = nullptr, ImGuiMouseButton mouse_button = 1) { return ImGui::OpenPopupOnItemClick(str_id, 1); } -inline bool IsPopupOpen(CStrView str_id) { return ImGui::IsPopupOpen(str_id); } - -// Columns -inline void Columns(int count = 1, CStrView id = nullptr, bool border = true) { ImGui::Columns(count, id, border); } - -// Tab Bars, Tabs -inline void SetTabItemClosed(CStrView tab_or_docked_window_label) { ImGui::SetTabItemClosed(tab_or_docked_window_label); } -// Logging/Capture -//inline void LogToFile(int auto_open_depth = -1, CStrView filename = nullptr) { ImGui::LogToFile(auto_open_depth, filename); } -//SQEE_API void LogText(CStrView text); - -// Drag and Drop -inline bool SetDragDropPayload(CStrView type, const void* data, size_t sz, ImGuiCond cond = 0) { return ImGui::SetDragDropPayload(type, data, sz, cond); } -inline const ImGuiPayload* AcceptDragDropPayload(CStrView type, ImGuiDragDropFlags flags = 0) { return ImGui::AcceptDragDropPayload(type, flags); } +SQEE_API void TextWrapped(std::string_view text); -// Miscellaneous Utilities -//inline CStrView GetStyleColorName(ImGuiCol idx) { return ImGui::GetStyleColorName(idx); } -inline ImVec2 CalcTextSize(std::string_view text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) { return ImGui::CalcTextSize(text.data(), text.data() + text.length(), hide_text_after_double_hash, wrap_width); } +SQEE_API void LabelText(ImStrv label, std::string_view text); -// Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) -//inline CStrView GetClipboardText() { return ImGui::GetClipboardText(); } -//inline void SetClipboardText(CStrView text) { ImGui::SetClipboardText(text); } +SQEE_API void BulletText(std::string_view text); -// Settings/.Ini Utilities -//inline void LoadIniSettingsFromDisk(CStrView ini_filename) { ImGui::LoadIniSettingsFromDisk(ini_filename); } -//inline void LoadIniSettingsFromMemory(CStrView ini_data, size_t ini_size = 0) { ImGui::LoadIniSettingsFromMemory(ini_data, ini_size); } -//inline void SaveIniSettingsToDisk(CStrView ini_filename) { ImGui::SaveIniSettingsToDisk(ini_filename); } -//inline CStrView SaveIniSettingsToMemory(size_t* out_ini_size = nullptr) { return ImGui::SaveIniSettingsToMemory(out_ini_size); } +SQEE_API void SetTooltip(std::string_view text); //----------------------------------------------------------------------------// -inline float FromScreenRight(float offset) -{ - return ImGui::GetIO().DisplaySize.x - offset; -} - -inline float FromScreenBottom(float offset) -{ - return ImGui::GetIO().DisplaySize.y - offset; -} - -/// Display a tooltip if the mouse is over the last item. -inline void HoverTooltip(std::string_view text) -{ - if (!ImGui::IsItemHovered()) return; - ImPlus::SetTooltip(text); -} +/// DisplaySize.x - offset +SQEE_API float FromScreenRight(float offset); -/// Display a tooltip at a fixed location, below the item. -inline void HoverTooltipFixed(std::string_view text) -{ - if (!ImGui::IsItemHovered()) return; - ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos()); - ImPlus::SetTooltip(text); -} +/// DisplaySize.y - offset +SQEE_API float FromScreenBottom(float offset); /// Version of PushFont taking the index of a font. -inline void PushFont(int fontIndex) -{ - ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[fontIndex]); -} +SQEE_API void PushFont(int index); -//----------------------------------------------------------------------------// +/// Arrange a set of same-width widgets over one or more lines. Call between widgets, like SameLine(). +SQEE_API void AutoArrange(float minItemWidth); /// InputText operating on an auto-resizing std::string. -SQEE_API bool InputString(CStrView label, std::string& str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* userData = nullptr); +SQEE_API bool InputString(ImStrv label, std::string& str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* userData = nullptr); /// InputTextMultiline operating on an auto-resizing std::string. -SQEE_API bool InputStringMultiline(CStrView label, std::string& str, ImVec2 size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* userData = nullptr); +SQEE_API bool InputStringMultiline(ImStrv label, std::string& str, ImVec2 size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* userData = nullptr); /// ColorEdit3 that behaves like other ImPlus input widgets. -SQEE_API bool InputColour(CStrView label, sq::Vec3F& colour, ImGuiColorEditFlags flags = 0); +SQEE_API bool InputColour(ImStrv label, sq::Vec3F& colour, ImGuiColorEditFlags flags = 0); /// ColorEdit4 that behaves like other ImPlus input widgets. -SQEE_API bool InputColour(CStrView label, sq::Vec4F& colour, ImGuiColorEditFlags flags = 0); +SQEE_API bool InputColour(ImStrv label, sq::Vec4F& colour, ImGuiColorEditFlags flags = 0); /// Show a dialog prompting the user for confirmation. -SQEE_API DialogResult DialogConfirmation(CStrView title, CStrView message = nullptr); +SQEE_API DialogResult DialogConfirmation(ImStrv title, std::string_view message = {}); -/// Show a little button with a cross on it. TODO: actually show the label -SQEE_API bool CloseButton(CStrView label); +//----------------------------------------------------------------------------// + +SQEE_API void HoverTooltipV(bool delay, ImGuiDir dir, fmt::string_view fstr, fmt::format_args args); + +/// Display a formatted tooltip if the mouse is over the last item. +template +inline void HoverTooltip(bool delay, ImGuiDir dir, FormatString fstr, Args&&... args) { HoverTooltipV(delay, dir, fstr, fmt::make_format_args(args...)); } + +/// Display a formatted tooltip if the mouse is over the last item. +template +inline void HoverTooltip(FormatString fstr, Args&&... args) { HoverTooltipV(true, ImGuiDir_None, fstr, fmt::make_format_args(args...)); } //----------------------------------------------------------------------------// @@ -249,8 +127,6 @@ constexpr ImGuiDataType_ get_data_type() if constexpr (std::is_same_v) return ImGuiDataType_Double; } -SQEE_API bool is_temp_input_open(); - struct ScopeBase { ScopeBase() = default; @@ -260,15 +136,14 @@ struct ScopeBase ScopeBase& operator=(ScopeBase&&) = delete; }; +SQEE_API bool is_temp_input_open(); + } // namespace detail //----------------------------------------------------------------------------// -// note: all of the Input* widgets currently suffer from https://github.com/ocornut/imgui/issues/4714 -// not worrying about it for now, will hopefully be fixed soon - template -inline bool InputValue(CStrView label, Type& ref, decltype(Type()) step, const char* format = nullptr) +inline bool InputValue(ImStrv label, Type& ref, decltype(Type()) step, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); Type temp = ref; @@ -279,7 +154,7 @@ inline bool InputValue(CStrView label, Type& ref, decltype(Type()) step, const c } template -inline bool DragValue(CStrView label, Type& ref, float speed, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) +inline bool DragValue(ImStrv label, Type& ref, float speed, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); Type temp = ref; @@ -290,7 +165,7 @@ inline bool DragValue(CStrView label, Type& ref, float speed, decltype(Type()) m } template -inline bool SliderValue(CStrView label, Type& ref, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) +inline bool SliderValue(ImStrv label, Type& ref, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); Type temp = ref; @@ -301,35 +176,35 @@ inline bool SliderValue(CStrView label, Type& ref, decltype(Type()) min, decltyp } template -inline bool DragValueRange2(CStrView label, Type& refMin, Type& refMax, float speed, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) +inline bool DragValueRange2(ImStrv label, Type& refMin, Type& refMax, float speed, decltype(Type()) min, decltype(Type()) max, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); - Type temp[2] = { refMin, refMax }; - bool changed = ImGui::DragScalarRange2(label, dataType, &temp[0], &temp[1], speed, &min, &max, format, format, ImGuiSliderFlags_AlwaysClamp); + Type tempMin = refMin, tempMax = refMax; + bool changed = ImGui::DragScalarRange2(label, dataType, &tempMin, &tempMax, speed, &min, &max, format, format, ImGuiSliderFlags_AlwaysClamp); if (changed && detail::is_temp_input_open()) changed = ImGui::IsItemDeactivatedAfterEdit(); - if (changed) { refMin = temp[0]; refMax = temp[1]; } + if (changed) { refMin = tempMin; refMax = tempMax; } return changed; } //----------------------------------------------------------------------------// template -inline bool InputVector(CStrView label, sq::maths::Vector& ref, decltype(Type()) step, const char* format = nullptr) +inline bool InputVector(ImStrv label, sq::maths::Vector& ref, decltype(Type()) step, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); auto temp = ref; - bool changed = ImGui::InputScalarN(label, dataType, temp.data, Size, step > 0 ? &step : nullptr, nullptr, format); + bool changed = ImGui::InputScalarN(label, dataType, temp.data(), Size, step > 0 ? &step : nullptr, nullptr, format); if (changed) changed = ImGui::IsItemDeactivatedAfterEdit(); if (changed) ref = temp; return changed; } template -inline bool DragVector(CStrView label, sq::maths::Vector& ref, float speed, const char* format = nullptr) +inline bool DragVector(ImStrv label, sq::maths::Vector& ref, float speed, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); auto temp = ref; - bool changed = ImGui::DragScalarN(label, dataType, temp.data, Size, speed, nullptr, nullptr, format); + bool changed = ImGui::DragScalarN(label, dataType, temp.data(), Size, speed, nullptr, nullptr, format); if (changed && detail::is_temp_input_open()) changed = ImGui::IsItemDeactivatedAfterEdit(); if (changed) ref = temp; return changed; @@ -337,12 +212,12 @@ inline bool DragVector(CStrView label, sq::maths::Vector& ref, float // todo: make widget fancy, allow to switch input mode to euler XYZ template -inline bool InputQuaternion(CStrView label, sq::maths::Quaternion& ref, decltype(Type()) step, const char* format = nullptr) +inline bool InputQuaternion(ImStrv label, sq::maths::Quaternion& ref, decltype(Type()) step, const char* format = nullptr) { constexpr auto dataType = detail::get_data_type(); auto temp = ref; - ImGui::InputScalarN(label, dataType, temp.data, 4, step > 0 ? &step : nullptr, nullptr, format); - const bool changed = ImGui::IsItemDeactivatedAfterEdit(); + bool changed = ImGui::InputScalarN(label, dataType, temp.data(), 4, step > 0 ? &step : nullptr, nullptr, format); + if (changed) changed = ImGui::IsItemDeactivatedAfterEdit(); if (changed) ref = temp; return changed; } @@ -351,7 +226,7 @@ inline bool InputQuaternion(CStrView label, sq::maths::Quaternion& ref, de /// C++ style API for combo boxes. If none is given, it can be selected to set the index to -1. template -inline bool ComboIndex(CStrView label, const Container& container, Index& ref, CStrView none = nullptr, ImGuiComboFlags flags = 0) +inline bool ComboIndex(ImStrv label, const Container& container, Index& ref, ImStrv none = {}, ImGuiComboFlags flags = 0) { // todo: unsigned types would be fine if none is not given static_assert(std::is_signed_v, "index type must be signed"); @@ -360,10 +235,9 @@ inline bool ComboIndex(CStrView label, const Container& container, Index& ref, C // return true if new selection is different to old selection bool changed = false; - const char* const currentItem = ref == -1 ? none.c_str() : container[ref].c_str(); - if (ImGui::BeginCombo(label, currentItem, flags)) + if (ImGui::BeginCombo(label, ref == -1 ? none : ImStrv(container[ref]), flags)) { - if (none != nullptr) + if (none) { const bool selected = (ref == -1); if (ImGui::Selectable(none, selected) && !selected) @@ -373,7 +247,7 @@ inline bool ComboIndex(CStrView label, const Container& container, Index& ref, C for (Index index = 0; index < container.size(); ++index) { const bool selected = (ref == index); - if (ImGui::Selectable(container[index].c_str(), selected) && !selected) + if (ImGui::Selectable(container[index], selected) && !selected) ref = index, changed = true; } @@ -385,24 +259,24 @@ inline bool ComboIndex(CStrView label, const Container& container, Index& ref, C /// C++ style API for combo boxes. If none is given, it can be selected to clear the value. template -inline bool ComboString(CStrView label, const Container& container, String& ref, CStrView none = nullptr, ImGuiComboFlags flags = 0) +inline bool ComboString(ImStrv label, const Container& container, String& ref, ImStrv none = {}, ImGuiComboFlags flags = 0) { // return true if new selection is different to old selection bool changed = false; - if (ImGui::BeginCombo(label, ref.c_str(), flags)) + if (ImGui::BeginCombo(label, ref, flags)) { - if (none != nullptr) + if (none) { const bool selected = ref.empty(); if (ImGui::Selectable(none, selected) && !selected) - ref.clear(), changed = true; + ref = {}, changed = true; } for (const auto& entry : container) { const bool selected = (ref == entry); - if (ImGui::Selectable(entry.c_str(), selected) && !selected) + if (ImGui::Selectable(entry, selected) && !selected) ref = entry, changed = true; } @@ -413,20 +287,19 @@ inline bool ComboString(CStrView label, const Container& container, String& ref, } /// Combo box for an enum value. For use with the SQEE_ENUM_HELPER macro. -template -inline bool ComboEnum(CStrView label, EnumType& ref, ImGuiComboFlags flags = 0) +template +inline bool ComboEnum(ImStrv label, Enum& ref, ImGuiComboFlags flags = 0) { // return true if new selection is different to old selection bool changed = false; if (ImGui::BeginCombo(label, sq::enum_to_string(ref), flags)) { - for (EnumType entry : sq::enum_items_v) + for (const Enum value : sq::enum_values_v) { - const bool selected = (ref == entry); - - if (ImGui::Selectable(sq::enum_to_string(entry), selected) && !selected) - ref = entry, changed = true; + const bool selected = (ref == value); + if (ImGui::Selectable(sq::enum_to_string(value), selected) && !selected) + ref = value, changed = true; } ImGui::EndCombo(); @@ -439,170 +312,192 @@ inline bool ComboEnum(CStrView label, EnumType& ref, ImGuiComboFlags flags = 0) /// Assign ref to value when pressed. template -inline bool RadioButton(CStrView label, Type& ref, Type value) +inline bool RadioButton(ImStrv label, Type& ref, Type value) { const bool pressed = ImGui::RadioButton(label, ref == value); - if (pressed == true) ref = value; - + if (pressed) ref = value; return pressed; } //----------------------------------------------------------------------------// /// Wrapper for Begin, End. -struct ScopeWindow final : detail::ScopeBase +struct Scope_Window final : detail::ScopeBase { bool show; - ScopeWindow(CStrView name, ImGuiWindowFlags flags) : show(ImGui::Begin(name, nullptr, flags)) {} - ~ScopeWindow() { ImGui::End(); } + Scope_Window(ImStrv name, ImGuiWindowFlags flags) : show(ImGui::Begin(name, nullptr, flags)) {} + ~Scope_Window() { ImGui::End(); } }; -/// Wrapper for Begin, End with a close button. -struct ScopeWindowClosable final : detail::ScopeBase +/// Variant of Scope_Window with a close button. +struct Scope_WindowClosable final : detail::ScopeBase { bool open = true; bool show; - ScopeWindowClosable(CStrView name, ImGuiWindowFlags flags) : show(ImGui::Begin(name, &open, flags)) {} - ~ScopeWindowClosable() { ImGui::End(); } + Scope_WindowClosable(ImStrv name, ImGuiWindowFlags flags) : show(ImGui::Begin(name, &open, flags)) {} + ~Scope_WindowClosable() { ImGui::End(); } }; //----------------------------------------------------------------------------// /// Wrapper for BeginChild, EndChild. -template inline -void if_Child(CStrView id, ImGuiWindowFlags flags, Body body) +template +inline void if_Child(ImStrv id, ImGuiWindowFlags flags, Body body) { if (ImGui::BeginChild(id, ImVec2(), false, flags)) body(); ImGui::EndChild(); } /// Wrapper for BeginPopup, EndPopup. -template inline -void if_Popup(CStrView id, ImGuiWindowFlags flags, Body body) +template +inline void if_Popup(ImStrv id, ImGuiWindowFlags flags, Body body) { if (ImGui::BeginPopup(id, flags)) { body(); ImGui::EndPopup(); } } /// Wrapper for BeginPopupContextItem, EndPopup. -template inline -void if_PopupContextItem(CStrView id, ImGuiPopupFlags flags, Body body) +template +inline void if_PopupContextItem(ImStrv id, ImGuiPopupFlags flags, Body body) { if (ImGui::BeginPopupContextItem(id, flags)) { body(); ImGui::EndPopup(); } } /// Wrapper for BeginTabBar, EndTabBar. -template inline -void if_TabBar(CStrView id, ImGuiTabBarFlags flags, Body body) +template +inline void if_TabBar(ImStrv id, ImGuiTabBarFlags flags, Body body) { if (ImGui::BeginTabBar(id, flags)) { body(); ImGui::EndTabBar(); } } /// Wrapper for BeginTabItem, EndTabItem. -template inline -void if_TabItem(CStrView label, ImGuiTabItemFlags flags, Body body) +template +inline void if_TabItem(ImStrv label, ImGuiTabItemFlags flags, Body body) { if (ImGui::BeginTabItem(label, nullptr, flags)) { body(); ImGui::EndTabItem(); } } +/// Variant of if_TabItem that puts contents in a child window. +template +inline void if_TabItemChild(ImStrv label, ImGuiTabItemFlags flags, Body body) +{ + if (ImGui::BeginTabItem(label, nullptr, flags)) + { + if (ImGui::BeginChild("", ImVec2(), false, 0)) body(); + ImGui::EndChild(); + ImGui::EndTabItem(); + } +} + /// Wrapper for BeginMenuBar, EndMenuBar. -template inline -void if_MenuBar(Body body) +template +inline void if_MenuBar(Body body) { if (ImGui::BeginMenuBar()) { body(); ImGui::EndMenuBar(); } } /// Wrapper for BeginMenu, EndMenu. -template inline -void if_Menu(CStrView label, bool enabled, Body body) +template +inline void if_Menu(ImStrv label, bool enabled, Body body) { if (ImGui::BeginMenu(label, enabled)) { body(); ImGui::EndMenu(); } } -/// Wrapper for TreeNode, TreePop. -template inline -void if_TreeNode(CStrView label, Body body) +/// Wrapper for TreeNodeEx, TreePop. +template +inline void if_TreeNode(ImStrv label, ImGuiTreeNodeFlags flags, Body body) { - if (ImGui::TreeNode(label)) { body(); ImGui::TreePop(); } + if (ImGui::TreeNodeEx(label, flags)) { body(); ImGui::TreePop(); } } -//----------------------------------------------------------------------------// - -/// Variant of TabItem that puts contents in a child window. -template inline -void if_TabItemChild(CStrView label, ImGuiTabItemFlags flags, Body body) +/// Wrapper for BeginTable, EndTable. +template +inline void if_Table(ImStrv id, int columns, ImGuiTableFlags flags, ImVec2 outerSize, float innerWidth, Body body) { - if (ImGui::BeginTabItem(label, nullptr, flags)) - { - if (ImGui::BeginChild("", {0,0}, false, 0)) body(); - ImGui::EndChild(); - ImGui::EndTabItem(); - } + if (ImGui::BeginTable(id, columns, flags, outerSize, innerWidth)) { body(); ImGui::EndTable(); } } //----------------------------------------------------------------------------// /// Wrapper for PushID, PopID. -struct ScopeID final : detail::ScopeBase +struct Scope_ID final : detail::ScopeBase { - ScopeID(const char* cstr_id) { ImGui::PushID(cstr_id); } - ScopeID(std::string_view sv_id) { ImGui::PushID(sv_id.data(), sv_id.data() + sv_id.length()); } - ScopeID(const void* ptr_id) { ImGui::PushID(ptr_id); } - ScopeID(int int_id) { ImGui::PushID(int_id); } - ~ScopeID() { ImGui::PopID(); } + Scope_ID(const char* str_id) { ImGui::PushID(str_id); } + Scope_ID(ImStrv str_id) { ImGui::PushID(str_id); } + Scope_ID(const void* ptr_id) { ImGui::PushID(ptr_id); } + Scope_ID(int int_id) { ImGui::PushID(int_id); } + ~Scope_ID() { ImGui::PopID(); } }; /// Wrapper for PushItemWidth, PopItemWidth. -struct ScopeItemWidth final : detail::ScopeBase +struct Scope_ItemWidth final : detail::ScopeBase { - ScopeItemWidth(float width) { ImGui::PushItemWidth(width); } - ~ScopeItemWidth() { ImGui::PopItemWidth(); } + Scope_ItemWidth(float width) { ImGui::PushItemWidth(width); } + ~Scope_ItemWidth() { ImGui::PopItemWidth(); } }; /// Wrapper for Indent, Unindent. -struct ScopeIndent final : detail::ScopeBase +struct Scope_Indent final : detail::ScopeBase { - ScopeIndent(float width = 0.f) : width(width) { ImGui::Indent(width); } - ~ScopeIndent() { ImGui::Unindent(width); } - const float width; + float width; + Scope_Indent(float width) : width(width) { ImGui::Indent(width); } + ~Scope_Indent() { ImGui::Unindent(width); } }; /// Wrapper for Unindent, Indent. -struct ScopeUnindent final : detail::ScopeBase +struct Scope_Unindent final : detail::ScopeBase { - ScopeUnindent(float width = 0.f) : width(width) { ImGui::Unindent(width); } - ~ScopeUnindent() { ImGui::Indent(width); } - const float width; + float width; + Scope_Unindent(float width) : width(width) { ImGui::Unindent(width); } + ~Scope_Unindent() { ImGui::Indent(width); } }; /// Wrapper for PushFont, PopFont. -struct ScopeFont final : detail::ScopeBase +struct Scope_Font final : detail::ScopeBase { - ScopeFont(ImFont* font) { ImGui::PushFont(font); } - ScopeFont(int fontIndex) { ImPlus::PushFont(fontIndex); } - ~ScopeFont() { ImGui::PopFont(); } + Scope_Font(int index) { ImPlus::PushFont(index); } + ~Scope_Font() { ImGui::PopFont(); } }; +/// Variant of Scope_Font that also temporarily scales the font. +struct Scope_FontScale final : detail::ScopeBase +{ + ImFont* font; float scale; + Scope_FontScale(int index, float scale) : font(ImGui::GetIO().Fonts->Fonts[index]), scale(font->Scale) { font->Scale = scale; ImGui::PushFont(font); } + ~Scope_FontScale() { font->Scale = scale; ImGui::PopFont(); } +}; + +//----------------------------------------------------------------------------// + /// Wrapper for PushStyleVar(float), PopStyleVar. template -struct ScopeStyleFloat final : detail::ScopeBase +struct Scope_StyleFloat final : detail::ScopeBase { - ScopeStyleFloat(float value) { ImGui::PushStyleVar(StyleVar, value); } - ~ScopeStyleFloat() { ImGui::PopStyleVar(); } + Scope_StyleFloat(float value) { ImGui::PushStyleVar(StyleVar, value); } + ~Scope_StyleFloat() { ImGui::PopStyleVar(); } }; +using Style_IndentSpacing = Scope_StyleFloat; + /// Wrapper for PushStyleVar(ImVec2), PopStyleVar. template -struct ScopeStyleVec final : detail::ScopeBase +struct Scope_StyleVec final : detail::ScopeBase { - ScopeStyleVec(float x, float y) { ImGui::PushStyleVar(StyleVar, {x, y}); } - ~ScopeStyleVec() { ImGui::PopStyleVar(); } + Scope_StyleVec(float x, float y) { ImGui::PushStyleVar(StyleVar, {x, y}); } + ~Scope_StyleVec() { ImGui::PopStyleVar(); } }; +using Style_FramePadding = Scope_StyleVec; +using Style_ItemSpacing = Scope_StyleVec; +using Style_CellPadding = Scope_StyleVec; +using Style_ButtonTextAlign = Scope_StyleVec; +using Style_SelectableTextAlign = Scope_StyleVec; + //----------------------------------------------------------------------------// -using Style_FramePadding = ScopeStyleVec; -using Style_ItemSpacing = ScopeStyleVec; -using Style_ButtonTextAlign = ScopeStyleVec; -using Style_SelectableTextAlign = ScopeStyleVec; +#define IMPLUS_WITH_CONCAT_INNER(a, b) a##b +#define IMPLUS_WITH_CONCAT(a, b) IMPLUS_WITH_CONCAT_INNER(a, b) + +/// Declare a variable with a generated name of the given ImPlus class. +#define IMPLUS_WITH(Class) const ImPlus::Class IMPLUS_WITH_CONCAT(implus_with_, __LINE__) //============================================================================// diff --git a/include/sqee/app/WrenForward.hpp b/include/sqee/app/WrenForward.hpp index 6c556f3d..16cadf7b 100644 --- a/include/sqee/app/WrenForward.hpp +++ b/include/sqee/app/WrenForward.hpp @@ -49,9 +49,9 @@ class WrenPlusVM; #define WRENPLUS_TRAITS_HEADER(Type) \ template<> struct wren::Traits : std::true_type \ { \ - static const char* const module; \ - static const char* const className; \ - static const size_t index; \ + static const char* const module; \ + static const char* const className; \ + static const size_t index; \ }; #define WRENPLUS_TRAITS_DEFINITION(Type, Module, ClassName) \ @@ -61,6 +61,36 @@ const size_t wren::Traits::index = wren::detail::generate_type_index(); //============================================================================// +#define WRENPLUS_BASE_CLASS_HEADER(BaseType) \ +template <> \ +struct wren::SlotHelper \ +{ \ + static BaseType* get(WrenVM* vm, int slot, WrenType slotType); \ + static void set(WrenVM* vm, int slot, BaseType* ptr); \ +}; + +#define WRENPLUS_BASE_CLASS_DEFINITION(BaseType, ...) \ +BaseType* wren::SlotHelper::get(WrenVM* vm, int slot, WrenType slotType) \ +{ \ + if (slotType == WREN_TYPE_FOREIGN) \ + { \ + const auto& data = *static_cast(wrenGetSlotForeign(vm, slot)); \ + return detail::base_class_slot_helper_get_inner(data); \ + } \ + if (slotType == WREN_TYPE_NULL) \ + return nullptr; \ + throw Exception("slot does not hold Object*"); \ +} \ +void wren::SlotHelper::set(WrenVM* vm, int slot, BaseType* ptr) \ +{ \ + if (ptr != nullptr) \ + detail::base_class_slot_helper_set_inner(vm, slot, ptr); \ + else \ + wrenSetSlotNull(vm, slot); \ +} + +//============================================================================// + #define WRENPLUS_ADD_METHOD(Pvm, Class, Method, Signature) \ Pvm.register_method<&Class::Method, Class>(Signature) diff --git a/include/sqee/app/WrenPlus.hpp b/include/sqee/app/WrenPlus.hpp index 215daf78..da469bce 100644 --- a/include/sqee/app/WrenPlus.hpp +++ b/include/sqee/app/WrenPlus.hpp @@ -30,21 +30,14 @@ namespace wren { //============================================================================// /// General exception to throw from functions bound to wren. -struct Exception final : public std::exception +struct Exception final : public std::runtime_error { - Exception(std::string str) : message(std::move(str)) {} + Exception(const char* cstr) : std::runtime_error(cstr) {} + Exception(const std::string& str) : std::runtime_error(str) {} template - // todo: temporary workaround for an internal compiler error - #ifdef SQEE_MSVC - Exception(std::string_view str, Args&&... args) : message(fmt::format(fmt::runtime(str), std::forward(args)...)) {} - #else - Exception(fmt::format_string str, Args&&... args) : message(fmt::format(str, std::forward(args)...)) {} - #endif - - const char* what() const noexcept override { return message.c_str(); } - - std::string message; + Exception(fmt::format_string fstr, Args&&... args) + : std::runtime_error(fmt::vformat(fstr, fmt::make_format_args(args...))) {} }; /// Minimal either type used for returning errors as strings. @@ -238,7 +231,7 @@ class WRENPLUS_API WrenPlusVM mErrorString.clear(); if (wrenCall(mWrenVM, method) != WREN_RESULT_SUCCESS) - throw Exception(std::move(mErrorString)); + throw Exception(mErrorString); return get_slot(mWrenVM, 0); } @@ -251,14 +244,14 @@ class WRENPLUS_API WrenPlusVM mErrorString.clear(); if (wrenCall(mWrenVM, method) != WREN_RESULT_SUCCESS) - throw Exception(std::move(mErrorString)); + throw Exception(mErrorString); } //--------------------------------------------------------// /// Call a wren method with the given arguments and return the result or any errors. template - SafeResult safe_call[[nodiscard]](WrenHandle* method, Receiver receiver, const Args&... args) noexcept + [[nodiscard]] SafeResult safe_call(WrenHandle* method, Receiver receiver, const Args&... args) noexcept { set_call_slots(mWrenVM, receiver, args...); mErrorString.clear(); @@ -276,7 +269,7 @@ class WRENPLUS_API WrenPlusVM /// Call a wren method with the given arguments and return any errors. template - std::string safe_call_void[[nodiscard]](WrenHandle* method, Receiver receiver, const Args&... args) noexcept + [[nodiscard]] std::string safe_call_void(WrenHandle* method, Receiver receiver, const Args&... args) noexcept { set_call_slots(mWrenVM, receiver, args...); mErrorString.clear(); @@ -293,13 +286,13 @@ class WRENPLUS_API WrenPlusVM void interpret(const char* module, const char* source); /// Same as interpret, but return errors as a string. - std::string safe_interpret[[nodiscard]](const char* module, const char* source); + [[nodiscard]] std::string safe_interpret(const char* module, const char* source); /// Interpret a module from file, as if using import. void load_module(const char* module); /// Same as load_module, but return errors as a string. - std::string safe_load_module(const char* module); + [[nodiscard]] std::string safe_load_module(const char* module); /// Makes sure that no foreign class indices are missing. void validate_class_handle_cache(); @@ -307,19 +300,7 @@ class WRENPLUS_API WrenPlusVM //--------------------------------------------------------// /// Lookup a variable that is known to exist. - WrenHandle* get_variable(const char* module, const char* variable); - - //--------------------------------------------------------// - - /// Abort the current wren fiber with a formatted error message. - //template - //void abort(fmt::format_string str, Args&&... args) noexcept - //{ - // const std::string message = fmt::format(str, std::forward(args)...); - // wrenEnsureSlots(mWrenVM, 1); - // wrenSetSlotBytes(mWrenVM, 0, message.data(), message.length()); - // wrenAbortFiber(mWrenVM, 0); - //} + [[nodiscard]] WrenHandle* get_variable(const char* module, const char* variable); private: //===================================================// @@ -351,7 +332,7 @@ class WRENPLUS_API WrenPlusVM std::vector mModuleImportDirs; - std::map mForiegnMethods; + std::map mForeignMethods; std::vector mForeignClassHandles; @@ -406,6 +387,41 @@ struct MethodWrapper } }; +/// Internal data for foreign objects. +struct TaggedPointer +{ + void* ptr; + size_t index; +}; + +template +inline BaseType* base_class_slot_helper_get_inner(const TaggedPointer& data) +{ + if (data.index == Traits::index) + return static_cast(data.ptr); + + if constexpr (sizeof...(Types) != 0) + return base_class_slot_helper_get_inner(data); + + throw Exception("slot holds different type of Object"); +} + +template +inline void base_class_slot_helper_set_inner(WrenVM* vm, int slot, BaseType* ptr) +{ + if (dynamic_cast(ptr) != nullptr) + { + wrenSetSlotHandle(vm, slot, WrenPlusVM::access(vm).get_class_handle()); + auto& data = *static_cast(wrenSetSlotNewForeign(vm, slot, slot, sizeof(TaggedPointer))); + data = { ptr, Traits::index }; + } + + else if constexpr (sizeof...(Types) != 0) + base_class_slot_helper_set_inner(vm, slot, ptr); + + else throw Exception("dynamic_cast failed for base ptr"); +} + } // namespace detail } // namespace wren @@ -426,16 +442,16 @@ struct wren::SlotHelper template struct wren::SlotHelper>> { - struct TaggedPointer { Object* ptr; size_t index; }; - static Object* get(WrenVM* vm, int slot, WrenType slotType) { if (slotType == WREN_TYPE_FOREIGN) { - const auto& data = *static_cast(wrenGetSlotForeign(vm, slot)); - if (data.index != Traits::index) - throw Exception("slot holds different type of Object"); - return data.ptr; + const auto& data = *static_cast(wrenGetSlotForeign(vm, slot)); + + if (data.index == Traits::index) + return static_cast(data.ptr); + + throw Exception("slot holds different type of Object"); } if (slotType == WREN_TYPE_NULL) @@ -449,7 +465,7 @@ struct wren::SlotHelper>> if (ptr != nullptr) { wrenSetSlotHandle(vm, slot, WrenPlusVM::access(vm).get_class_handle()); - auto& data = *static_cast(wrenSetSlotNewForeign(vm, slot, slot, sizeof(TaggedPointer))); + auto& data = *static_cast(wrenSetSlotNewForeign(vm, slot, slot, sizeof(detail::TaggedPointer))); data = { ptr, Traits::index }; } else wrenSetSlotNull(vm, slot); @@ -656,8 +672,8 @@ struct wren::SlotHelper> #include /// Specialisation for the sqee enum helper. -template -struct wren::SlotHelper>> +template +struct wren::SlotHelper { static Enum get(WrenVM* vm, int slot, WrenType slotType) { diff --git a/include/sqee/core/EnumHelper.hpp b/include/sqee/core/EnumHelper.hpp index 774477df..9df14523 100644 --- a/include/sqee/core/EnumHelper.hpp +++ b/include/sqee/core/EnumHelper.hpp @@ -4,6 +4,8 @@ #pragma once #include +#include +#include #include @@ -12,62 +14,49 @@ #include #include #include -#include namespace sq { //============================================================================// -/// Specialise using the SQEE_ENUM_HELPER macro. -template struct EnumTraits : std::false_type {}; - -/// Check if EnumTraits has been specialised for a given enum type. -template constexpr bool has_enum_traits_v = EnumTraits::value; - -/// An iterable containing all enumeration values. -template constexpr auto enum_items_v = EnumTraits::items; - -/// The underlying value of the first enum. -template constexpr auto enum_first_v = EnumTraits::first; - -/// The number of enum values, excluding the first if it is -1. -template constexpr auto enum_count_v = EnumTraits::count; - -//============================================================================// - -/// Convert an enum to a string. -template -constexpr const char* enum_to_string(Type value) -{ - return EnumTraits::to_string(value); -} - /// Try to convert an enum to a string. -template -constexpr std::optional enum_to_string_safe(Type value) +template +constexpr std::optional enum_to_string_safe(Type arg) noexcept { - return EnumTraits::to_string_safe(value); + for (size_t i = 0u; i < enum_values_v.size(); ++i) + if (arg == enum_values_v[i]) + return enum_strings_v[i]; + + return std::nullopt; } -/// Convert a string to an enum. -template -constexpr Type enum_from_string(std::string_view sv) +/// Convert an enum to a string. +template +constexpr const char* enum_to_string(Type arg) { - return EnumTraits::from_string(sv); + if (auto opt = enum_to_string_safe(arg)) return *opt; + + throw std::runtime_error(fmt::format("enum_to_string<{}>({})", type_name_v.c_str(), std::underlying_type_t(arg))); } /// Try to convert a string to an enum. -template -constexpr std::optional enum_from_string_safe(std::string_view sv) +template +constexpr std::optional enum_from_string_safe(std::string_view arg) noexcept { - return EnumTraits::from_string_safe(sv); + for (size_t i = 0u; i < enum_strings_v.size(); ++i) + if (arg == enum_strings_v[i]) + return enum_values_v[i]; + + return std::nullopt; } -/// SFINAE overload for converting enums to c strings. -template -std::enable_if_t, const char*> to_c_string(Type arg) +/// Convert a string to an enum. +template +constexpr Type enum_from_string(std::string_view arg) { - return enum_to_string(arg); + if (auto opt = enum_from_string_safe(arg)) return *opt; + + throw std::runtime_error(fmt::format("enum_from_string<{}>({})", type_name_v.c_str(), arg)); } //============================================================================// @@ -76,51 +65,21 @@ std::enable_if_t, const char*> to_c_string(Type arg) //============================================================================// -#define SQEE_ENUM_ITEMS_INNER(Case) ,enum_type::Case - -#define SQEE_ENUM_TO_STRING_INNER(Case) case enum_type::Case: return #Case; - -#define SQEE_ENUM_FROM_STRING_INNER(Case) if (sv == #Case) return enum_type::Case; - #define SQEE_ENUM_HELPER(Type, First, ...) \ -template<> struct sq::EnumTraits : std::true_type \ -{ \ - using enum_type = Type; \ - using base_type = std::underlying_type_t; \ - static constexpr auto items = std::array { Type::First SQEE_FOR_EACH(SQEE_ENUM_ITEMS_INNER, __VA_ARGS__) }; \ - static constexpr auto first = base_type(items.front()); \ - static_assert(first == 0 || first == -1, "unsupported first value"); \ - static constexpr auto count = base_type(items.size()) + first; \ - static constexpr const char* to_string(Type value) \ - { \ - switch (value) { SQEE_FOR_EACH(SQEE_ENUM_TO_STRING_INNER, First, __VA_ARGS__) } \ - throw std::runtime_error(fmt::format("enum " #Type " to string: {}", base_type(value))); \ - } \ - static constexpr Type from_string(std::string_view sv) \ - { \ - SQEE_FOR_EACH(SQEE_ENUM_FROM_STRING_INNER, First, __VA_ARGS__) \ - throw std::runtime_error(fmt::format("enum " #Type " from string: '{}'", sv)); \ - } \ - static constexpr std::optional to_string_safe(Type value) \ - { \ - switch (value) { SQEE_FOR_EACH(SQEE_ENUM_TO_STRING_INNER, First, __VA_ARGS__) } \ - return std::nullopt; \ - } \ - static constexpr std::optional from_string_safe(std::string_view sv) \ - { \ - SQEE_FOR_EACH(SQEE_ENUM_FROM_STRING_INNER, First, __VA_ARGS__) \ - return std::nullopt; \ - } \ -}; +template <> inline constexpr auto sq::type_name_v = StackString(#Type); \ +template <> inline constexpr auto sq::enum_first_v = std::underlying_type_t(Type::First); \ +template <> inline constexpr auto sq::enum_count_v = std::underlying_type_t(int(Type::First) + SQEE_COUNT_ARGS(First, __VA_ARGS__)); \ +template <> inline constexpr auto sq::enum_values_v = []() { using enum Type; return std::array { First, __VA_ARGS__ }; }(); \ +template <> inline constexpr auto sq::enum_strings_v = []() { return std::array { SQEE_STRINGIFY_ARGS(First, __VA_ARGS__) }; }(); //============================================================================// -template -struct fmt::formatter>> : fmt::formatter +template +struct fmt::formatter : fmt::formatter { template - auto format(const Type& value, FormatContext& ctx) + constexpr auto format(const Type& value, FormatContext& ctx) const { - return formatter::format(sq::enum_to_string(value), ctx); + return fmt::formatter::format(sq::enum_to_string(value), ctx); } }; diff --git a/include/sqee/core/Macros.hpp b/include/sqee/core/Macros.hpp index 16ab1a0f..5bd9b71d 100644 --- a/include/sqee/core/Macros.hpp +++ b/include/sqee/core/Macros.hpp @@ -185,3 +185,11 @@ _Pragma("GCC diagnostic pop") #define CASE(...) break; SQEE_FOR_EACH(SQEE_CASE_INNER, __VA_ARGS__) #define CASE_DEFAULT break; default: + +//============================================================================// + +#define SQEE_COUNT_ARGS_INNER(Arg) +1 +#define SQEE_COUNT_ARGS(First, ...) (1 SQEE_FOR_EACH(SQEE_COUNT_ARGS_INNER, __VA_ARGS__)) + +#define SQEE_STRINGIFY_ARGS_INNER(Arg) ,#Arg +#define SQEE_STRINGIFY_ARGS(First, ...) #First SQEE_FOR_EACH(SQEE_STRINGIFY_ARGS_INNER, __VA_ARGS__) diff --git a/include/sqee/core/Strings.hpp b/include/sqee/core/Strings.hpp index e9a88875..3dec14da 100644 --- a/include/sqee/core/Strings.hpp +++ b/include/sqee/core/Strings.hpp @@ -5,36 +5,17 @@ #include +#include #include -#include -#include +#include #include #include -#include namespace sq { //============================================================================// -inline const char* to_c_string(const char* arg) -{ - return arg; -} - -inline const char* to_c_string(const std::string& arg) -{ - return arg.c_str(); -} - -template -inline const char* to_c_string(const StackString& arg) -{ - return arg.c_str(); -} - -//============================================================================// - template constexpr size_t string_length(const char(&)[Size]) { @@ -47,7 +28,7 @@ constexpr size_t string_length(const StackString& ss) return ss.length(); } -constexpr size_t string_length(char) +constexpr size_t string_length(const char&) { return 1u; } @@ -57,33 +38,52 @@ constexpr size_t string_length(const std::string_view& sv) return sv.length(); } -template >> -inline size_t string_length(const CharT* const& cstr) +template CharT> +constexpr size_t string_length(const CharT* const& cstr) { - return std::strlen(cstr); + return std::char_traits::length(cstr); } -//============================================================================// - -/// Function to join a bunch of strings with a single allocation. +/// Concatenate a bunch of strings with a single allocation. template -inline std::string build_string(Args&&... args) +inline std::string string_concat(const Args&... args) { - // todo: this is definitely using forward wrong std::string result; - result.reserve((string_length(std::forward(args)) + ...)); + result.reserve((string_length(args) + ...)); ((result += args), ...); return result; } //============================================================================// -/// Slightly more ergonomic wrapper around fmt::format_to. +template +consteval auto format_consteval() +{ + constexpr auto cfstr = FMT_COMPILE(std::string_view(fstr)); + StackString result; + fmt::format_to(result.data(), cfstr, args...); + return result; +}; + +//============================================================================// + +/// Only perform formatting if arguments are given. template -inline std::string& format_append(std::string& output, fmt::format_string str, Args&&... args) +using FmtStrIfArgs = std::conditional_t, fmt::string_view>; + +/// Version of vformat_to that only does formatting if args is not empty. +template +inline OutputIt vformat_to_if_args(OutputIt out, fmt::string_view fstr, fmt::format_args args) { - fmt::format_to(std::back_inserter(output), str, std::forward(args)...); - return output; + auto&& buf = fmt::detail::get_buffer(out); + + // check if there are any arguments by checking if desc_ has been set + if (reinterpret_cast(args) != 0) + fmt::detail::vformat_to(buf, fstr, args, {}); + else + buf.append(fstr.data(), fstr.data() + fstr.size()); + + return fmt::detail::get_iterator(buf, out); } //============================================================================// diff --git a/include/sqee/core/TypeAliases.hpp b/include/sqee/core/TypeAliases.hpp new file mode 100644 index 00000000..f2aaa2a0 --- /dev/null +++ b/include/sqee/core/TypeAliases.hpp @@ -0,0 +1,78 @@ +// Copyright(c) 2020 James Gangur +// Part of https://github.com/jagoly/sqee + +#pragma once + +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export + +//============================================================================== + +typedef unsigned char uchar; +typedef unsigned int uint; + +namespace sq { //############################################################### + +// template using Optional = std::optional; +// template using Expected = tl::expected; + +using String = std::string; +using StringView = std::string_view; + +template class StackString; +using TinyString = StackString<15u>; +using SmallString = StackString<23u>; + +template class StackVector; + +namespace maths { template struct Vector; } +using Vec2I = maths::Vector<2, int>; +using Vec3I = maths::Vector<3, int>; +using Vec4I = maths::Vector<4, int>; +using Vec2U = maths::Vector<2, uint>; +using Vec3U = maths::Vector<3, uint>; +using Vec4U = maths::Vector<4, uint>; +using Vec2F = maths::Vector<2, float>; +using Vec3F = maths::Vector<3, float>; +using Vec4F = maths::Vector<4, float>; + +namespace maths { template struct Matrix; } +using Mat3F = maths::Matrix<3, 3, float>; +using Mat34F = maths::Matrix<3, 4, float>; +using Mat4F = maths::Matrix<4, 4, float>; + +namespace maths { template struct Quaternion; } +using QuatF = maths::Quaternion; + +namespace maths { template struct RandomRange; } + +class JsonAny; class JsonArray; class JsonObject; class JsonDocument; +class JsonMutAny; class JsonMutArray; class JsonMutObject; class JsonMutDocument; + +} // namespace sq ############################################################## + +namespace sq::coretypes { //#################################################### + +// using sq::Optional, sq::Expected; + +using sq::String, sq::StringView; + +using sq::StackString, sq::TinyString, sq::SmallString; + +using sq::StackVector; + +using sq::Vec2I, sq::Vec3I, sq::Vec4I; +using sq::Vec2U, sq::Vec3U, sq::Vec4U; +using sq::Vec2F, sq::Vec3F, sq::Vec4F; + +using sq::Mat3F, sq::Mat34F, sq::Mat4F; + +using sq::QuatF; + +using sq::JsonAny, sq::JsonArray, sq::JsonObject, sq::JsonDocument; +using sq::JsonMutAny, sq::JsonMutArray, sq::JsonMutObject, sq::JsonMutDocument; + +} // namespace sq::coretypes ################################################### diff --git a/include/sqee/core/TypeNames.hpp b/include/sqee/core/TypeNames.hpp new file mode 100644 index 00000000..79d1d045 --- /dev/null +++ b/include/sqee/core/TypeNames.hpp @@ -0,0 +1,72 @@ +// Copyright(c) 2020 James Gangur +// Part of https://github.com/jagoly/sqee + +#pragma once + +#include +#include +#include + +namespace sq { //############################################################### + +template <> inline constexpr auto type_name_v = StackString("nullptr"); + +template <> inline constexpr auto type_name_v = StackString("bool"); +template <> inline constexpr auto type_name_v = StackString("int8"); +template <> inline constexpr auto type_name_v = StackString("int16"); +template <> inline constexpr auto type_name_v = StackString("int32"); +template <> inline constexpr auto type_name_v = StackString("int64"); +template <> inline constexpr auto type_name_v = StackString("uint8"); +template <> inline constexpr auto type_name_v = StackString("uint16"); +template <> inline constexpr auto type_name_v = StackString("uint32"); +template <> inline constexpr auto type_name_v = StackString("uint64"); +template <> inline constexpr auto type_name_v = StackString("float32"); +template <> inline constexpr auto type_name_v = StackString("float64"); + +template <> inline constexpr auto type_name_v = StackString("String"); +template <> inline constexpr auto type_name_v = StackString("StringView"); + +template +inline constexpr auto type_name_v> = format_consteval<"StackString<{}>", Capacity>(); +template <> inline constexpr auto type_name_v = StackString("TinyString"); +template <> inline constexpr auto type_name_v = StackString("SmallString"); + +template +inline constexpr auto type_name_v> = format_consteval<"StackVector<{}, {}>", type_name_v, Capacity>(); + +template +inline constexpr auto type_name_v> = format_consteval<"Vector<{}, {}>", Size, type_name_v>(); +template <> inline constexpr auto type_name_v = StackString("Vec2I"); +template <> inline constexpr auto type_name_v = StackString("Vec3I"); +template <> inline constexpr auto type_name_v = StackString("Vec4I"); +template <> inline constexpr auto type_name_v = StackString("Vec2U"); +template <> inline constexpr auto type_name_v = StackString("Vec3U"); +template <> inline constexpr auto type_name_v = StackString("Vec4U"); +template <> inline constexpr auto type_name_v = StackString("Vec2F"); +template <> inline constexpr auto type_name_v = StackString("Vec3F"); +template <> inline constexpr auto type_name_v = StackString("Vec4F"); + +template +inline constexpr auto type_name_v> = format_consteval<"Matrix<{}, {}, {}>", Width, Height, type_name_v>(); +template <> inline constexpr auto type_name_v = StackString("Mat3F"); +template <> inline constexpr auto type_name_v = StackString("Mat34F"); +template <> inline constexpr auto type_name_v = StackString("Mat4F"); + +template +inline constexpr auto type_name_v> = format_consteval<"Quaternion<{}>", type_name_v>(); +template <> inline constexpr auto type_name_v> = StackString("QuatF"); + +template +inline constexpr auto type_name_v> = format_consteval<"RandomRange<{}>", type_name_v>(); + +template <> inline constexpr auto type_name_v = StackString("JsonAny"); +template <> inline constexpr auto type_name_v = StackString("JsonArray"); +template <> inline constexpr auto type_name_v = StackString("JsonObject"); +template <> inline constexpr auto type_name_v = StackString("JsonDocument"); + +template <> inline constexpr auto type_name_v = StackString("JsonMutAny"); +template <> inline constexpr auto type_name_v = StackString("JsonMutArray"); +template <> inline constexpr auto type_name_v = StackString("JsonMutObject"); +template <> inline constexpr auto type_name_v = StackString("JsonMutDocument"); + +} // namespace sq ############################################################## diff --git a/include/sqee/core/TypeTraits.hpp b/include/sqee/core/TypeTraits.hpp new file mode 100644 index 00000000..4d3683f2 --- /dev/null +++ b/include/sqee/core/TypeTraits.hpp @@ -0,0 +1,47 @@ +// Copyright(c) 2020 James Gangur +// Part of https://github.com/jagoly/sqee + +#pragma once + +#include // IWYU pragma: export +#include // IWYU pragma: export + +namespace sq { //############################################################### + +template +concept EqualToAny = ((Value == Values) || ...); + +template +concept SameAsAny = (std::same_as || ...); + +//============================================================================== + +/// Specialise with a StackString containing the canonical name of a type. +template +constexpr auto type_name_v = nullptr; + +template +concept HasTypeName = !std::same_as), const std::nullptr_t>; + +//============================================================================== + +/// The underlying value of the first enum, either -1 or 0. +template +constexpr auto enum_first_v = nullptr; + +/// The number of enum values, excluding the first if it is -1. +template +constexpr auto enum_count_v = nullptr; + +/// An iterable containing all values for an enum. +template +constexpr auto enum_values_v = nullptr; + +/// An iterable containing all strings for an enum. +template +constexpr auto enum_strings_v = nullptr; + +template +concept HasEnumHelper = !std::same_as), const std::nullptr_t>; + +} // namespace sq ############################################################## diff --git a/include/sqee/core/Types.hpp b/include/sqee/core/Types.hpp index 492b53d5..04a3eb77 100644 --- a/include/sqee/core/Types.hpp +++ b/include/sqee/core/Types.hpp @@ -6,68 +6,14 @@ // todo: might be good to split all of the maths functions into seperate files, // leaving just the types and string conversions in the main headers +#include // IWYU pragma: export + #include // IWYU pragma: export #include // IWYU pragma: export #include // IWYU pragma: export #include // IWYU pragma: export -#include // IWYU pragma: export + #include // IWYU pragma: export -#include // IWYU pragma: export #include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export #include // IWYU pragma: export - -//============================================================================// - -typedef unsigned char uchar; -typedef unsigned int uint; - -//============================================================================// - -namespace sq { - -using String = std::string; -using StringView = std::string_view; - -using TinyString = StackString<15u>; -using SmallString = StackString<23u>; - -using Vec2I = maths::Vector<2, int>; -using Vec3I = maths::Vector<3, int>; -using Vec4I = maths::Vector<4, int>; -using Vec2U = maths::Vector<2, uint>; -using Vec3U = maths::Vector<3, uint>; -using Vec4U = maths::Vector<4, uint>; -using Vec2F = maths::Vector<2, float>; -using Vec3F = maths::Vector<3, float>; -using Vec4F = maths::Vector<4, float>; - -using Mat3F = maths::Matrix<3, 3, float>; -using Mat34F = maths::Matrix<3, 4, float>; -using Mat4F = maths::Matrix<4, 4, float>; - -using QuatF = maths::Quaternion; - -} // namespace sq - -//============================================================================// - -namespace sq::coretypes { - -using sq::String, sq::StringView; - -using sq::TinyString, sq::SmallString; - -using sq::Vec2I, sq::Vec3I, sq::Vec4I; -using sq::Vec2U, sq::Vec3U, sq::Vec4U; -using sq::Vec2F, sq::Vec3F, sq::Vec4F; - -using sq::Mat3F, sq::Mat34F, sq::Mat4F; - -using sq::QuatF; - -using sq::JsonValue; - -} // namespace sq::coretypes diff --git a/include/sqee/debug/Assert.hpp b/include/sqee/debug/Assert.hpp index e6b10b60..c262bd44 100644 --- a/include/sqee/debug/Assert.hpp +++ b/include/sqee/debug/Assert.hpp @@ -58,7 +58,7 @@ do { \ #if defined(SQEE_GNU) || defined(SQEE_CLANG) #define SQEE_UNREACHABLE() __builtin_unreachable() #elif defined(SQEE_MSVC) - #define UNREACHABLE() __assume(0) + #define SQEE_UNREACHABLE() __assume(0) #endif #endif diff --git a/include/sqee/debug/Logging.hpp b/include/sqee/debug/Logging.hpp index 20f386f1..96c1c50a 100644 --- a/include/sqee/debug/Logging.hpp +++ b/include/sqee/debug/Logging.hpp @@ -7,7 +7,6 @@ #include -#include #include #include @@ -17,120 +16,89 @@ namespace sq { namespace detail { -SQEE_API void log_time_info(); -SQEE_API void log_time_warning(); -SQEE_API void log_time_error(); -SQEE_API void log_time_debug(); +SQEE_API void log(std::string_view category, std::string_view str); -} // namespace detail - -//============================================================================// - -SQEE_API void log_raw(std::string_view str); +SQEE_API void log_multiline(std::string_view category, std::string_view str); -SQEE_API void log_raw_multiline(std::string_view str); +SQEE_API void log(std::string_view category, fmt::string_view fstr, fmt::format_args args); -template -inline void log_raw(fmt::format_string str, Args&&... args) -{ - fmt::print(stdout, str, std::forward(args)...); - std::fputc('\n', stdout); - std::fflush(stdout); -} +SQEE_API void log_multiline(std::string_view category, fmt::string_view fstr, fmt::format_args args); -template -inline void log_raw_multiline(fmt::format_string str, Args&&... args) -{ - log_raw_multiline ( - fmt::format(str, std::forward(args)...) - ); -} +} // namespace detail //============================================================================// inline void log_info(std::string_view str) { - detail::log_time_info(); - log_raw(str); + detail::log("INFO", str); } inline void log_info_multiline(std::string_view str) { - detail::log_time_info(); - log_raw_multiline(str); + detail::log_multiline("INFO", str); } template -inline void log_info(fmt::format_string str, Args&&... args) +inline void log_info(fmt::format_string fstr, Args&&... args) { - detail::log_time_info(); - log_raw(str, std::forward(args)...); + detail::log("INFO", fstr, fmt::make_format_args(args...)); } template -inline void log_info_multiline(fmt::format_string str, Args&&... args) +inline void log_info_multiline(fmt::format_string fstr, Args&&... args) { - detail::log_time_info(); - log_raw_multiline(str, std::forward(args)...); + detail::log_multiline("INFO", fstr, fmt::make_format_args(args...)); } //============================================================================// inline void log_warning(std::string_view str) { - detail::log_time_warning(); - log_raw(str); + detail::log("WARNING", str); } inline void log_warning_multiline(std::string_view str) { - detail::log_time_warning(); - log_raw_multiline(str); + detail::log_multiline("WARNING", str); } template -inline void log_warning(fmt::format_string str, Args&&... args) +inline void log_warning(fmt::format_string fstr, Args&&... args) { - detail::log_time_warning(); - log_raw(str, std::forward(args)...); + detail::log("WARNING", fstr, fmt::make_format_args(args...)); } template -inline void log_warning_multiline(fmt::format_string str, Args&&... args) +inline void log_warning_multiline(fmt::format_string fstr, Args&&... args) { - detail::log_time_warning(); - log_raw_multiline(str, std::forward(args)...); + detail::log_multiline("WARNING", fstr, fmt::make_format_args(args...)); } //============================================================================// [[noreturn]] inline void log_error(std::string_view str) { - detail::log_time_error(); - log_raw(str); + detail::log("ERROR", str); std::abort(); } [[noreturn]] inline void log_error_multiline(std::string_view str) { - detail::log_time_error(); - log_raw_multiline(str); + detail::log_multiline("ERROR", str); std::abort(); } template -[[noreturn]] inline void log_error(fmt::format_string str, Args&&... args) +[[noreturn]] inline void log_error(fmt::format_string fstr, Args&&... args) { - detail::log_time_error(); - log_raw(str, std::forward(args)...); + detail::log("ERROR", fstr, fmt::make_format_args(args...)); std::abort(); } template -[[noreturn]] inline void log_error_multiline(fmt::format_string str, Args&&... args) +[[noreturn]] inline void log_error_multiline(fmt::format_string fstr, Args&&... args) { - detail::log_time_error(); - log_raw_multiline(str, std::forward(args)...); + detail::log_multiline("ERROR", fstr, fmt::make_format_args(args...)); std::abort(); } @@ -139,45 +107,65 @@ template inline void log_debug(std::string_view str) { #ifdef SQEE_DEBUG - detail::log_time_debug(); - log_raw(str); + detail::log("DEBUG", str); #else - (void)str; ((void)args, ...); + (void)str; #endif } inline void log_debug_multiline(std::string_view str) { #ifdef SQEE_DEBUG - detail::log_time_debug(); - log_raw_multiline(str); + detail::log_multiline("DEBUG", str); #else - (void)str; ((void)args, ...); + (void)str; #endif } template -inline void log_debug(fmt::format_string str, Args&&... args) +inline void log_debug(fmt::format_string fstr, Args&&... args) { #ifdef SQEE_DEBUG - detail::log_time_debug(); - log_raw(str, std::forward(args)...); + detail::log("DEBUG", fstr, fmt::make_format_args(args...)); #else - (void)str; ((void)args, ...); + (void)fstr; ((void)args, ...); #endif } template -inline void log_debug_multiline(fmt::format_string str, Args&&... args) +inline void log_debug_multiline(fmt::format_string fstr, Args&&... args) { #ifdef SQEE_DEBUG - detail::log_time_debug(); - log_raw_multiline(str, std::forward(args)...); + detail::log_multiline("DEBUG", fstr, fmt::make_format_args(args...)); #else - (void)str; ((void)args, ...); + (void)fstr; ((void)args, ...); #endif } //============================================================================// +inline void log_custom(std::string_view category, std::string_view str) +{ + detail::log(category, str); +} + +inline void log_custom_multiline(std::string_view category, std::string_view str) +{ + detail::log_multiline(category, str); +} + +template +inline void log_custom(std::string_view category, fmt::format_string fstr, Args&&... args) +{ + detail::log(category, fstr, fmt::make_format_args(args...)); +} + +template +inline void log_custom_multiline(std::string_view category, fmt::format_string fstr, Args&&... args) +{ + detail::log_multiline(category, fstr, fmt::make_format_args(args...)); +} + +//============================================================================// + } // namespace sq diff --git a/include/sqee/maths/Approx.hpp b/include/sqee/maths/Approx.hpp deleted file mode 100644 index f336a798..00000000 --- a/include/sqee/maths/Approx.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright(c) 2020 James Gangur -// Part of https://github.com/jagoly/sqee - -#pragma once - -#include -#include -#include - -#include - -#include -#include - -namespace sq::maths { - -//============================================================================// - -/// Simple templated version of a Catch's Approx class. -template struct Approx -{ - constexpr explicit Approx(T value) : value(value) {} - constexpr Approx(const Approx& other) : value(other.value) {} - - static_assert ( - std::is_floating_point_v || detail::is_vector_v || detail::is_matrix_v || detail::is_quaternion_v, - "Approx not implemented for this type" - ); - - const T value; -}; - -// deduction guide so we don't need a helper function -template Approx(T) -> Approx; - -//============================================================================// - -// note that epsilon is just high enough for current unit tests to pass - -constexpr bool operator==(float a, Approx b) -{ - const float maxScale = maths::max(maths::abs(a), maths::abs(b.value)); - return maths::abs(a - b.value) <= std::numeric_limits::epsilon() * 5.f * (1.f + maxScale); -} - -constexpr bool operator==(double a, Approx b) -{ - const double maxScale = maths::max(maths::abs(a), maths::abs(b.value)); - return maths::abs(a - b.value) <= std::numeric_limits::epsilon() * 5.0 * (1.0 + maxScale); -} - -template -constexpr bool operator==(Vector a, Approx> b) -{ - bool result = true; - for (int i = 0; i < S; ++i) - result &= a[i] == Approx(b.value[i]); - return result; -} - -template -constexpr bool operator==(Matrix a, Approx> b) -{ - bool result = true; - for (int i = 0; i < H; ++i) - for (int j = 0; j < W; ++j) - result &= a[i][j] == Approx(b.value[i][j]); - return result; -} - -template -constexpr bool operator==(Quaternion a, Approx> b) -{ - bool resultPos = true; - for (int i = 0; i < 4; ++i) - resultPos &= +a[i] == Approx(b.value[i]); - bool resultNeg = true; - for (int i = 0; i < 4; ++i) - resultNeg &= -a[i] == Approx(b.value[i]); - return resultPos || resultNeg; -} - -// these can all be defined in terms of the same operator -template inline bool operator==(Approx a, T b) { return operator==(b, a); } -template inline bool operator!=(T a, Approx b) { return !operator==(a, b); } -template inline bool operator!=(Approx a, T b) { return !operator==(b, a); } - -//============================================================================// - -} // namespace sq::maths - -//============================================================================// - -template -struct fmt::formatter> : fmt::formatter -{ - template - auto format(const sq::maths::Approx& approx, FormatContext& ctx) - { - fmt::format_to(ctx.out(), "Approx("); - formatter::format(approx.value, ctx); - return fmt::format_to(ctx.out(), ")"); - } -}; diff --git a/include/sqee/maths/Colours.hpp b/include/sqee/maths/Colours.hpp index 140f3e37..ceda70d8 100644 --- a/include/sqee/maths/Colours.hpp +++ b/include/sqee/maths/Colours.hpp @@ -3,22 +3,22 @@ #pragma once -#include +#include -namespace sq::maths { +#include +#include -//============================================================================// +namespace sq::maths { //######################################################## /// Convert an HSV colour value to sRGB. -template constexpr Vector3 hsv_to_srgb(Vector3 hsv) +inline Vec3F hsv_to_srgb(Vec3F hsv) { - static_assert(std::is_floating_point_v); + const int i = int(hsv.x * 6.f); - const int i = int(hsv[0] * T(6)); - const T f = hsv[0] * T(6) - T(i); - const T p = hsv[2] * (T(1) - hsv[1]); - const T q = hsv[2] * (T(1) - f * hsv[1]); - const T t = hsv[2] * (T(1) - (T(1) - f) * hsv[1]); + const float f = hsv.x * 6.f - float(i); + const float p = hsv.z * (1.f - hsv.y); + const float q = hsv.z * (1.f - f * hsv.y); + const float t = hsv.z * (1.f - (1.f - f) * hsv.y); const int j = i % 6; @@ -28,44 +28,40 @@ template constexpr Vector3 hsv_to_srgb(Vector3 hsv) if (j == 3) return { p, q, hsv.z }; if (j == 4) return { t, p, hsv.z }; if (j == 5) return { hsv.z, p, q }; + + return {}; // unreachable } -//============================================================================// +//============================================================================== /// Convert an sRGB scalar to linear. -template constexpr T srgb_to_linear(T value) +inline float srgb_to_linear(float value) { - static_assert(std::is_floating_point_v); - - if (value <= T(0.04045)) return value / T(12.92); - return std::pow(value + T(0.055) / T(1.055), T(2.4)); + if (value <= 0.04045f) return value / 12.92f; + return std::pow((value + 0.055f) / 1.055f, 2.4f); } /// Convert an sRGB vector to linear. -template constexpr Vector3 srgb_to_linear(Vector3 rgb) +inline Vec3F srgb_to_linear(Vec3F rgb) { - static_assert(std::is_floating_point_v); - - const T r = srgb_to_linear(rgb.r); - const T g = srgb_to_linear(rgb.g); - const T b = srgb_to_linear(rgb.b); + const float r = srgb_to_linear(rgb.x); + const float g = srgb_to_linear(rgb.y); + const float b = srgb_to_linear(rgb.z); return { r, g, b }; } /// Convert an sRGB+A vector to linear. -template constexpr Vector4 srgb_to_linear(Vector4 rgba) +inline Vec4F srgb_to_linear(Vec4F rgba) { - static_assert(std::is_floating_point_v); + const float r = srgb_to_linear(rgba.x); + const float g = srgb_to_linear(rgba.y); + const float b = srgb_to_linear(rgba.z); - const T r = srgb_to_linear(rgba.r); - const T g = srgb_to_linear(rgba.g); - const T b = srgb_to_linear(rgba.b); - - return { r, g, b, rgba.a }; + return { r, g, b, rgba.w }; } -//============================================================================// +//============================================================================== /// Compress a hdr colour into a 32 bit unsigned integer. inline uint32_t hdr_to_e5bgr9(Vec3F rgb) @@ -73,7 +69,7 @@ inline uint32_t hdr_to_e5bgr9(Vec3F rgb) constexpr float MAX_VALUE = float((1<<9)-1) / float(1<<9) * float(1<<5); const Vec3F clamped = maths::clamp(rgb, Vec3F(0.f), Vec3F(MAX_VALUE)); - const float maxComponent = maths::max(clamped.r, clamped.g, clamped.b); + const float maxComponent = maths::max(clamped.x, clamped.y, clamped.z); const float prelimExponent = std::max(-15.f - 1.f, std::floor(std::log2(maxComponent))) + 1.f + 15.f; const float maxExponent = std::floor(maxComponent / std::pow(2.f, (prelimExponent - 15.f - 9.f)) + 0.5f); @@ -81,9 +77,7 @@ inline uint32_t hdr_to_e5bgr9(Vec3F rgb) const Vec3U values = Vec3U(clamped / std::pow(2.f, (exponent - 15.f - 9.f)) + 0.5f); - return uint(exponent) << 27 | values.b << 18 | values.g << 9 | values.r; + return uint(exponent) << 27 | values.z << 18 | values.y << 9 | values.x; } -//============================================================================// - -} // namespace sq::maths +} // namespace sq::maths ####################################################### diff --git a/include/sqee/maths/Functions.hpp b/include/sqee/maths/Functions.hpp index ec379a89..420e98f8 100644 --- a/include/sqee/maths/Functions.hpp +++ b/include/sqee/maths/Functions.hpp @@ -3,219 +3,237 @@ #pragma once -#include - +#include #include #include #include -namespace sq::maths { - -//============================================================================// +namespace sq::maths { //######################################################## -/// Scale a Matrix33 by Vector3. -template constexpr -Matrix33 scale(Matrix33 m, Vector3 v) +/// Apply a scale to a 3x3 matrix. +template +constexpr Matrix33 scale(Matrix33 m, Vector3 v) { - return Matrix33 ( m[0]*v.x, m[1]*v.y, m[2]*v.z ); + return { m[0] * v.x, m[1] * v.y, m[2] * v.z }; } -/// Scale a Matrix44 by Vector3. -template constexpr -Matrix44 scale(Matrix44 m, Vector3 v) +/// Apply a scale to a 4x4 matrix. +template +constexpr Matrix44 scale(Matrix44 m, Vector3 v) { - return Matrix44 ( m[0]*v[0], m[1]*v[1], m[2]*v[2], m[3] ); + return { m[0] * v.x, m[1] * v.y, m[2] * v.z, m[3] }; } -//============================================================================// - -/// Translate a Matrix44 by Vector3. -template constexpr -Matrix44 translate(Matrix44 m, Vector3 v) +/// Apply a translation to a 4x4 matrix. +template +constexpr Matrix44 translate(Matrix44 m, Vector3 v) { - auto colD = m[0]*v.x + m[1]*v.y + m[2]*v.z + m[3]; - return Matrix44 ( m[0], m[1], m[2], colD ); + Vector colD = m[0] * v.x + m[1] * v.y + m[2] * v.z + m[3]; + return { m[0], m[1], m[2], colD }; } -//============================================================================// +//============================================================================== /// Create a matrix from a translation, rotation, and scale. -template constexpr -Matrix44 transform(Vector3 translation, Matrix33 rotation, Vector3 scale) +template +constexpr Matrix44 transform(Vector3 translation, Matrix33 rotation, Vector3 scale) { - auto result = Matrix44 ( maths::scale(rotation, scale) ); - result[3] = Vector4 ( translation, T(1.0) ); - return result; + Vector colA { rotation[0] * scale.x, T(0.0) }; + Vector colB { rotation[1] * scale.y, T(0.0) }; + Vector colC { rotation[2] * scale.z, T(0.0) }; + Vector colD { translation, T(1.0) }; + + return { colA, colB, colC, colD }; } /// Create a matrix from a translation, rotation, and scale. -template constexpr -Matrix44 transform(Vector3 translation, Matrix33 rotation, T scale) +template +constexpr Matrix44 transform(Vector3 translation, Matrix33 rotation, T scale) { return maths::transform(translation, rotation, Vector3(scale)); } /// Create a matrix from a translation, rotation, and scale. -template constexpr -Matrix44 transform(Vector3 translation, Quaternion rotation, Vector3 scale) +template +constexpr Matrix44 transform(Vector3 translation, Quaternion rotation, Vector3 scale) { return maths::transform(translation, Matrix33(rotation), scale); } /// Create a matrix from a translation, rotation, and scale. -template constexpr -Matrix44 transform(Vector3 translation, Quaternion rotation, T scale) +template +constexpr Matrix44 transform(Vector3 translation, Quaternion rotation, T scale) { return maths::transform(translation, Matrix33(rotation), Vector3(scale)); } -//============================================================================// +//============================================================================== /// Create a matrix from a translation and rotation. -template constexpr -Matrix44 transform(Vector3 translation, Matrix33 rotation) +template +constexpr Matrix44 transform(Vector3 translation, Matrix33 rotation) { - auto result = Matrix44 ( rotation ); - result[3] = Vector4 ( translation, T(1.0) ); - return result; + Vector colA { rotation[0], T(0.0) }; + Vector colB { rotation[1], T(0.0) }; + Vector colC { rotation[2], T(0.0) }; + Vector colD { translation, T(1.0) }; + + return { colA, colB, colC, colD }; } /// Create a matrix from a translation and rotation. -template constexpr -Matrix44 transform(Vector3 translation, Quaternion rotation) +template +constexpr Matrix44 transform(Vector3 translation, Quaternion rotation) { return maths::transform(translation, Matrix33(rotation)); } -//============================================================================// +//============================================================================== /// Create a matrix from a translation and scale. -template constexpr -Matrix44 transform(Vector3 translation, Vector3 scale) +template +constexpr Matrix44 transform(Vector3 translation, Vector3 scale) { - Vector4 colA { scale.x, 0.0, 0.0, 0.0 }; - Vector4 colB { 0.0, scale.y, 0.0, 0.0 }; - Vector4 colC { 0.0, 0.0, scale.z, 0.0 }; - Vector4 colD ( translation, T(1.0) ); + Vector colA { scale.x, T(0.0), T(0.0), T(0.0) }; + Vector colB { T(0.0), scale.y, T(0.0), T(0.0) }; + Vector colC { T(0.0), T(0.0), scale.z, T(0.0) }; + Vector colD { translation, T(1.0) }; - return Matrix44 ( colA, colB, colC, colD ); + return { colA, colB, colC, colD }; } /// Create a matrix from a translation and scale. -template constexpr -Matrix44 transform(Vector3 translation, T scale) +template +constexpr Matrix44 transform(Vector3 translation, T scale) { return maths::transform(translation, Vector3(scale)); } -//============================================================================// +//============================================================================== /// Create a rotation matrix from an axis and angle. -template constexpr -Matrix33 rotation(Vector3 axis, T angle) +template +inline Matrix33 rotation(Vector3 axis, T angle) { - const T c = std::cos(maths::radians(angle)), s = std::sin(maths::radians(angle)); - const Vector3 x = axis * axis.x, y = axis * axis.y, z = axis * axis.z; + T c = std::cos(maths::radians(angle)); + Vector s = axis * std::sin(maths::radians(angle)); - Vector3 colA { x.x + (T(1)-x.x) * c, x.y * (T(1)-c) - axis.z * s, x.z * (T(1)-c) + axis.y * s }; - Vector3 colB { y.x * (T(1)-c) + axis.z * s, y.y + (T(1)-y.y) * c, y.z * (T(1)-c) - axis.x * s }; - Vector3 colC { z.x * (T(1)-c) - axis.y * s, z.y * (T(1)-c) + axis.x * s, z.z + (T(1)-z.z) * c }; + Vector x = axis * axis.x, y = axis * axis.y, z = axis * axis.z; - return Matrix33 { colA, colB, colC }; + Vector colA { x.x + (T(1.0) - x.x) * c, x.y * (T(1.0) - c) - s.z, x.z * (T(1.0) - c) + s.y }; + Vector colB { y.x * (T(1.0) - c) + s.z, y.y + (T(1.0) - y.y) * c, y.z * (T(1.0) - c) - s.x }; + Vector colC { z.x * (T(1.0) - c) - s.y, z.y * (T(1.0) - c) + s.x, z.z + (T(1.0) - z.z) * c }; + + return { colA, colB, colC }; } -//============================================================================// +/// Create a rotation matrix from an Euler rotation. +template +inline Matrix33 rotation(Vector3 xyz) +{ + Vector c = maths::cos(-xyz); + Vector s = maths::sin(-xyz); + + Vector colA { c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z }; + Vector colB { c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z }; + Vector colC { -s.y, s.x * c.y, c.x * c.y }; + + return { colA, colB, colC }; +} + +//============================================================================== /// Create a left-handed view matrix from two points and a direction. -template inline -Matrix44 look_at_LH(Vector3 eye, Vector3 target, Vector3 up) +template +inline Matrix44 look_at_LH(Vector3 eye, Vector3 target, Vector3 up) { - Vector3 f = normalize(target - eye); - Vector3 s = normalize(maths::cross(up, f)); - Vector3 u = maths::cross(f, s); - - Vector4 colA { s.x, u.x, f.x, 0.0 }; - Vector4 colB { s.y, u.y, f.y, 0.0 }; - Vector4 colC { s.z, u.z, f.z, 0.0 }; + Vector f = maths::normalize(target - eye); + Vector s = maths::normalize(maths::cross(up, f)); + Vector u = maths::cross(f, s); - Vector4 colD { -dot(s, eye), -dot(u, eye), -dot(f, eye), 1.0 }; + Vector colA { s.x, u.x, f.x, T(0.0) }; + Vector colB { s.y, u.y, f.y, T(0.0) }; + Vector colC { s.z, u.z, f.z, T(0.0) }; + Vector colD { -maths::dot(s, eye), -maths::dot(u, eye), -maths::dot(f, eye), T(1.0) }; - return Matrix44 ( colA, colB, colC, colD ); + return { colA, colB, colC, colD }; } /// Create a right-handed view matrix from two points and a direction. -template inline -Matrix44 look_at_RH(Vector3 eye, Vector3 target, Vector3 up) +template +inline Matrix44 look_at_RH(Vector3 eye, Vector3 target, Vector3 up) { - Vector3 f = normalize(target - eye); - Vector3 s = normalize(maths::cross(f, up)); - Vector3 u = maths::cross(s, f); - - Vector4 colA { s.x, u.x, -f.x, 0.0 }; - Vector4 colB { s.y, u.y, -f.y, 0.0 }; - Vector4 colC { s.z, u.z, -f.z, 0.0 }; + Vector f = maths::normalize(target - eye); + Vector s = maths::normalize(maths::cross(f, up)); + Vector u = maths::cross(s, f); - Vector4 colD { -dot(s, eye), -dot(u, eye), dot(f, eye), 1.0 }; + Vector colA { s.x, u.x, -f.x, T(0.0) }; + Vector colB { s.y, u.y, -f.y, T(0.0) }; + Vector colC { s.z, u.z, -f.z, T(0.0) }; + Vector colD { -maths::dot(s, eye), -maths::dot(u, eye), maths::dot(f, eye), T(1.0) }; - return Matrix44 ( colA, colB, colC, colD ); + return { colA, colB, colC, colD }; } -//============================================================================// +//============================================================================== #undef near // mingw or win32 crap #undef far // mingw or win32 crap /// Create a left-handed perspective projection matrix. -template inline -Matrix44 perspective_LH(T fov, T aspect, T near, T far) +template +inline Matrix44 perspective_LH(T fov, T aspect, T near, T far) { T tanHalfFov = std::tan(fov * T(0.5)); - Vector4 colA { T(1.0) / (aspect * tanHalfFov), 0.0, 0.0, 0.0 }; - Vector4 colB { 0.0, T(1.0) / tanHalfFov, 0.0, 0.0 }; - Vector4 colC { 0.0, 0.0, far / (far - near), +1.0 }; - Vector4 colD { 0.0, 0.0, -(far * near) / (far - near), 0.0 }; + Vector colA { T(1.0) / (aspect * tanHalfFov), T(0.0), T(0.0), T(0.0) }; + Vector colB { T(0.0), T(1.0) / tanHalfFov, T(0.0), T(0.0) }; + Vector colC { T(0.0), T(0.0), far / (far - near), T(+1.0) }; + Vector colD { T(0.0), T(0.0), -(far * near) / (far - near), T(0.0) }; - return Matrix44 ( colA, colB, colC, colD ); + return { colA, colB, colC, colD }; } /// Create a right-handed perspective projection matrix. -template inline -Matrix44 perspective_RH(T fov, T aspect, T near, T far) +template +inline Matrix44 perspective_RH(T fov, T aspect, T near, T far) { T tanHalfFov = std::tan(fov * T(0.5)); - Vector4 colA { T(1.0) / (aspect * tanHalfFov), 0.0, 0.0, 0.0 }; - Vector4 colB { 0.0, T(1.0) / tanHalfFov, 0.0, 0.0 }; - Vector4 colC { 0.0, 0.0, far / (near - far), -1.0 }; - Vector4 colD { 0.0, 0.0, -(far * near) / (far - near), 0.0 }; + Vector colA { T(1.0) / (aspect * tanHalfFov), T(0.0), T(0.0), T(0.0) }; + Vector colB { T(0.0), T(1.0) / tanHalfFov, T(0.0), T(0.0) }; + Vector colC { T(0.0), T(0.0), far / (near - far), T(-1.0) }; + Vector colD { T(0.0), T(0.0), -(far * near) / (far - near), T(0.0) }; - return Matrix44 ( colA, colB, colC, colD ); + return { colA, colB, colC, colD }; } /// Create a left-handed perspective projection matrix. -template inline -Matrix44 perspective_LH(T fov, T aspect, Vector2 range) +template +inline Matrix44 perspective_LH(T fov, T aspect, Vector2 range) { return maths::perspective_LH(fov, aspect, range.x, range.y); } /// Create a right-handed perspective projection matrix. -template inline -Matrix44 perspective_RH(T fov, T aspect, Vector2 range) +template +inline Matrix44 perspective_RH(T fov, T aspect, Vector2 range) { return maths::perspective_RH(fov, aspect, range.x, range.y); } -//============================================================================// +//============================================================================== /// Create a left-handed orthographic projection matrix. -template inline -Matrix44 ortho_LH(T l, T r, T b, T t, T n, T f) +template +inline Matrix44 ortho_LH(T l, T r, T b, T t, T n, T f) { - T ax = T(2.0) / (r-l); T by = T(2.0) / (t-b); T cz = T(1.0) / (f-n); - Vector4 colD { -(r+l) / (r-l), -(t+b) / (t-b), -n / (f-n), 1.0 }; - return Matrix44 ( {ax, 0, 0, 0}, {0, by, 0, 0}, {0, 0, cz, 0}, colD ); + Vector colA { T(2.0) / (r-l), T(0.0), T(0.0), T(0.0) }; + Vector colB { T(0.0), T(2.0) / (t-b), T(0.0), T(0.0) }; + Vector colC { T(0.0), T(0.0), T(1.0) / (f-n), T(0.0) }; + Vector colD { -(r+l) / (r-l), -(t+b) / (t-b), -n / (f-n), T(1.0) }; + + return { colA, colB, colC, colD }; } /// Create a right-handed orthographic projection matrix. @@ -229,67 +247,63 @@ Matrix44 ortho_RH(T l, T r, T b, T t, T n, T f) } /// Create a left-handed orthographic projection matrix. -template inline -Matrix44 ortho_LH(Vector3 min, Vector3 max) +template +inline Matrix44 ortho_LH(Vector3 min, Vector3 max) { return maths::ortho_LH(min.x, max.x, min.y, max.y, min.z, max.z); } /// Create a right-handed orthographic projection matrix. -template inline -Matrix44 ortho_RH(Vector3 min, Vector3 max) +template +inline Matrix44 ortho_RH(Vector3 min, Vector3 max) { return maths::ortho_RH(min.x, max.x, min.y, max.y, min.z, max.z); } -//============================================================================// +//============================================================================== /// Create an orthonormal basis matrix given the y axis. -template inline -Matrix33 basis_from_y(Vector3 yAxis) +template +inline Matrix33 basis_from_y(Vector3 yAxis) { - Vector3 zAxis; - - const Vector3 tanX = maths::cross(yAxis, Vector3(1, 0, 0)); - const Vector3 tanY = maths::cross(yAxis, Vector3(0, 1, 0)); - const Vector3 tanZ = maths::cross(yAxis, Vector3(0, 0, 1)); + Vector tanX = maths::cross(yAxis, Vector3(1, 0, 0)); + Vector tanY = maths::cross(yAxis, Vector3(0, 1, 0)); + Vector tanZ = maths::cross(yAxis, Vector3(0, 0, 1)); - const float lenX = maths::length_squared(tanX); - const float lenY = maths::length_squared(tanY); - const float lenZ = maths::length_squared(tanZ); + float lenX = maths::length_squared(tanX); + float lenY = maths::length_squared(tanY); + float lenZ = maths::length_squared(tanZ); + Vector3 zAxis; if (lenX >= lenY && lenX >= lenZ) zAxis = maths::normalize(tanX); else if (lenY >= lenZ) zAxis = maths::normalize(tanY); else zAxis = maths::normalize(tanZ); - const Vector3 xAxis = maths::cross(yAxis, zAxis); + Vector3 xAxis = maths::cross(yAxis, zAxis); - return Matrix33 ( xAxis, yAxis, zAxis ); + return { xAxis, yAxis, zAxis }; } /// Create an orthonormal basis matrix given the z axis. -template inline -Matrix33 basis_from_z(Vector3 zAxis) +template +inline Matrix33 basis_from_z(Vector3 zAxis) { - Vector3 yAxis; - - const Vector3 tanX = maths::cross(zAxis, Vector3(1, 0, 0)); - const Vector3 tanY = maths::cross(zAxis, Vector3(0, 1, 0)); - const Vector3 tanZ = maths::cross(zAxis, Vector3(0, 0, 1)); + Vector tanX = maths::cross(zAxis, Vector3(1, 0, 0)); + Vector tanY = maths::cross(zAxis, Vector3(0, 1, 0)); + Vector tanZ = maths::cross(zAxis, Vector3(0, 0, 1)); - const float lenX = maths::length_squared(tanX); - const float lenY = maths::length_squared(tanY); - const float lenZ = maths::length_squared(tanZ); + float lenX = maths::length_squared(tanX); + float lenY = maths::length_squared(tanY); + float lenZ = maths::length_squared(tanZ); + Vector3 yAxis; if (lenX >= lenY && lenX >= lenZ) yAxis = maths::normalize(tanX); else if (lenY >= lenZ) yAxis = maths::normalize(tanY); else yAxis = maths::normalize(tanZ); - const Vector3 xAxis = maths::cross(zAxis, yAxis); + Vector3 xAxis = maths::cross(zAxis, yAxis); - return Matrix33 ( xAxis, yAxis, zAxis ); + return { xAxis, yAxis, zAxis }; } -//============================================================================// - -} // namespace sq::maths +} // namespace sq::maths ####################################################### diff --git a/include/sqee/maths/Matrices.hpp b/include/sqee/maths/Matrices.hpp index ce1a512a..70e5fe44 100644 --- a/include/sqee/maths/Matrices.hpp +++ b/include/sqee/maths/Matrices.hpp @@ -6,228 +6,215 @@ #include #include -#include - -namespace sq { namespace maths { - -//============================================================================// +namespace sq::maths { //######################################################## -template struct Matrix {}; +template struct Matrix; template using Matrix33 = Matrix<3, 3, T>; template using Matrix34 = Matrix<3, 4, T>; template using Matrix44 = Matrix<4, 4, T>; -//============================================================================// +/// Concept that matches any kind of matrix. +template +concept AnyMatrix = requires (MatrixWHT m) +{ + [](Matrix&){}(m); +}; + +//============================================================================== template struct Matrix<3, 3, T> { static_assert(std::is_floating_point_v); - // Column Type Alias using Column = Vector<3, T>; - // Default Constructor (Identity) - constexpr Matrix() : data { 1,0,0, 0,1,0, 0,0,1 } {} + Column columns[3]; - // Uninitialised Constructor - Matrix(std::nullptr_t) {} + constexpr Matrix() : columns { {1,0,0}, {0,1,0}, {0,0,1} } {} + constexpr Matrix(Column a, Column b, Column c) : columns { a, b, c } {} + + constexpr explicit Matrix(T s) : columns { {s,0,0}, {0,s,0}, {0,0,s} } {} - // Copy Constructor and Assignment constexpr Matrix(const Matrix& m) = default; constexpr Matrix& operator=(const Matrix& m) = default; - // Scalar and Vector Constructors - constexpr explicit Matrix(T s) : data { s,0,0, 0,s,0, 0,0,s } {} - constexpr explicit Matrix(Column a, Column b, Column c) : columns { a, b, c } {} + /// Construct without initialisation. + Matrix(std::nullptr_t) {} + + /// Construct from a matrix of a different scalar type. + template + constexpr explicit Matrix(Matrix33 m) : columns { Column(m[0]), Column(m[1]), Column(m[2]) } {} - // Matrix Resize Constructors constexpr explicit Matrix(Matrix34 m) : columns { Column(m[0]), Column(m[1]), Column(m[2]) } {} constexpr explicit Matrix(Matrix44 m) : columns { Column(m[0]), Column(m[1]), Column(m[2]) } {} - // Column Access Operators constexpr Column& operator[](int index) { return columns[index]; } constexpr const Column& operator[](int index) const { return columns[index]; } - - union { T data[3*3]; Column columns[3]; }; }; -//============================================================================// +template Matrix(Vector3, Vector3, Vector3) -> Matrix<3, 3, T>; + +//============================================================================== template struct Matrix<3, 4, T> { static_assert(std::is_floating_point_v); - // Column Type Alias using Column = Vector<4, T>; - // Default Constructor (Identity) - constexpr Matrix() : data { 1,0,0,0, 0,1,0,0, 0,0,1,0 } {} + Column columns[3]; - // Uninitialised Constructor - Matrix(std::nullptr_t) {} + constexpr Matrix() : columns { {1,0,0,0}, {0,1,0,0}, {0,0,1,0} } {} + constexpr Matrix(Column a, Column b, Column c) : columns { a, b, c } {} + + constexpr explicit Matrix(T s) : columns { {s,0,0,0}, {0,s,0,0}, {0,0,s,0} } {} - // Copy Constructor and Assignment constexpr Matrix(const Matrix& m) = default; constexpr Matrix& operator=(const Matrix& m) = default; - // Scalar and Vector Constructors - constexpr explicit Matrix(T s) : data { s,0,0,0, 0,s,0,0, 0,0,s,0 } {} - constexpr explicit Matrix(Column a, Column b, Column c) : columns { a, b, c } {} + /// Construct without initialisation. + Matrix(std::nullptr_t) {} + + /// Construct from a matrix of a different scalar type. + template + constexpr explicit Matrix(Matrix34 m) : columns { Column(m[0]), Column(m[1]), Column(m[2]) } {} - // Matrix Resize Constructors constexpr explicit Matrix(Matrix33 m) : columns { Column(m[0], 0), Column(m[1], 0), Column(m[2], 0) } {} constexpr explicit Matrix(Matrix44 m) : columns { m[0], m[1], m[2] } {} - // Column Access Operators constexpr Column& operator[](int index) { return columns[index]; } constexpr const Column& operator[](int index) const { return columns[index]; } - - union { T data[3*4]; Column columns[3]; }; }; -//============================================================================// +template Matrix(Vector4, Vector4, Vector4) -> Matrix<3, 4, T>; + +//============================================================================== template struct Matrix<4, 4, T> { static_assert(std::is_floating_point_v); - // Column Type Alias using Column = Vector<4, T>; - // Default Constructor (Identity) - constexpr Matrix() : data { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 } {} + Column columns[4]; - // Uninitialised Constructor - Matrix(std::nullptr_t) {} + constexpr Matrix() : columns { {1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1} } {} + constexpr Matrix(Column a, Column b, Column c, Column d) : columns { a, b, c, d } {} + + constexpr explicit Matrix(T s) : columns { {s,0,0,0}, {0,s,0,0}, {0,0,s,0}, {0,0,0,s} } {} - // Copy Constructor and Assignment constexpr Matrix(const Matrix& m) = default; constexpr Matrix& operator=(const Matrix& m) = default; - // Scalar and Vector Constructors - constexpr explicit Matrix(T s) : data { s,0,0,0, 0,s,0,0, 0,0,s,0, 0,0,0,s } {} - constexpr explicit Matrix(Column a, Column b, Column c, Column d) : columns { a, b, c, d } {} + /// Construct without initialisation. + Matrix(std::nullptr_t) {} + + /// Construct from a matrix of a different scalar type. + template + constexpr explicit Matrix(Matrix44 m) : columns { Column(m[0]), Column(m[1]), Column(m[2]), Column(m[3]) } {} - // Matrix Resize Constructors - constexpr explicit Matrix(Matrix33 m) : columns { Column(m[0], 0), Column(m[1], 0), Column(m[2], 0), Column(0,0,0,1) } {} - constexpr explicit Matrix(Matrix34 m) : columns { m[0], m[1], m[2], Column(0,0,0,1) } {} + constexpr explicit Matrix(Matrix33 m) : columns { Column(m[0], 0), Column(m[1], 0), Column(m[2], 0), {0,0,0,1} } {} + constexpr explicit Matrix(Matrix34 m) : columns { m[0], m[1], m[2], {0,0,0,1} } {} - // Column Access Operators constexpr Column& operator[](int index) { return columns[index]; } constexpr const Column& operator[](int index) const { return columns[index]; } - - union { T data[4*4]; Column columns[4]; }; }; -//============================================================================// +template Matrix(Vector4, Vector4, Vector4, Vector4) -> Matrix<4, 4, T>; -// equality, inequality (Matrix, Matrix) ///// +//============================================================================== -template constexpr -bool operator==(Matrix a, Matrix b) +template +constexpr bool operator==(Matrix a, Matrix b) { for (int i = 0; i < W; ++i) for (int j = 0; j < H; ++j) - if (a[i][j] != b[i][j]) - return false; + if (a[i][j] != b[i][j]) return false; return true; } -template constexpr -bool operator!=(Matrix a, Matrix b) -{ - for (int i = 0; i < W; ++i) - for (int j = 0; j < H; ++j) - if (a[i][j] != b[i][j]) - return true; - return false; -} - -//============================================================================// +//============================================================================== -// Multiplication (Matrix, Matrix) ///// - -template constexpr -Matrix33 operator*(Matrix33 a, Matrix33 b) +template +constexpr Matrix33 operator*(Matrix33 a, Matrix33 b) { - Vector3 colA = a[0]*b[0][0] + a[1]*b[0][1] + a[2]*b[0][2]; - Vector3 colB = a[0]*b[1][0] + a[1]*b[1][1] + a[2]*b[1][2]; - Vector3 colC = a[0]*b[2][0] + a[1]*b[2][1] + a[2]*b[2][2]; - return Matrix33 ( colA, colB, colC ); + Vector colA = a[0] * b[0][0] + a[1] * b[0][1] + a[2] * b[0][2]; + Vector colB = a[0] * b[1][0] + a[1] * b[1][1] + a[2] * b[1][2]; + Vector colC = a[0] * b[2][0] + a[1] * b[2][1] + a[2] * b[2][2]; + return { colA, colB, colC }; } -template constexpr -Matrix44 operator*(Matrix44 a, Matrix44 b) +template +constexpr Matrix44 operator*(Matrix44 a, Matrix44 b) { - Vector4 colA = a[0]*b[0][0] + a[1]*b[0][1] + a[2]*b[0][2] + a[3]*b[0][3]; - Vector4 colB = a[0]*b[1][0] + a[1]*b[1][1] + a[2]*b[1][2] + a[3]*b[1][3]; - Vector4 colC = a[0]*b[2][0] + a[1]*b[2][1] + a[2]*b[2][2] + a[3]*b[2][3]; - Vector4 colD = a[0]*b[3][0] + a[1]*b[3][1] + a[2]*b[3][2] + a[3]*b[3][3]; - return Matrix44 ( colA, colB, colC, colD ); + Vector colA = a[0] * b[0][0] + a[1] * b[0][1] + a[2] * b[0][2] + a[3] * b[0][3]; + Vector colB = a[0] * b[1][0] + a[1] * b[1][1] + a[2] * b[1][2] + a[3] * b[1][3]; + Vector colC = a[0] * b[2][0] + a[1] * b[2][1] + a[2] * b[2][2] + a[3] * b[2][3]; + Vector colD = a[0] * b[3][0] + a[1] * b[3][1] + a[2] * b[3][2] + a[3] * b[3][3]; + return { colA, colB, colC, colD }; } -//============================================================================// +//============================================================================== -// Multiplication (Matrix, Vector) ///// - -template constexpr -Vector3 operator*(Matrix33 m, Vector3 v) +template +constexpr Vector3 operator*(Matrix33 m, Vector3 v) { - T x = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2]; - T y = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2]; - T z = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2]; - return Vector3 { x, y, z }; + T x = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2]; + T y = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2]; + T z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]; + return { x, y, z }; } -template constexpr -Vector4 operator*(Matrix44 m, Vector4 v) +template +constexpr Vector4 operator*(Matrix44 m, Vector4 v) { - T x = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3]; - T y = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3]; - T z = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3]; - T w = m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3]; - return Vector4 { x, y, z, w }; + T x = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3]; + T y = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3]; + T z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3]; + T w = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]; + return { x, y, z, w }; } -//============================================================================// +//============================================================================== -/// Compute the transpose of a Matrix33. -template constexpr -Matrix33 transpose(Matrix33 m) +/// Transpose a 3x3 Matrix. +template +constexpr Matrix33 transpose(Matrix33 m) { - Vector3 colA { m[0][0], m[1][0], m[2][0] }; - Vector3 colB { m[0][1], m[1][1], m[2][1] }; - Vector3 colC { m[0][2], m[1][2], m[2][2] }; - return Matrix33 ( colA, colB, colC ); + Vector colA { m[0][0], m[1][0], m[2][0] }; + Vector colB { m[0][1], m[1][1], m[2][1] }; + Vector colC { m[0][2], m[1][2], m[2][2] }; + return { colA, colB, colC }; } -/// Compute the transpose of a Matrix44. -template constexpr -Matrix44 transpose(Matrix44 m) +/// Transpose a 4x4 Matrix. +template +constexpr Matrix44 transpose(Matrix44 m) { - Vector4 colA { m[0][0], m[1][0], m[2][0], m[3][0] }; - Vector4 colB { m[0][1], m[1][1], m[2][1], m[3][1] }; - Vector4 colC { m[0][2], m[1][2], m[2][2], m[3][2] }; - Vector4 colD { m[0][3], m[1][3], m[2][3], m[3][3] }; - return Matrix44 ( colA, colB, colC, colD ); + Vector colA { m[0][0], m[1][0], m[2][0], m[3][0] }; + Vector colB { m[0][1], m[1][1], m[2][1], m[3][1] }; + Vector colC { m[0][2], m[1][2], m[2][2], m[3][2] }; + Vector colD { m[0][3], m[1][3], m[2][3], m[3][3] }; + return { colA, colB, colC, colD }; } -//============================================================================// +//============================================================================== -/// Compute the determinant of a Matrix33. -template inline -T determinant(Matrix33 m) +/// Compute the determinant of a 3x3 Matrix. +template +inline T determinant(Matrix33 m) { T valueA = m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); T valueB = m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); T valueC = m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + return valueA - valueB + valueC; } -/// Compute the determinant of a Matrix44. -template inline -T determinant(Matrix44 m) +/// Compute the determinant of a 4x4 Matrix. +template +inline T determinant(Matrix44 m) { T fac0 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; T fac1 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; @@ -241,14 +228,14 @@ T determinant(Matrix44 m) T ceZ = +(m[1][0] * fac1 - m[1][1] * fac3 + m[1][3] * fac5); T ceW = -(m[1][0] * fac2 - m[1][1] * fac4 + m[1][2] * fac5); - return maths::dot(m[0], Vector4(ceX, ceY, ceZ, ceW)); + return maths::dot(m[0], Vector(ceX, ceY, ceZ, ceW)); } -//============================================================================// +//============================================================================== -/// Compute the inverse of a Matrix33. -template inline -Matrix33 inverse(Matrix33 m) +/// Compute the inverse of a 3x3 Matrix. +template +inline Matrix33 inverse(Matrix33 m) { T ax = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]); T ay = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]); @@ -261,15 +248,17 @@ Matrix33 inverse(Matrix33 m) T cz = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]); T invDet = T(1.0) / maths::determinant(m); - auto colA = Vector3(ax, ay, az) * invDet; - auto colB = Vector3(bx, by, bz) * invDet; - auto colC = Vector3(cx, cy, cz) * invDet; - return Matrix33 ( colA, colB, colC ); + + Vector colA = Vector(ax, ay, az) * invDet; + Vector colB = Vector(bx, by, bz) * invDet; + Vector colC = Vector(cx, cy, cz) * invDet; + + return { colA, colB, colC }; } -/// Compute the inverse of a Matrix44. -template inline -Matrix44 inverse(Matrix44 m) +/// Compute the inverse of a 4x4 Matrix. +template +inline Matrix44 inverse(Matrix44 m) { T coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; T coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; @@ -293,147 +282,113 @@ Matrix44 inverse(Matrix44 m) T coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; T coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; - Vector4 fac0 { coef00, coef00, coef02, coef03 }; - Vector4 fac1 { coef04, coef04, coef06, coef07 }; - Vector4 fac2 { coef08, coef08, coef10, coef11 }; - Vector4 fac3 { coef12, coef12, coef14, coef15 }; - Vector4 fac4 { coef16, coef16, coef18, coef19 }; - Vector4 fac5 { coef20, coef20, coef22, coef23 }; - - Vector4 vec0 { m[1][0], m[0][0], m[0][0], m[0][0] }; - Vector4 vec1 { m[1][1], m[0][1], m[0][1], m[0][1] }; - Vector4 vec2 { m[1][2], m[0][2], m[0][2], m[0][2] }; - Vector4 vec3 { m[1][3], m[0][3], m[0][3], m[0][3] }; - - Vector4 invA = vec1 * fac0 - vec2 * fac1 + vec3 * fac2; - Vector4 invB = vec0 * fac0 - vec2 * fac3 + vec3 * fac4; - Vector4 invC = vec0 * fac1 - vec1 * fac3 + vec3 * fac5; - Vector4 invD = vec0 * fac2 - vec1 * fac4 + vec2 * fac5; - - invA = invA * Vector4(+1.0, -1.0, +1.0, -1.0); - invB = invB * Vector4(-1.0, +1.0, -1.0, +1.0); - invC = invC * Vector4(+1.0, -1.0, +1.0, -1.0); - invD = invD * Vector4(-1.0, +1.0, -1.0, +1.0); - - Vector4 repA { m[0][0], m[0][1], m[0][2], m[0][3] }; - Vector4 repB { invA[0], invB[0], invC[0], invD[0] }; - T r = T(1.0) / maths::dot(repA, repB); + Vector fac0 { coef00, coef00, coef02, coef03 }; + Vector fac1 { coef04, coef04, coef06, coef07 }; + Vector fac2 { coef08, coef08, coef10, coef11 }; + Vector fac3 { coef12, coef12, coef14, coef15 }; + Vector fac4 { coef16, coef16, coef18, coef19 }; + Vector fac5 { coef20, coef20, coef22, coef23 }; - return Matrix44 ( invA*r, invB*r, invC*r, invD*r ); -} + Vector vec0 { m[1][0], m[0][0], m[0][0], m[0][0] }; + Vector vec1 { m[1][1], m[0][1], m[0][1], m[0][1] }; + Vector vec2 { m[1][2], m[0][2], m[0][2], m[0][2] }; + Vector vec3 { m[1][3], m[0][3], m[0][3], m[0][3] }; -//============================================================================// + Vector invA = vec1 * fac0 - vec2 * fac1 + vec3 * fac2; + Vector invB = vec0 * fac0 - vec2 * fac3 + vec3 * fac4; + Vector invC = vec0 * fac1 - vec1 * fac3 + vec3 * fac5; + Vector invD = vec0 * fac2 - vec1 * fac4 + vec2 * fac5; -/// Compute the inverse of an affine Matrix44. -template inline -Matrix44 affine_inverse(Matrix44 m) -{ - Matrix33 inv33 = maths::inverse(Matrix33(m)); + invA = invA * Vector4(+1, -1, +1, -1); + invB = invB * Vector4(-1, +1, -1, +1); + invC = invC * Vector4(+1, -1, +1, -1); + invD = invD * Vector4(-1, +1, -1, +1); - Vector4 colA { inv33[0], T(0.0) }; - Vector4 colB { inv33[1], T(0.0) }; - Vector4 colC { inv33[2], T(0.0) }; + Vector repA { m[0][0], m[0][1], m[0][2], m[0][3] }; + Vector repB { invA[0], invB[0], invC[0], invD[0] }; - Vector4 colD { -(inv33 * Vector3(m[3])), T(1.0) }; + T r = T(1.0) / maths::dot(repA, repB); - return Matrix44 ( colA, colB, colC, colD ); + return { invA*r, invB*r, invC*r, invD*r }; } -//============================================================================// +//============================================================================== -/// Compute the normal matrix of a model view matrix. -template inline -Matrix33 normal_matrix(Matrix44 modelView) +/// Compute the inverse of an affine transform Matrix. +template +inline Matrix44 affine_inverse(Matrix44 m) { - return maths::transpose(maths::inverse(Matrix33(modelView))); -} + Matrix inv33 = maths::inverse(Matrix33(m)); -//============================================================================// + Vector colA { inv33[0], T(0.0) }; + Vector colB { inv33[1], T(0.0) }; + Vector colC { inv33[2], T(0.0) }; + Vector colD { -(inv33 * Vector3(m[3])), T(1.0) }; -} // namespace maths + return { colA, colB, colC, colD }; +} -template -constexpr const char* type_to_string(maths::Matrix) +/// Compute the normal matrix of a model view matrix. +template +inline Matrix33 normal_matrix(Matrix44 modelView) { - if constexpr (W == 3 && H == 3 && std::is_same_v) return "Mat3F"; - if constexpr (W == 3 && H == 4 && std::is_same_v) return "Mat34F"; - if constexpr (W == 4 && H == 4 && std::is_same_v) return "Mat4F"; - return "Matrix"; + return maths::transpose(maths::inverse(Matrix33(modelView))); } -//============================================================================// +} // namespace sq::maths ####################################################### -namespace detail { +#include -template -struct MatrixTraits : std::false_type {}; - -template -struct MatrixTraits : MatrixTraits {}; +#include template -struct MatrixTraits> : std::true_type +struct fmt::formatter> { - static constexpr int width = W; - static constexpr int height = H; - using type = T; -}; - -template -constexpr bool is_matrix_v = MatrixTraits::value; - -template -constexpr int matrix_width_v = MatrixTraits::width; + fmt::formatter base; -template -constexpr int matrix_height_v = MatrixTraits::height; - -template -using matrix_type_t = typename MatrixTraits::type; - -}} // namespace sq::detail - -//============================================================================// + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } -template -struct fmt::formatter> : fmt::formatter -{ template - auto format(const sq::maths::Matrix& mat, FormatContext& ctx) + FormatContext::iterator format(const sq::maths::Matrix& mat, FormatContext& ctx) const { - // this func does support W/H of 2 in case I ever need 2D matrices - fmt::format_to(ctx.out(), "{}((", sq::type_to_string(sq::maths::Matrix())); - formatter::format(mat[0][0], ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(mat[0][1], ctx); - if constexpr (H >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (H >= 3) formatter::format(mat[0][2], ctx); - if constexpr (H == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (H == 4) formatter::format(mat[0][3], ctx); - fmt::format_to(ctx.out(), "), ("); - formatter::format(mat[1][0], ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(mat[1][1], ctx); - if constexpr (H >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (H >= 3) formatter::format(mat[1][2], ctx); - if constexpr (H == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (H == 4) formatter::format(mat[1][3], ctx); - if constexpr (W >= 3) fmt::format_to(ctx.out(), "), ("); - if constexpr (W >= 3) formatter::format(mat[2][0], ctx); - if constexpr (W >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (W >= 3) formatter::format(mat[2][1], ctx); - if constexpr (W >= 3 && H >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (W >= 3 && H >= 3) formatter::format(mat[2][2], ctx); - if constexpr (W >= 3 && H == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (W >= 3 && H == 4) formatter::format(mat[2][3], ctx); - if constexpr (W == 4) fmt::format_to(ctx.out(), "), ("); - if constexpr (W == 4) formatter::format(mat[3][0], ctx); - if constexpr (W == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (W == 4) formatter::format(mat[3][1], ctx); - if constexpr (W == 4 && H >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (W == 4 && H >= 3) formatter::format(mat[3][2], ctx); - if constexpr (W == 4 && H == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (W == 4 && H == 4) formatter::format(mat[3][3], ctx); - return fmt::format_to(ctx.out(), "))"); + // note that this does support W/H of 2 in case I ever need 2D matrices + ctx.advance_to(fmt::detail::write(ctx.out(), sq::type_name_v>.c_str())); + ctx.advance_to(fmt::detail::write(ctx.out(), "((")); + ctx.advance_to(base.format(mat[0][0], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(mat[0][1], ctx)); + if constexpr (H >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (H >= 3) ctx.advance_to(base.format(mat[0][2], ctx)); + if constexpr (H == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (H == 4) ctx.advance_to(base.format(mat[0][3], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), "), (")); + ctx.advance_to(base.format(mat[1][0], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(mat[1][1], ctx)); + if constexpr (H >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (H >= 3) ctx.advance_to(base.format(mat[1][2], ctx)); + if constexpr (H == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (H == 4) ctx.advance_to(base.format(mat[1][3], ctx)); + if constexpr (W >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), "), (")); + if constexpr (W >= 3) ctx.advance_to(base.format(mat[2][0], ctx)); + if constexpr (W >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W >= 3) ctx.advance_to(base.format(mat[2][1], ctx)); + if constexpr (W >= 3 && H >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W >= 3 && H >= 3) ctx.advance_to(base.format(mat[2][2], ctx)); + if constexpr (W >= 3 && H == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W >= 3 && H == 4) ctx.advance_to(base.format(mat[2][3], ctx)); + if constexpr (W == 4) ctx.advance_to(fmt::detail::write(ctx.out(), "), (")); + if constexpr (W == 4) ctx.advance_to(base.format(mat[3][0], ctx)); + if constexpr (W == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W == 4) ctx.advance_to(base.format(mat[3][1], ctx)); + if constexpr (W == 4 && H >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W == 4 && H >= 3) ctx.advance_to(base.format(mat[3][2], ctx)); + if constexpr (W == 4 && H == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (W == 4 && H == 4) ctx.advance_to(base.format(mat[3][3], ctx)); + return fmt::detail::write(ctx.out(), "))"); } }; diff --git a/include/sqee/maths/Quaternion.hpp b/include/sqee/maths/Quaternion.hpp index 282cde37..599181a6 100644 --- a/include/sqee/maths/Quaternion.hpp +++ b/include/sqee/maths/Quaternion.hpp @@ -7,34 +7,45 @@ #include #include -#include +namespace sq::maths { //######################################################## + +template struct Quaternion; -namespace sq { namespace maths { +/// Concept that matches any kind of quaternion. +template +concept AnyQuaternion = requires (QuaternionT quat) +{ + [](Quaternion&){}(quat); +}; -//============================================================================// +//============================================================================== template struct Quaternion { static_assert(std::is_floating_point_v); - // Default and Value Constructor - constexpr Quaternion() : data { T(0), T(0), T(0), T(1) } {} - constexpr Quaternion(T x, T y, T z, T w) : data { x, y, z, w } {} - - // Uninitialised Constructor - Quaternion(std::nullptr_t) {} + T x, y, z, w; +\ + constexpr Quaternion() : x(0), y(0), z(0), w(1) {} + constexpr Quaternion(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} - // Copy Constructor and Assignment constexpr Quaternion(const Quaternion& q) = default; constexpr Quaternion& operator=(const Quaternion& q) = default; - /// Construct a quaternion from an XYZ euler rotation. + /// Construct without initialisation. + Quaternion(std::nullptr_t) {} + + /// Construct from a quaternion of a different scalar type. + template + constexpr explicit Quaternion(Quaternion q) : Quaternion(T(q.x), T(q.y), T(q.z), T(q.w)) {} + + /// Construct from an XYZ euler rotation. inline explicit Quaternion(T rx, T ry, T rz) { - Vector3 halfrads = maths::radians(Vector3(rx, ry, rz)) * T(0.5); + Vector halfRads = maths::radians(Vector(rx, ry, rz)) * T(0.5); - Vector3 s = maths::sin(halfrads); - Vector3 c = maths::cos(halfrads); + Vector s = maths::sin(halfRads); + Vector c = maths::cos(halfRads); x = (s.x * c.y * c.z) - (c.x * s.y * s.z); y = (c.x * s.y * c.z) + (s.x * c.y * s.z); @@ -42,7 +53,7 @@ template struct Quaternion w = (c.x * c.y * c.z) + (s.x * s.y * s.z); } - /// Construct a quaternion from a 3x3 rotation matrix. + /// Construct from a 3x3 rotation matrix. inline explicit Quaternion(const Matrix33& m) { T biggest = m[0][0] + m[1][1] + m[2][2]; int index = 0; // w @@ -59,161 +70,152 @@ template struct Quaternion if (index == 3) { x = (m[2][0] + m[0][2]) * mul; y = (m[1][2] + m[2][1]) * mul; z = value; w = (m[0][1] - m[1][0]) * mul; } } - /// Convert a quaternion to a 3x3 rotation matrix. + /// Construct from a 4x4 rotation matrix. + inline explicit Quaternion(const Matrix44& m) : Quaternion(Matrix33(m)) {} + + /// Convert to a 3x3 rotation matrix. constexpr explicit operator Matrix33() const { - Vector3 colA { T(1) - T(2) * (y*y + z*z), T(2) * (x*y + w*z), T(2) * (x*z - w*y) }; - Vector3 colB { T(2) * (x*y - w*z), T(1) - T(2) * (x*x + z*z), T(2) * (y*z + w*x) }; - Vector3 colC { T(2) * (x*z + w*y), T(2) * (y*z - w*x), T(1) - T(2) * (x*x + y*y) }; - return Matrix33 ( colA, colB, colC ); - } + Vector colA { T(1) - T(2) * (y*y + z*z), T(2) * (x*y + w*z), T(2) * (x*z - w*y) }; + Vector colB { T(2) * (x*y - w*z), T(1) - T(2) * (x*x + z*z), T(2) * (y*z + w*x) }; + Vector colC { T(2) * (x*z + w*y), T(2) * (y*z - w*x), T(1) - T(2) * (x*x + y*y) }; - /// Construct a quaternion from a 4x4 rotation matrix. - inline explicit Quaternion(const Matrix44& m) : Quaternion(Matrix33(m)) {} + return { colA, colB, colC }; + } - /// Convert a quaternion to a 4x4 rotation matrix. + /// Convert to a 4x4 rotation matrix. constexpr explicit operator Matrix44() const { return Matrix44(Matrix33(*this)); } - /// Cast a quaternion to a Vector4. + /// Convert to a four component vector. constexpr explicit operator Vector4() const { return { x, y, z, w }; } - // Array Access Operators - constexpr T& operator[](int index) { return data[index]; } - constexpr const T& operator[](int index) const { return data[index]; } + constexpr const T& operator[](int index) const + { + if (std::is_constant_evaluated()) + { + if (index == 0) return x; + if (index == 1) return y; + if (index == 2) return z; + if (index == 3) return w; + } + return reinterpret_cast(this)[index]; + } + + constexpr T& operator[](int index) + { + return const_cast(static_cast(*this)[index]); + } - union { T data[4]; struct { T x, y, z, w; }; }; + const T* data() const { return reinterpret_cast(this); } + + T* data() { return reinterpret_cast(this); } }; -//============================================================================// +template Quaternion(T, T, T, T) -> Quaternion; -// equality, inequality (Quaternion, Quaternion) ///// +//============================================================================== -template constexpr -bool operator==(Quaternion a, Quaternion b) +template +constexpr bool operator==(Quaternion a, Quaternion b) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; } -template constexpr -bool operator!=(Quaternion a, Quaternion b) +template +constexpr Quaternion operator*(Quaternion q, T s) { - return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w; + return { q.x*s, q.y*s, q.z*s, q.w*s }; } -//============================================================================// - -// multiplication & division (Quaternion, Scalar) ///// - -template constexpr -Quaternion operator*(Quaternion q, T s) -{ return { q.x*s, q.y*s, q.z*s, q.w*s }; } - -template constexpr -Quaternion operator/(Quaternion q, T s) -{ return { q.x/s, q.y/s, q.z/s, q.w/s }; } - -//============================================================================// - -// multiplication (Quaternion, Quaternion) ///// +template +constexpr Quaternion operator/(Quaternion q, T s) +{ + return { q.x/s, q.y/s, q.z/s, q.w/s }; +} -template constexpr -Quaternion operator*(Quaternion a, Quaternion b) +template +constexpr Quaternion operator*(Quaternion a, Quaternion b) { T x = (a.w * b.x) + (a.x * b.w) + (a.y * b.z) - (a.z * b.y); T y = (a.w * b.y) - (a.x * b.z) + (a.y * b.w) + (a.z * b.x); T z = (a.w * b.z) + (a.x * b.y) - (a.y * b.x) + (a.z * b.w); T w = (a.w * b.w) - (a.x * b.x) - (a.y * b.y) - (a.z * b.z); - return Quaternion { x, y, z, w }; + return { x, y, z, w }; } -//============================================================================// - -// multiplication (Quaternion, Vector3) ///// - -template constexpr -Vector3 operator*(Quaternion q, Vector3 v) +template +constexpr Vector3 operator*(Quaternion q, Vector3 v) { - auto qv = maths::cross(Vector3(q.x, q.y, q.z), v); - auto qqv = maths::cross(Vector3(q.x, q.y, q.z), qv); + Vector qv = maths::cross(Vector(q.x, q.y, q.z), v); + Vector qqv = maths::cross(Vector(q.x, q.y, q.z), qv); return v + (qv * q.w + qqv) * T(2.0); } -//============================================================================// - -// unary operators (Quaternion) ///// - -template constexpr -Quaternion operator+(Quaternion q) -{ return { +q.x, +q.y, +q.z, +q.w }; } +template +constexpr Quaternion operator+(Quaternion q) +{ + return { +q.x, +q.y, +q.z, +q.w }; +} -template constexpr -Quaternion operator-(Quaternion q) -{ return { -q.x, -q.y, -q.z, -q.w }; } +template +constexpr Quaternion operator-(Quaternion q) +{ + return { -q.x, -q.y, -q.z, -q.w }; +} -//============================================================================// +//============================================================================== /// Compute the dot product of two quaternions. -template constexpr -T dot(Quaternion a, Quaternion b) +template +constexpr T dot(Quaternion a, Quaternion b) { - Vector4 vecA { a.x, a.y, a.z, a.w }; - Vector4 vecB { b.x, b.y, b.z, b.w }; + Vector vecA { a.x, a.y, a.z, a.w }; + Vector vecB { b.x, b.y, b.z, b.w }; return maths::dot(vecA, vecB); } -//============================================================================// - /// Compute the conjugate of a quaternion. -template constexpr -Quaternion conjugate(Quaternion quat) +template +constexpr Quaternion conjugate(Quaternion quat) { - return Quaternion { -quat.x, -quat.y, -quat.z, quat.w }; + return { -quat.x, -quat.y, -quat.z, quat.w }; } -//============================================================================// - /// Compute the inverse of a quaternion. -template constexpr -Quaternion inverse(Quaternion quat) +template +constexpr Quaternion inverse(Quaternion quat) { return maths::conjugate(quat) / maths::dot(quat, quat); } -//============================================================================// - /// Compute the length of a quaternion. -template inline -T length(Quaternion quat) +template +inline T length(Quaternion quat) { return std::sqrt(maths::dot(quat, quat)); } -//============================================================================// - -/// Compute the unit length quaternion. -template inline -Quaternion normalize(Quaternion quat) +/// Scale a quaternion to a length of one. +template +inline Quaternion normalize(Quaternion quat) { return quat * (T(1.0) / maths::length(quat)); } -//============================================================================// - /// Compute the angular difference between two quaternions. -template inline -T angular_difference(Quaternion a, Quaternion b) +template +inline T angular_difference(Quaternion a, Quaternion b) { Quaternion rot = maths::inverse(a) * b; - Vector3 vec = { rot.x, rot.y, rot.z }; - - return maths::cycles(T(2.0) * std::atan2(maths::length(vec), rot.w)); + T halfRads = std::atan2(maths::length(Vector(rot.x, rot.y, rot.z)), rot.w); + return maths::cycles(T(2.0) * halfRads); } -//============================================================================// +//============================================================================== /// Linearly interpolate between two quaternions. -template inline -Quaternion lerp(Quaternion a, Quaternion b, T factor) +template +inline Quaternion lerp(Quaternion a, Quaternion b, T factor) { T invFactor = T(1.0) - factor; T x = (a.x * invFactor) + (b.x * factor); @@ -221,15 +223,13 @@ Quaternion lerp(Quaternion a, Quaternion b, T factor) T z = (a.z * invFactor) + (b.z * factor); T w = (a.w * invFactor) + (b.w * factor); - // note that this result is not normalised - return Quaternion { x, y, z, w }; + // note that this is not normalised + return { x, y, z, w }; } -//============================================================================// - /// Spherically interpolate between two unit quaternions. -template inline -Quaternion slerp(Quaternion a, Quaternion b, T factor) +template +inline Quaternion slerp(Quaternion a, Quaternion b, T factor) { T cosine = maths::dot(a, b); T absCosine = std::abs(cosine); @@ -252,14 +252,12 @@ Quaternion slerp(Quaternion a, Quaternion b, T factor) T w = (a.w * factorA) + (b.w * factorB); // if a and b were normalised, this will be too - return Quaternion { x, y, z, w }; + return { x, y, z, w }; } -//============================================================================// - /// Lerp between two quaternions using the shorter path. -template inline -Quaternion lerp_shortest(Quaternion a, Quaternion b, T factor) +template +inline Quaternion lerp_shorter(Quaternion a, Quaternion b, T factor) { // don't go the long way around if (maths::dot(a, b) < T(0.0)) b = -b; @@ -267,22 +265,20 @@ Quaternion lerp_shortest(Quaternion a, Quaternion b, T factor) return maths::normalize(maths::lerp(a, b, factor)); } -//============================================================================// - /// Lerp between two quaternions in whichever direction is closest to the guide. -template inline -Quaternion lerp_guided(Quaternion a, Quaternion b, T factor, Quaternion guide) +template +inline Quaternion lerp_guided(Quaternion a, Quaternion b, T factor, Quaternion guide) { - Quaternion resultPos = maths::lerp(a, +b, factor); - Quaternion resultNeg = maths::lerp(a, -b, factor); + Quaternion resultPos = maths::lerp(a, +b, factor); + Quaternion resultNeg = maths::lerp(a, -b, factor); - Quaternion invGuide = maths::inverse(guide); + Quaternion invGuide = maths::inverse(guide); - Quaternion rotPos = resultPos * invGuide; - Quaternion rotNeg = resultNeg * invGuide; + Quaternion rotPos = resultPos * invGuide; + Quaternion rotNeg = resultNeg * invGuide; - T lengthPos = maths::length(Vector3(rotPos.x, rotPos.y, rotPos.z)); - T lengthNeg = maths::length(Vector3(rotNeg.x, rotNeg.y, rotNeg.z)); + T lengthPos = maths::length(Vector(rotPos.x, rotPos.y, rotPos.z)); + T lengthNeg = maths::length(Vector(rotNeg.x, rotNeg.y, rotNeg.z)); T diffPos = std::abs(std::atan2(lengthPos, rotPos.w)); T diffNeg = std::abs(std::atan2(lengthNeg, rotNeg.w)); @@ -290,58 +286,35 @@ Quaternion lerp_guided(Quaternion a, Quaternion b, T factor, Quaternion return maths::normalize(diffPos < diffNeg ? resultPos : resultNeg); } -//============================================================================// +} // namespace sq::maths ####################################################### -} // namespace maths +#include -template -constexpr const char* type_to_string(maths::Quaternion) -{ - if constexpr (std::is_same_v) return "QuatF"; - return "Quaternion"; -} - -//============================================================================// - -namespace detail { - -template -struct QuaternionTraits : std::false_type {}; - -template -struct QuaternionTraits : QuaternionTraits {}; +#include template -struct QuaternionTraits> : std::true_type +struct fmt::formatter> { - static constexpr bool value = true; - using type = T; -}; - -template -constexpr bool is_quaternion_v = QuaternionTraits::value; - -template -using quaternion_type_t = typename QuaternionTraits::type; + fmt::formatter base; -}} // namespace sq::detail - -//============================================================================// + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } -template -struct fmt::formatter> : fmt::formatter -{ template - auto format(const sq::maths::Quaternion& quat, FormatContext& ctx) + FormatContext::iterator format(const sq::maths::Quaternion& quat, FormatContext& ctx) const { - fmt::format_to(ctx.out(), "{}(", sq::type_to_string(sq::maths::Quaternion())); - formatter::format(quat.x, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(quat.y, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(quat.z, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(quat.w, ctx); - return fmt::format_to(ctx.out(), ")"); + ctx.advance_to(fmt::detail::write(ctx.out(), sq::type_name_v>.c_str())); + ctx.advance_to(fmt::detail::write(ctx.out(), '(')); + ctx.advance_to(base.format(quat.x, ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(quat.y, ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(quat.z, ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(quat.w, ctx)); + return fmt::detail::write(ctx.out(), ')'); } }; diff --git a/include/sqee/maths/Random.hpp b/include/sqee/maths/Random.hpp index 3397fd7e..6d9b555d 100644 --- a/include/sqee/maths/Random.hpp +++ b/include/sqee/maths/Random.hpp @@ -5,132 +5,109 @@ #include -#include - #include // IWYU pragma: export -namespace sq { namespace maths { +namespace sq::maths { //######################################################## -//============================================================================// +using RandNumGen = std::mt19937; /// Callable object for generating random values within a range. template struct RandomRange { - static_assert ( - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - detail::is_vector_v, "unsupported type" - ); - - constexpr RandomRange() : data { T(0), T(0) } {} + constexpr RandomRange() : min(T(0)), max(T(0)) {} constexpr RandomRange(T min, T max) : min(min), max(max) {} - template - T operator()(Generator& gen) const + T operator()(RandNumGen& gen) const requires std::integral { - if (min == max) - { - if constexpr (std::is_arithmetic_v) - gen.discard(1u); - - if constexpr (detail::is_vector_v) - gen.discard(detail::vector_size_v); - - return min; - } + if (min == max) { gen.discard(1); return min; } + return std::uniform_int_distribution(min, max)(gen); + }; - if constexpr (std::is_integral_v) - return std::uniform_int_distribution(min, max)(gen); - - if constexpr (std::is_floating_point_v) - return std::uniform_real_distribution(min, max)(gen); + T operator()(RandNumGen& gen) const requires std::floating_point + { + if (min == max) { gen.discard(1); return min; } + return std::uniform_real_distribution(min, max)(gen); + }; - if constexpr (detail::is_vector_v) + T operator()(RandNumGen& gen) const requires AnyVector + { + return [&](Vector result) { - T result(nullptr); - for (int i = 0; i < detail::vector_size_v; ++i) - result[i] = RandomRange>(min[i], max[i])(gen); + for (int i = 0; i < VecS; ++i) + result[i] = RandomRange(min[i], max[i])(gen); return result; } - } + (T(nullptr)); + }; constexpr bool operator==(const RandomRange& other) const - { return min == other.min && max == other.max; } - - constexpr bool operator!=(const RandomRange& other) const - { return min != other.min || max != other.max; } + { + return min == other.min && max == other.max; + } - union { T data[2]; struct { T min, max; }; }; + T min, max; }; -//============================================================================// +} // namespace sq::maths ####################################################### -} // namespace maths +#include -template -constexpr const char* type_to_string(maths::RandomRange) -{ - if constexpr (std::is_same_v) return "RandRangeInt16"; - if constexpr (std::is_same_v) return "RandRangeUInt16"; - if constexpr (std::is_same_v) return "RandRangeInt32"; - if constexpr (std::is_same_v) return "RandRangeUInt32"; - if constexpr (std::is_same_v) return "RandRangeFloat"; - if constexpr (std::is_same_v) return "RandRangeDouble"; - if constexpr (std::is_same_v>) return "RandRangeVec2I"; - if constexpr (std::is_same_v>) return "RandRangeVec3I"; - if constexpr (std::is_same_v>) return "RandRangeVec4I"; - if constexpr (std::is_same_v>) return "RandRangeVec2U"; - if constexpr (std::is_same_v>) return "RandRangeVec3U"; - if constexpr (std::is_same_v>) return "RandRangeVec4U"; - if constexpr (std::is_same_v>) return "RandRangeVec2F"; - if constexpr (std::is_same_v>) return "RandRangeVec3F"; - if constexpr (std::is_same_v>) return "RandRangeVec4F"; - return "RandomRange"; -} - -} // namespace sq - -//============================================================================// +#include template -struct fmt::formatter> : fmt::formatter +struct fmt::formatter> { + fmt::formatter base; + + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } + template - auto format(const sq::maths::RandomRange& range, FormatContext& ctx) + FormatContext::iterator format(const sq::maths::RandomRange& rr, FormatContext& ctx) const { - fmt::format_to(ctx.out(), "{}(", sq::type_to_string(sq::maths::RandomRange())); - formatter::format(range.min, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(range.max, ctx); - return fmt::format_to(ctx.out(), ")"); + ctx.advance_to(fmt::detail::write(ctx.out(), sq::type_name_v>.c_str())); + ctx.advance_to(fmt::detail::write(ctx.out(), '(')); + ctx.advance_to(base.format(rr.min, ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(rr.max, ctx)); + return fmt::detail::write(ctx.out(), ')'); } }; template -struct fmt::formatter>> : fmt::formatter +struct fmt::formatter>> { - using VectorST = sq::maths::Vector; + fmt::formatter base; + + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } template - auto format(const sq::maths::RandomRange& range, FormatContext& ctx) + FormatContext::iterator format(const sq::maths::RandomRange>& rr, FormatContext& ctx) const { - fmt::format_to(ctx.out(), "{}((", sq::type_to_string(sq::maths::RandomRange())); - formatter::format(range.min.x, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(range.min.y, ctx); - if constexpr (S >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (S >= 3) formatter::format(range.min.z, ctx); - if constexpr (S == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (S == 4) formatter::format(range.min.w, ctx); - fmt::format_to(ctx.out(), "), ("); - formatter::format(range.max.x, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(range.max.y, ctx); - if constexpr (S >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (S >= 3) formatter::format(range.max.z, ctx); - if constexpr (S == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (S == 4) formatter::format(range.max.w, ctx); - return fmt::format_to(ctx.out(), "))"); - } + ctx.advance_to(fmt::detail::write(ctx.out(), sq::type_name_v>>.c_str())); + ctx.advance_to(fmt::detail::write(ctx.out(), "((")); + ctx.advance_to(base.format(rr.min[0], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(rr.min[1], ctx)); + if constexpr (S >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S >= 3) ctx.advance_to(base.format(rr.min[2], ctx)); + if constexpr (S == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S == 4) ctx.advance_to(base.format(rr.min[3], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), "), (")); + ctx.advance_to(base.format(rr.max[0], ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(rr.max[1], ctx)); + if constexpr (S >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S >= 3) ctx.advance_to(base.format(rr.max[2], ctx)); + if constexpr (S == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S == 4) ctx.advance_to(base.format(rr.max[3], ctx)); + return fmt::detail::write(ctx.out(), "))"); + } }; diff --git a/include/sqee/maths/Scalar.hpp b/include/sqee/maths/Scalar.hpp index 08878e7b..0b2d8039 100644 --- a/include/sqee/maths/Scalar.hpp +++ b/include/sqee/maths/Scalar.hpp @@ -3,29 +3,26 @@ #pragma once -#include - #include +#include typedef unsigned char uchar; typedef unsigned int uint; -namespace sq::maths { - -//============================================================================// +namespace sq::maths { //######################################################## /// Constexpr version of std::abs. template constexpr T abs(T value) { - static_assert(std::is_arithmetic_v); + static_assert(std::is_signed_v); - if constexpr (std::is_floating_point_v) - if (value == T(0)) return T(0); + if (std::is_constant_evaluated()) + return value == T(0) ? T(0) : value < T(0) ? -value : value; - return value < T(0) ? -value : value; + return std::abs(value); } -//============================================================================// +//============================================================================== /// Minimum of two scalar arguments. template constexpr T min(T a, T b) @@ -35,40 +32,38 @@ template constexpr T min(T a, T b) return a < b ? a : b; } -/// Maximum of two scalar arguments. -template constexpr T max(T a, T b) +/// Minimum of three scalar arguments. +template constexpr T min(T a, T b, T c) { static_assert(std::is_arithmetic_v); - return a > b ? a : b; + return maths::min(maths::min(a, b), c); } -//============================================================================// - -/// Minimum of three scalar arguments. -template constexpr T min(T a, T b, T c) +/// Minimum of four scalar arguments. +template constexpr T min(T a, T b, T c, T d) { static_assert(std::is_arithmetic_v); - return maths::min(maths::min(a, b), c); + return maths::min(maths::min(maths::min(a, b), c), d); } -/// Maximum of three scalar arguments. -template constexpr T max(T a, T b, T c) +//============================================================================== + +/// Maximum of two scalar arguments. +template constexpr T max(T a, T b) { static_assert(std::is_arithmetic_v); - return maths::max(maths::max(a, b), c); + return a > b ? a : b; } -//============================================================================// - -/// Minimum of four scalar arguments. -template constexpr T min(T a, T b, T c, T d) +/// Maximum of three scalar arguments. +template constexpr T max(T a, T b, T c) { static_assert(std::is_arithmetic_v); - return maths::min(maths::min(maths::min(a, b), c), d); + return maths::max(maths::max(a, b), c); } /// Maximum of four scalar arguments. @@ -79,7 +74,7 @@ template constexpr T max(T a, T b, T c, T d) return maths::max(maths::max(maths::max(a, b), c), d); } -//============================================================================// +//============================================================================== /// Clamp a scalar value within a range, template constexpr T clamp(T value, T min, T max) @@ -89,17 +84,15 @@ template constexpr T clamp(T value, T min, T max) return maths::min(maths::max(value, min), max); } -//============================================================================// - /// Clamp a scalar value to an absolute magnitude, template constexpr T clamp_magnitude(T value, T magnitude) { - static_assert(std::is_arithmetic_v); + static_assert(std::is_signed_v); - return maths::clamp(value, -std::abs(magnitude), +std::abs(magnitude)); + return maths::clamp(value, -maths::abs(magnitude), +maths::abs(magnitude)); } -//============================================================================// +//============================================================================== /// Linearly interpolate between two scalars. template constexpr T mix(T a, T b, T factor) @@ -109,7 +102,16 @@ template constexpr T mix(T a, T b, T factor) return a * (T(1.0) - factor) + b * factor; } -//============================================================================// +/// Interpolate between two angles by the shortest path. +template inline T mix_radians(T a, T b, T factor) +{ + static_assert(std::is_floating_point_v); + + constexpr double pi = 3.14159265358979323846; + return (std::fmod(std::fmod(b - a, T(2.0 * pi)) + T(3.0 * pi), T(2.0 * pi)) - T(pi)) * factor; +} + +//============================================================================== /// Convert a scalar from cycles to radians. template constexpr T radians(T cycles) @@ -127,25 +129,4 @@ template constexpr T cycles(T radians) return radians * T(0.5 / 3.14159265358979323846); } -//============================================================================// - -/// Interpolate between two angles by the shortest path. -template constexpr T mix_radians(T a, T b, T factor) -{ - static_assert(std::is_floating_point_v); - - constexpr double pi = 3.14159265358979323846; - return (std::fmod(std::fmod(b - a, T(2.0 * pi)) + T(3.0 * pi), T(2.0 * pi)) - T(pi)) * factor; -} - -/*/// Interpolate between two angles by the shortest path. -template constexpr T mix_degrees(T a, T b, T factor) -{ - static_assert(std::is_floating_point_v); - - return (std::fmod(std::fmod(b - a, T(360.0)) + T(540.0), T(360.0)) - T(180.0)) * factor; -}*/ - -//============================================================================// - -} // namespace sq::maths +} // namespace sq::maths ####################################################### diff --git a/include/sqee/maths/Vectors.hpp b/include/sqee/maths/Vectors.hpp index d43cabfd..c3bd8d28 100644 --- a/include/sqee/maths/Vectors.hpp +++ b/include/sqee/maths/Vectors.hpp @@ -5,388 +5,414 @@ #include -#include - -namespace sq { namespace maths { +namespace sq::maths { //######################################################## -//============================================================================// - -template struct Vector {}; +template struct Vector; template using Vector2 = Vector<2, T>; template using Vector3 = Vector<3, T>; template using Vector4 = Vector<4, T>; -//============================================================================// +/// Concept that matches any kind of vector. +template +concept AnyVector = requires (VectorST vec) +{ + [](Vector&){}(vec); +}; + +//============================================================================== template struct Vector<2, T> { - constexpr Vector() : data { T(0), T(0) } {} - constexpr Vector(T x, T y) : data { x, y } {} + T x, y; - constexpr explicit Vector(T s) : Vector(s, s) {} + constexpr Vector() : x(0), y(0) {} + constexpr Vector(T x, T y) : x(x), y(y) {} - // Uninitialised Constructor - Vector(std::nullptr_t) {} + constexpr explicit Vector(T s) : Vector(s, s) {} - // Copy Constructor and Assignment constexpr Vector(const Vector& v) = default; constexpr Vector& operator=(const Vector& v) = default; - // Conversion Constructor - template explicit Vector(Vector2 v) : Vector(T(v.x), T(v.y)) {} + /// Construct without initialisation. + Vector(std::nullptr_t) {} + + /// Construct from a vector of a different scalar type. + template + constexpr explicit Vector(Vector2 v) : Vector(T(v.x), T(v.y)) {} - // Swizzle Constructors constexpr explicit Vector(Vector3 v) : Vector(v.x, v.y) {} constexpr explicit Vector(Vector4 v) : Vector(v.x, v.y) {} - // Array Access Operators - constexpr T& operator[](int index) { return data[index]; } - constexpr const T& operator[](int index) const { return data[index]; } + constexpr const T& operator[](int index) const + { + if (std::is_constant_evaluated()) + { + if (index == 0) return x; + if (index == 1) return y; + } + return reinterpret_cast(this)[index]; + } + + constexpr T& operator[](int index) + { + return const_cast(static_cast(*this)[index]); + } + + const T* data() const { return reinterpret_cast(this); } - union { T data[2]; struct { T x, y; }; struct { T r, g; }; }; + T* data() { return reinterpret_cast(this); } }; -//============================================================================// +template Vector(T, T) -> Vector<2, T>; + +//============================================================================== template struct Vector<3, T> { - constexpr Vector() : data { T(0), T(0), T(0) } {} - constexpr Vector(T x, T y, T z) : data { x, y, z } {} + T x, y, z; - constexpr explicit Vector(T s) : Vector(s, s, s) {} + constexpr Vector() : x(0), y(0), z(0) {} + constexpr Vector(T x, T y, T z) : x(x), y(y), z(z) {} - // Uninitialised Constructor - Vector(std::nullptr_t) {} + constexpr explicit Vector(T s) : Vector(s, s, s) {} - // Copy Constructor and Assignment constexpr Vector(const Vector& v) = default; constexpr Vector& operator=(const Vector& v) = default; - // Conversion Constructor - template explicit Vector(Vector3 v) : Vector(T(v.x), T(v.y), T(v.z)) {} + /// Construct without initialisation. + Vector(std::nullptr_t) {} + + /// Construct from a vector of a different scalar type. + template + constexpr explicit Vector(Vector3 v) : Vector(T(v.x), T(v.y), T(v.z)) {} - // Swizzle Constructors constexpr explicit Vector(Vector4 v) : Vector(v.x, v.y, v.z) {} constexpr explicit Vector(Vector2 xy, T z) : Vector(xy.x, xy.y, z) {} constexpr explicit Vector(T x, Vector2 yz) : Vector(x, yz.x, yz.y) {} - // Array Access Operators - constexpr T& operator[](int index) { return data[index]; } - constexpr const T& operator[](int index) const { return data[index]; } + constexpr const T& operator[](int index) const + { + if (std::is_constant_evaluated()) + { + if (index == 0) return x; + if (index == 1) return y; + if (index == 2) return z; + } + return reinterpret_cast(this)[index]; + } - union { T data[3]; struct { T x, y, z; }; struct { T r, g, b; }; }; + constexpr T& operator[](int index) + { + return const_cast(static_cast(*this)[index]); + } + + const T* data() const { return reinterpret_cast(this); } + + T* data() { return reinterpret_cast(this); } }; -//============================================================================// +template Vector(T, T, T) -> Vector<3, T>; +template Vector(Vector2, T) -> Vector<3, T>; +template Vector(T, Vector2) -> Vector<3, T>; + +//============================================================================== template struct Vector<4, T> { - constexpr Vector() : data { T(0), T(0), T(0), T(0) } {} - constexpr Vector(T x, T y, T z, T w) : data { x, y, z, w } {} + T x, y, z, w; - constexpr explicit Vector(T s) : Vector(s, s, s, s) {} + constexpr Vector() : x(0), y(0), z(0), w(0) {} + constexpr Vector(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} - // Uninitialised Constructor - Vector(std::nullptr_t) {} + constexpr explicit Vector(T s) : Vector(s, s, s, s) {} - // Copy Constructor and Assignment constexpr Vector(const Vector& v) = default; constexpr Vector& operator=(const Vector& v) = default; - // Conversion Constructor - template explicit Vector(Vector4 v) : Vector(T(v.x), T(v.y), T(v.z), T(v.w)) {} + /// Construct without initialisation. + Vector(std::nullptr_t) {} + + /// Construct from a vector of a different scalar type. + template + explicit Vector(Vector4 v) : Vector(T(v.x), T(v.y), T(v.z), T(v.w)) {} - // Swizzle Constructors constexpr explicit Vector(Vector2 xy, T z, T w) : Vector(xy.x, xy.y, z, w) {} constexpr explicit Vector(T x, Vector2 yz, T w) : Vector(x, yz.x, yz.y, w) {} constexpr explicit Vector(T x, T y, Vector2 zw) : Vector(x, y, zw.x, zw.y) {} constexpr explicit Vector(Vector3 xyz, T w) : Vector(xyz.x, xyz.y, xyz.z, w) {} constexpr explicit Vector(T x, Vector3 yzw) : Vector(x, yzw.x, yzw.y, yzw.z) {} - // Array Access Operators - constexpr T& operator[](int index) { return data[index]; } - constexpr const T& operator[](int index) const { return data[index]; } + constexpr const T& operator[](int index) const + { + if (std::is_constant_evaluated()) + { + if (index == 0) return x; + if (index == 1) return y; + if (index == 2) return z; + if (index == 3) return w; + } + return reinterpret_cast(this)[index]; + } - union { T data[4]; struct { T x, y, z, w; }; struct { T r, g, b, a; }; }; + constexpr T& operator[](int index) + { + return const_cast(static_cast(*this)[index]); + } + + const T* data() const { return reinterpret_cast(this); } + + T* data() { return reinterpret_cast(this); } }; -//============================================================================// +template Vector(T, T, T, T) -> Vector<4, T>; +template Vector(Vector2, T, T) -> Vector<4, T>; +template Vector(T, Vector2, T) -> Vector<4, T>; +template Vector(T, T, Vector2) -> Vector<4, T>; +template Vector(Vector3, T) -> Vector<4, T>; +template Vector(T, Vector3) -> Vector<4, T>; -// equality, inequality (Vector, Vector) ///// +//============================================================================== -template constexpr -bool operator==(Vector a, Vector b) +template +constexpr auto operator<=>(Vector a, Vector b) { for (int i = 0; i < S; ++i) - if (a[i] != b[i]) return false; - - return true; + if (auto cmp = a[i] <=> b[i]; cmp != 0) return cmp; + return T() <=> T(); } -template constexpr -bool operator!=(Vector a, Vector b) +template +constexpr bool operator==(Vector a, Vector b) { for (int i = 0; i < S; ++i) - if (a[i] != b[i]) return true; - - return false; + if (a[i] != b[i]) return false; + return true; } -//============================================================================// +//============================================================================== -// integral comparison (Vector, Vector) ///// - -template constexpr -bool operator<(Vector a, Vector b) +template +constexpr Vector operator+(Vector a, Vector b) { - static_assert(std::is_integral_v); - - for (int i = 0; i < S; ++i) - if (a[i] != b[i]) return a[i] < b[i]; - - return false; + for (int i = 0; i < S; ++i) a[i] += b[i]; + return a; +} +template +constexpr Vector& operator+=(Vector& a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] += b[i]; + return a; } -//============================================================================// - -// arithmetic binary operators (Vector, Vector) ///// - -//========================================================// - -template constexpr -Vector operator+(Vector a, Vector b) -{ for (int i=0; i constexpr -Vector& operator+=(Vector& a, Vector b) -{ for (int i=0; i constexpr -Vector operator-(Vector a, Vector b) -{ for (int i=0; i constexpr -Vector& operator-=(Vector& a, Vector b) -{ for (int i=0; i constexpr -Vector operator*(Vector a, Vector b) -{ for (int i=0; i constexpr -Vector& operator*=(Vector& a, Vector b) -{ for (int i=0; i constexpr -Vector operator/(Vector a, Vector b) -{ for (int i=0; i constexpr -Vector& operator/=(Vector& a, Vector b) -{ for (int i=0; i constexpr -Vector operator+(Vector v, T s) -{ for (int i=0; i constexpr -Vector& operator+=(Vector& v, T s) -{ for (int i=0; i constexpr -Vector operator-(Vector v, T s) -{ for (int i=0; i constexpr -Vector& operator-=(Vector& v, T s) -{ for (int i=0; i +constexpr Vector operator-(Vector a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] -= b[i]; + return a; +} +template +constexpr Vector& operator-=(Vector& a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] -= b[i]; + return a; +} -//--------------------------------------------------------// +template +constexpr Vector operator*(Vector a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] *= b[i]; + return a; +} +template +constexpr Vector& operator*=(Vector& a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] *= b[i]; + return a; +} -template constexpr -Vector operator*(Vector v, T s) -{ for (int i=0; i +constexpr Vector operator/(Vector a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] /= b[i]; + return a; +} +template +constexpr Vector& operator/=(Vector& a, Vector b) +{ + for (int i = 0; i < S; ++i) a[i] /= b[i]; + return a; +} -template constexpr -Vector& operator*=(Vector& v, T s) -{ for (int i=0; i +constexpr Vector operator+(Vector v, T s) +{ + for (int i = 0; i < S; ++i) v[i] += s; + return v; +} +template +constexpr Vector& operator+=(Vector& v, T s) +{ + for (int i = 0; i < S; ++i) v[i] += s; + return v; +} -template constexpr -Vector operator/(Vector v, T s) -{ for (int i=0; i +constexpr Vector operator-(Vector v, T s) +{ + for (int i = 0; i < S; ++i) v[i] -= s; + return v; +} +template +constexpr Vector& operator-=(Vector& v, T s) +{ + for (int i = 0; i < S; ++i) v[i] -= s; + return v; +} -template constexpr -Vector& operator/=(Vector& v, T s) -{ for (int i=0; i +constexpr Vector operator*(Vector v, T s) +{ + for (int i = 0; i < S; ++i) v[i] *= s; + return v; +} +template +constexpr Vector& operator*=(Vector& v, T s) +{ + for (int i = 0; i < S; ++i) v[i] *= s; + return v; +} -//============================================================================// +template +constexpr Vector operator/(Vector v, T s) +{ + for (int i = 0; i < S; ++i) v[i] /= s; + return v; +} +template +constexpr Vector& operator/=(Vector& v, T s) +{ + for (int i = 0; i < S; ++i) v[i] /= s; + return v; +} -// arithmetic unary operators (Vector) ///// +//============================================================================== -template constexpr -Vector operator+(Vector vec) +template +constexpr Vector operator+(Vector vec) { static_assert(std::is_signed_v); - return Vector() + vec; + for (int i = 0; i < S; ++i) vec[i] = +vec[i]; + return vec; } -template constexpr -Vector operator-(Vector vec) +template +constexpr Vector operator-(Vector vec) { static_assert(std::is_signed_v); - return Vector() - vec; -} - -//============================================================================// - -/// Component-wise a is less than b test. -template constexpr -bool all_less(Vector a, Vector b) -{ - for (int i = 0; i < S; ++i) if (a[i] >= b[i]) return false; - return true; + for (int i = 0; i < S; ++i) vec[i] = -vec[i]; + return vec; } -/// Component-wise a is greater than b test. -template constexpr -bool all_greater(Vector a, Vector b) -{ - for (int i = 0; i < S; ++i) if (a[i] <= b[i]) return false; - return true; -} +//============================================================================== -/// Component-wise a is less than or equal to b test. -template constexpr -bool all_less_equal(Vector a, Vector b) +/// Compute the component-wise absolute of a vector. +template +constexpr Vector abs(Vector vec) { - for (int i = 0; i < S; ++i) if (a[i] > b[i]) return false; - return true; -} + static_assert(std::is_signed_v); -/// Component-wise a is greater than or equal to b test. -template constexpr -bool all_greater_equal(Vector a, Vector b) -{ - for (int i = 0; i < S; ++i) if (a[i] < b[i]) return false; - return true; + for (int i = 0; i < S; ++i) vec[i] = maths::abs(vec[i]); + return vec; } -//============================================================================// - /// Compute the component-wise minimum of two vectors. -template constexpr -Vector min(Vector a, Vector b) +template +constexpr Vector min(Vector a, Vector b) { - for (int i = 0; i < S; ++i) - a[i] = maths::min(a[i], b[i]); - + for (int i = 0; i < S; ++i) a[i] = maths::min(a[i], b[i]); return a; } /// Compute the component-wise maximum of two vectors. -template constexpr -Vector max(Vector a, Vector b) +template +constexpr Vector max(Vector a, Vector b) { - for (int i = 0; i < S; ++i) - a[i] = maths::max(a[i], b[i]); - + for (int i = 0; i < S; ++i) a[i] = maths::max(a[i], b[i]); return a; } -//============================================================================// - /// Clamp a vector to within the specified range. -template constexpr -Vector clamp(Vector vec, Vector min, Vector max) +template +constexpr Vector clamp(Vector vec, Vector min, Vector max) { return maths::min(maths::max(vec, min), max); } -//============================================================================// +//============================================================================== /// Linearly interpolate between two vectors. -template constexpr -Vector mix(Vector a, Vector b, T factor) +template +constexpr Vector mix(Vector a, Vector b, T factor) { static_assert(std::is_floating_point_v); return a * (T(1.0) - factor) + b * factor; } -//============================================================================// - -/// Compute the component-wise sine of a vector. -template inline -Vector sin(Vector vec) +/// Interpolate between euler rotations component-wise. +template +constexpr Vector3 mix_radians(Vector3 a, Vector3 b, T factor) { static_assert(std::is_floating_point_v); - for (int i = 0; i < S; ++i) - vec[i] = std::sin(vec[i]); - - return vec; + T x = maths::mix_radians(a.x, b.x, factor); + T y = maths::mix_radians(a.y, b.y, factor); + T z = maths::mix_radians(a.z, b.z, factor); + return { x, y, z }; } -/// Compute the component-wise cosine of a vector. -template inline -Vector cos(Vector vec) +//============================================================================== + +/// Compute the component-wise sine of a vector. +template +inline Vector sin(Vector vec) { static_assert(std::is_floating_point_v); - for (int i = 0; i < S; ++i) - vec[i] = std::cos(vec[i]); - + for (int i = 0; i < S; ++i) vec[i] = std::sin(vec[i]); return vec; } -/// Compute the component-wise tangent of a vector. -template inline -Vector tan(Vector vec) +/// Compute the component-wise cosine of a vector. +template +inline Vector cos(Vector vec) { static_assert(std::is_floating_point_v); - for (int i = 0; i < S; ++i) - vec[i] = std::tan(vec[i]); - + for (int i = 0; i < S; ++i) vec[i] = std::cos(vec[i]); return vec; } -//============================================================================// - -/// Compute the component-wise absolute of a vector. -template constexpr -Vector abs(Vector vec) +/// Compute the component-wise tangent of a vector. +template +inline Vector tan(Vector vec) { - for (int i = 0; i < S; ++i) - vec[i] = maths::abs(vec[i]); + static_assert(std::is_floating_point_v); + for (int i = 0; i < S; ++i) vec[i] = std::tan(vec[i]); return vec; } -//============================================================================// +//============================================================================== /// Convert a vector from cycles to radians. -template constexpr -Vector radians(Vector cycles) +template +constexpr Vector radians(Vector cycles) { static_assert(std::is_floating_point_v); @@ -394,49 +420,43 @@ Vector radians(Vector cycles) } /// Convert a vector from radians to cycles. -template constexpr -Vector cycles(Vector radians) +template +constexpr Vector cycles(Vector radians) { static_assert(std::is_floating_point_v); return radians * T(0.5 / 3.14159265358979323846); } -//============================================================================// +//============================================================================== /// Compute the dot product of two vectors. -template constexpr -T dot(Vector a, Vector b) +template +constexpr T dot(Vector a, Vector b) { static_assert(std::is_floating_point_v); T result = T(0.0); - - for (int i = 0; i < S; ++i) - result += a[i] * b[i]; - + for (int i = 0; i < S; ++i) result += a[i] * b[i]; return result; } /// Compute the dot product of a vector and a scalar. -template constexpr -T dot(Vector v, T s) +template +constexpr T dot(Vector v, T s) { static_assert(std::is_floating_point_v); T result = T(0.0); - - for (int i = 0; i < S; ++i) - result += v[i] * s; - + for (int i = 0; i < S; ++i) result += v[i] * s; return result; } -//============================================================================// +//============================================================================== /// Compute the squared length of a vector. -template constexpr -T length_squared(Vector vec) +template +constexpr T length_squared(Vector vec) { static_assert(std::is_floating_point_v); @@ -444,75 +464,71 @@ T length_squared(Vector vec) } /// Compute the length of a vector. -template inline -T length(Vector vec) +template +inline T length(Vector vec) { static_assert(std::is_floating_point_v); return std::sqrt(maths::dot(vec, vec)); } -//============================================================================// - -/// Compute the squared distance between two vectors. -template constexpr -T distance_squared(Vector a, Vector b) +/// Scale a vector to a length of one. +template +inline Vector normalize(Vector vec) { static_assert(std::is_floating_point_v); - return maths::length_squared(a - b); + return vec * (T(1.0) / maths::length(vec)); } -/// Compute the distance between two vectors. -template inline -T distance(Vector a, Vector b) +//============================================================================== + +/// Compute the squared distance between two vectors. +template +constexpr T distance_squared(Vector a, Vector b) { static_assert(std::is_floating_point_v); - return maths::length(a - b); + return maths::length_squared(a - b); } -//============================================================================// - -/// Compute the unit length vector. -template inline -Vector normalize(Vector vec) +/// Compute the distance between two vectors. +template +inline T distance(Vector a, Vector b) { static_assert(std::is_floating_point_v); - return vec * (T(1.0) / maths::length(vec)); + return maths::length(a - b); } -//============================================================================// +//============================================================================== /// Compute the reflection of incident by normal. -template constexpr -Vector reflect(Vector incident, Vector normal) +template +constexpr Vector3 reflect(Vector3 incident, Vector3 normal) { static_assert(std::is_floating_point_v); return incident - normal * maths::dot(normal, incident) * T(2.0); } -//============================================================================// - /// Compute the cross product of two vectors. -template constexpr -Vector3 cross(Vector3 a, Vector3 b) +template +constexpr Vector3 cross(Vector3 a, Vector3 b) { static_assert(std::is_floating_point_v); T x = (a.y * b.z) - (b.y * a.z); T y = (a.z * b.x) - (b.z * a.x); T z = (a.x * b.y) - (b.x * a.y); - return Vector3(x, y, z); + return { x, y, z }; } -//============================================================================// +//============================================================================== /// Rotate a vector along the X axis. -template inline -Vector3 rotate_x(Vector3 vec, T angle) +template +inline Vector3 rotate_x(Vector3 vec, T angle) { static_assert(std::is_floating_point_v); @@ -520,12 +536,12 @@ Vector3 rotate_x(Vector3 vec, T angle) T c = std::cos(radians(angle)); T y = (+vec.y * c) + (-vec.z * s); T z = (+vec.y * s) + (+vec.z * c); - return Vector3(vec.x, y, z); + return { vec.x, y, z }; } /// Rotate a vector along the Y axis. -template inline -Vector3 rotate_y(Vector3 vec, T angle) +template +inline Vector3 rotate_y(Vector3 vec, T angle) { static_assert(std::is_floating_point_v); @@ -533,12 +549,12 @@ Vector3 rotate_y(Vector3 vec, T angle) T c = std::cos(radians(angle)); T x = (+vec.x * c) + (+vec.z * s); T z = (-vec.x * s) + (+vec.z * c); - return Vector3(x, vec.y, z); + return { x, vec.y, z }; } /// Rotate a vector along the Z axis. -template inline -Vector3 rotate_z(Vector3 vec, T angle) +template +inline Vector3 rotate_z(Vector3 vec, T angle) { static_assert(std::is_floating_point_v); @@ -546,72 +562,38 @@ Vector3 rotate_z(Vector3 vec, T angle) T c = std::cos(radians(angle)); T x = (+vec.x * c) + (-vec.y * s); T y = (+vec.x * s) + (+vec.y * c); - return Vector3(x, y, vec.z); + return { x, y, vec.z }; } -//============================================================================// - -} // namespace maths +} // namespace sq::maths ####################################################### -template -constexpr const char* type_to_string(maths::Vector) -{ - if constexpr (S == 2 && std::is_same_v) return "Vec2I"; - if constexpr (S == 3 && std::is_same_v) return "Vec3I"; - if constexpr (S == 4 && std::is_same_v) return "Vec4I"; - if constexpr (S == 2 && std::is_same_v) return "Vec2U"; - if constexpr (S == 3 && std::is_same_v) return "Vec3U"; - if constexpr (S == 4 && std::is_same_v) return "Vec4U"; - if constexpr (S == 2 && std::is_same_v) return "Vec2F"; - if constexpr (S == 3 && std::is_same_v) return "Vec3F"; - if constexpr (S == 4 && std::is_same_v) return "Vec4F"; - return "Vector"; -} - -//============================================================================// - -namespace detail { - -template -struct VectorTraits : std::false_type {}; +#include -template -struct VectorTraits : VectorTraits {}; +#include template -struct VectorTraits> : std::true_type +struct fmt::formatter> { - static constexpr int size = S; - using type = T; -}; - -template -constexpr bool is_vector_v = VectorTraits::value; - -template -constexpr int vector_size_v = VectorTraits::size; + fmt::formatter base; -template -using vector_type_t = typename VectorTraits::type; - -}} // namespace sq::detail - -//============================================================================// + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } -template -struct fmt::formatter> : fmt::formatter -{ template - auto format(const sq::maths::Vector& vec, FormatContext& ctx) + FormatContext::iterator format(const sq::maths::Vector& vec, FormatContext& ctx) const { - fmt::format_to(ctx.out(), "{}(", sq::type_to_string(sq::maths::Vector())); - formatter::format(vec.x, ctx); - fmt::format_to(ctx.out(), ", "); - formatter::format(vec.y, ctx); - if constexpr (S >= 3) fmt::format_to(ctx.out(), ", "); - if constexpr (S >= 3) formatter::format(vec.z, ctx); - if constexpr (S == 4) fmt::format_to(ctx.out(), ", "); - if constexpr (S == 4) formatter::format(vec.w, ctx); - return fmt::format_to(ctx.out(), ")"); + ctx.advance_to(fmt::detail::write(ctx.out(), sq::type_name_v>.c_str())); + ctx.advance_to(fmt::detail::write(ctx.out(), '(')); + ctx.advance_to(base.format(vec.x, ctx)); + ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + ctx.advance_to(base.format(vec.y, ctx)); + if constexpr (S >= 3) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S >= 3) ctx.advance_to(base.format(vec.z, ctx)); + if constexpr (S == 4) ctx.advance_to(fmt::detail::write(ctx.out(), ", ")); + if constexpr (S == 4) ctx.advance_to(base.format(vec.w, ctx)); + return fmt::detail::write(ctx.out(), ')'); } }; diff --git a/include/sqee/misc/Files.hpp b/include/sqee/misc/Files.hpp index 7d51c403..66a5d2e7 100644 --- a/include/sqee/misc/Files.hpp +++ b/include/sqee/misc/Files.hpp @@ -5,7 +5,7 @@ #include -#include +#include // Note that all file paths in sqee are unix style, don't try to use dos paths. // Windows is kind enough to work just fine with unix paths, so there's no need diff --git a/include/sqee/misc/Json.hpp b/include/sqee/misc/Json.hpp index 429ac95c..65372c1c 100644 --- a/include/sqee/misc/Json.hpp +++ b/include/sqee/misc/Json.hpp @@ -3,135 +3,711 @@ #pragma once -#include +#include -#include -#include +#include +#include +#include -#include // IWYU pragma: export +#include -#include // IWYU pragma: export +//============================================================================== -namespace sq { +extern "C" { +typedef struct yyjson_doc yyjson_doc; +typedef struct yyjson_val yyjson_val; +typedef struct yyjson_mut_doc yyjson_mut_doc; +typedef struct yyjson_mut_val yyjson_mut_val; +} // extern "C" -//============================================================================// +namespace sq { //############################################################### -SQEE_API JsonValue parse_json_from_file(const String& path); +template +struct JsonTraits final {}; -SQEE_API std::optional try_parse_json_from_file(const String& path); +template +concept JsonCastableAs = HasTypeName && requires (JsonAny json) { JsonTraits::as(json); }; -//============================================================================// +template +concept JsonCastableFrom = HasTypeName && requires (JsonMutDocument& doc, const Type& arg) { JsonTraits::from(doc, arg); }; -template -void from_json(const JsonValue& j, StackString& str) +//============================================================================== + +namespace detail { + +constexpr uint8_t JSON_TYPE_NULL = 2; +constexpr uint8_t JSON_TYPE_BOOL = 3; +constexpr uint8_t JSON_TYPE_NUM = 4; +constexpr uint8_t JSON_TYPE_STR = 5; +constexpr uint8_t JSON_TYPE_ARR = 6; +constexpr uint8_t JSON_TYPE_OBJ = 7; + +constexpr uint8_t JSON_SUBTYPE_FALSE = 0 << 3; +constexpr uint8_t JSON_SUBTYPE_TRUE = 1 << 3; +constexpr uint8_t JSON_SUBTYPE_UINT = 0 << 3; +constexpr uint8_t JSON_SUBTYPE_SINT = 1 << 3; +constexpr uint8_t JSON_SUBTYPE_REAL = 2 << 3; + +inline bool json_check_tag(void* val, uint8_t type) { - if (j.is_string() == false || j.size() > Capacity) - SQEE_THROW("from_json: {} -> {}", j.dump(), type_to_string(StackString())); - str = j.get_ref(); + return (*reinterpret_cast(val) & uint8_t(0x7)) == type; } -template -void to_json(JsonValue& j, const StackString& str) +inline bool json_check_tag(void* val, uint8_t type, uint8_t subtype) { - j = String(str); + return *reinterpret_cast(val) == (type | subtype); } -//============================================================================// +inline size_t json_get_length(void* val) +{ + return size_t(*reinterpret_cast(val) >> 8); +} -namespace maths { +inline yyjson_val* json_get_first(yyjson_val* val) +{ + return json_get_length(val) ? reinterpret_cast(reinterpret_cast(val)+2) : nullptr; +} -//====== Forward Declarations ================================================// +template +inline std::optional json_as_integer(void* val) noexcept +{ + if (json_check_tag(val, JSON_TYPE_NUM, JSON_SUBTYPE_UINT)) + { + if (uint64_t v = reinterpret_cast(val)[1]; v <= uint64_t(std::numeric_limits::max())) + return Integer(v); + } + else if constexpr (std::is_signed_v) + { + if (json_check_tag(val, JSON_TYPE_NUM, JSON_SUBTYPE_SINT)) + if (int64_t v = reinterpret_cast(val)[1]; v >= int64_t(std::numeric_limits::min())) + return Integer(v); + } + return std::nullopt; +} -template struct RandomRange; +} // namespace detail -//============================================================================// +//============================================================================== -template -inline void from_json(const JsonValue& json, Vector& vec) +class SQEE_API JsonAny { - if (json.is_array() == false || json.size() != Size) - SQEE_THROW("from_json: {} -> {}", json.dump(), type_to_string(Vector())); +public: //====================================================== - json[0].get_to(vec.x); - json[1].get_to(vec.y); - if constexpr (Size >= 3) json[2].get_to(vec.z); - if constexpr (Size == 4) json[3].get_to(vec.w); -} + /// Access the document that contains this element. + const JsonDocument& document() const { return *mDoc; } -template -inline void to_json(JsonValue& json, const Vector& vec) + /// Conveniently check if the element is null. + bool is_null() const noexcept + { + return detail::json_check_tag(mVal, detail::JSON_TYPE_NULL); + } + + /// Cast the element to the given type, return nullopt if the conversion fails. + template + std::optional as_safe() const noexcept + { + return JsonTraits::as(*this); + } + + /// Cast the element to the given type, throw if the conversion fails. + template + Type as() const + { + if (auto opt = JsonTraits::as(*this)) return *opt; + impl_throw_as(type_name_v.c_str()); + } + + struct AutoCaster final + { + const JsonAny& ref; + template + operator Type() const { return ref.as(); } + }; + + /// Get an object that can be implicitly converted to any supported type. + AutoCaster as_auto() const + { + return AutoCaster{*this}; + } + + /// Build a minified or pretty document string from this element. + String dump(bool pretty) const noexcept; + + /// Build a json pointer string for this element. + String pointer() const noexcept; + + /// Throw a std::runtime_error with extra information about this element. + template + [[noreturn]] void throw_with_context(FmtStrIfArgs fstr, Args&&... args) const + { + impl_throw_with_context(fstr, fmt::make_format_args(args...)); + } + +protected: //=================================================== + + yyjson_val* mVal; const JsonDocument* mDoc; + + JsonAny(yyjson_val* val, const JsonDocument* doc) noexcept : mVal(val), mDoc(doc) {} + + [[noreturn]] void impl_throw_as(const char* typeName) const; + + [[noreturn]] void impl_throw_with_context(fmt::string_view fstr, fmt::format_args args) const; + + friend JsonArray; friend JsonObject; friend JsonDocument; + template friend struct JsonTraits; +}; + +//------------------------------------------------------------------------------ + +class SQEE_API JsonArray final : public JsonAny { - if constexpr (Size == 2) json = { vec.x, vec.y }; - if constexpr (Size == 3) json = { vec.x, vec.y, vec.z }; - if constexpr (Size == 4) json = { vec.x, vec.y, vec.z, vec.w }; -} +public: //====================================================== -//----------------------------------------------------------------------------// + using IndexValue = std::pair; -template -inline void from_json(const JsonValue& json, Quaternion& quat) + struct PointerFacade final { IndexValue item; IndexValue* operator->() noexcept { return &item; } }; + + struct Iterator final + { + size_t iterIdx; yyjson_val* iterCur; const JsonArray* array; + + using element_type = IndexValue; + using iterator_concept = std::forward_iterator_tag; + + Iterator& operator++() noexcept; + Iterator operator++(int) noexcept { Iterator tmp = *this; ++(*this); return tmp; } + + ptrdiff_t operator-(const Iterator& other) const noexcept { return ptrdiff_t(iterIdx) - ptrdiff_t(other.iterIdx); } + + IndexValue operator*() const noexcept; + PointerFacade operator->() const noexcept { return PointerFacade{**this}; } + + auto operator<=>(const Iterator& other) const noexcept { return iterIdx <=> other.iterIdx; }; + bool operator==(const Iterator& other) const noexcept { return iterIdx == other.iterIdx; } + }; + + size_t size() const noexcept { return detail::json_get_length(mVal); } + + Iterator begin() const noexcept { return { 0u, detail::json_get_first(mVal), this }; } + + Iterator end() const noexcept { return { detail::json_get_length(mVal), nullptr, this }; } + + /// Get a value by index if the index is in range. + std::optional get_safe(size_t index) const noexcept; + + /// Get a value by index or throw if the index is not in range. + JsonAny operator[](size_t index) const { if (auto opt = get_safe(index)) return *opt; impl_throw_get(index); } + +protected: //=================================================== + + explicit JsonArray(JsonAny base) noexcept : JsonAny(base.mVal, base.mDoc) {} + + void impl_iter_next(Iterator& iter) const noexcept; + + [[noreturn]] void impl_throw_get(size_t index) const; + + template friend struct JsonTraits; +}; + +//------------------------------------------------------------------------------ + +class SQEE_API JsonObject final : public JsonAny { - if (json.is_array() == false || json.size() != 4) - SQEE_THROW("from_json: {} -> {}", json.dump(), type_to_string(Quaternion())); +public: //====================================================== - json[0].get_to(quat.x); - json[1].get_to(quat.y); - json[2].get_to(quat.z); - json[3].get_to(quat.w); -} + using KeyValue = std::pair; -template -inline void to_json(JsonValue& json, const Quaternion& quat) + struct PointerFacade final { KeyValue item; KeyValue* operator->() noexcept { return &item; } }; + + struct Iterator final + { + size_t iterIdx; yyjson_val* iterCur; const JsonObject* object; + + using element_type = KeyValue; + using iterator_concept = std::forward_iterator_tag; + + Iterator& operator++() noexcept; + Iterator operator++(int) noexcept { Iterator tmp = *this; ++(*this); return tmp; } + + ptrdiff_t operator-(const Iterator& other) const noexcept { return ptrdiff_t(iterIdx) - ptrdiff_t(other.iterIdx); } + + KeyValue operator*() const noexcept; + PointerFacade operator->() const noexcept { return PointerFacade{**this}; } + + auto operator<=>(const Iterator& other) const noexcept { return iterIdx <=> other.iterIdx; }; + bool operator==(const Iterator& other) const noexcept { return iterIdx == other.iterIdx; } + }; + + size_t size() const noexcept { return detail::json_get_length(mVal); } + + Iterator begin() const noexcept { return { 0u, detail::json_get_first(mVal), this }; } + + Iterator end() const noexcept { return { detail::json_get_length(mVal), nullptr, this }; } + + /// Get a value by key if the key exists. + std::optional get_safe(StringView key) const noexcept; + + /// Get a value by key or throw if the key does not exist. + JsonAny operator[](StringView key) const { if (auto opt = get_safe(key)) return *opt; impl_throw_get(key); } + +protected: //=================================================== + + explicit JsonObject(JsonAny base) noexcept : JsonAny(base.mVal, base.mDoc) {} + + void impl_iter_next(Iterator& iter) const noexcept; + + [[noreturn]] void impl_throw_get(StringView Key) const; + + template friend struct JsonTraits; +}; + +//------------------------------------------------------------------------------ + +class SQEE_API JsonDocument final { - json = { quat.x, quat.y, quat.z, quat.w }; -} +public: //====================================================== -//----------------------------------------------------------------------------// + ~JsonDocument() noexcept; -template -inline void from_json(const JsonValue& json, RandomRange& range) + /// Load a new document from a file. Return an error string on failure. + static tl::expected parse_file_safe(String path) noexcept; + + /// Load a new document from a file. Throw an exception on failure. + static JsonDocument parse_file(String path); + + /// Load a new document from a string. Return an error string on failure. + static tl::expected parse_string_safe(StringView source, String fakePath) noexcept; + + /// Load a new document from a string. Throw an exception on failure. + static JsonDocument parse_string(StringView source, String fakePath); + + /// Access the document's root element. + JsonAny root() const noexcept { return JsonAny(mRoot, this); } + +private: //===================================================== + + yyjson_doc* const mDoc; yyjson_val* const mRoot; const String mPath; + + JsonDocument(yyjson_doc* doc, yyjson_val* root, String path) noexcept : mDoc(doc), mRoot(root), mPath(path) {} + + friend JsonAny; friend JsonArray; friend JsonObject; + template friend struct JsonTraits; +}; + +//============================================================================== + +class SQEE_API JsonMutAny { - if (json.is_array() == false || json.size() != 2u) - SQEE_THROW("from_json: {} -> {}", json.dump(), type_to_string(RandomRange())); +public: //====================================================== - json[0].get_to(range.min); - json[1].get_to(range.max); -} + /// Construct a new element for the given document. + template + JsonMutAny(JsonMutDocument& doc, const Type& arg) noexcept : mVal(JsonTraits::from(doc, arg).mVal), mDoc(&doc) {} -template -inline void to_json(JsonValue& json, const RandomRange& range) + /// Access the document that was used to create this element. + JsonMutDocument& document() noexcept { return *mDoc; } + + /// Build a minified or pretty document string from this element. + String dump(bool pretty) const noexcept; + +protected: //=================================================== + + yyjson_mut_val* mVal; JsonMutDocument* mDoc; + + JsonMutAny(yyjson_mut_val* val, JsonMutDocument* doc) noexcept : mVal(val), mDoc(doc) {} + + friend JsonMutArray; friend JsonMutObject; friend JsonMutDocument; + template friend struct JsonTraits; +}; + +//------------------------------------------------------------------------------ + +class SQEE_API JsonMutArray final : public JsonMutAny { - json = { range.min, range.max }; -} +public: //====================================================== + + /// Construct a new json array for the given document. + JsonMutArray(JsonMutDocument& doc) noexcept; + + /// Add a new element to the end of the array. Returns an Any/Array/Object. + template + auto append(const Type& arg) noexcept + { + auto result = JsonTraits::from(*mDoc, arg); + impl_append_any(result); + return result; + } + +private: //===================================================== -//============================================================================// + void impl_append_any(JsonMutAny any) noexcept; -}} // namespace sq::maths + template friend struct JsonTraits; +}; -//============================================================================// +//------------------------------------------------------------------------------ -template -struct nlohmann::adl_serializer>> +class SQEE_API JsonMutObject final : public JsonMutAny { - static void to_json(sq::JsonValue& json, const EnumT& e) +public: //====================================================== + + /// Construct a new json object for the given document. + JsonMutObject(JsonMutDocument& doc) noexcept; + + /// Add a new element with the given key. Returns an Any/Array/Object. + template + auto append(StringView key, const Type& arg) noexcept { - json = sq::enum_to_string(e); + auto result = JsonTraits::from(*mDoc, arg); + impl_append_any(key, result); + return result; } - static void from_json(const sq::JsonValue& json, EnumT& e) + +private: //===================================================== + + void impl_append_any(StringView key, JsonMutAny any) noexcept; + + template friend struct JsonTraits; +}; + +//------------------------------------------------------------------------------ + +class SQEE_API JsonMutDocument final +{ +public: //====================================================== + + JsonMutDocument() noexcept; + + ~JsonMutDocument() noexcept; + + /// Set the document's root element. Returns an Any/Array/Object. + template + auto assign(const Type& arg) noexcept { - e = sq::enum_from_string(json.get_ref()); + auto result = JsonTraits::from(*this, arg); + impl_assign_any(result); + return result; } + +private: //===================================================== + + yyjson_mut_doc* const mDoc; yyjson_mut_val* mRoot = nullptr; + + void impl_assign_any(JsonMutAny any) noexcept; + + friend JsonMutAny; friend JsonMutArray; friend JsonMutObject; + template friend struct JsonTraits; }; -//============================================================================// +//============================================================================== -template<> struct fmt::formatter : fmt::formatter +namespace views { + +/// Casts each value of a JsonArray or JsonObject to the given type. +template +inline const auto json_as = std::views::transform([](auto item) { return std::pair(item.first, item.second.template as()); }); + +} // namespace views + +//============================================================================== + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_NULL)) return nullptr; + return std::nullopt; + } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, std::nullptr_t) noexcept; +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_BOOL, detail::JSON_SUBTYPE_FALSE)) return false; + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_BOOL, detail::JSON_SUBTYPE_TRUE)) return true; + return std::nullopt; + } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, bool arg) noexcept; +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, int64_t arg) noexcept; +}; + +template<> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, int32_t arg) noexcept { return JsonTraits::from(doc, int64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, int16_t arg) noexcept { return JsonTraits::from(doc, int64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, int8_t arg) noexcept { return JsonTraits::from(doc, int64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, uint64_t arg) noexcept; +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, uint32_t arg) noexcept { return JsonTraits::from(doc, uint64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, uint16_t arg) noexcept { return JsonTraits::from(doc, uint64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return detail::json_as_integer(json.mVal); } + inline static JsonMutAny from(JsonMutDocument& doc, uint8_t arg) noexcept { return JsonTraits::from(doc, uint64_t(arg)); } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_NUM, detail::JSON_SUBTYPE_REAL)) + return reinterpret_cast(json.mVal)[1]; + return std::nullopt; + } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, double arg) noexcept; +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + // automatically round or clamp double to float + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_NUM, detail::JSON_SUBTYPE_REAL)) + return float(reinterpret_cast(json.mVal)[1]); + return std::nullopt; + } + inline static JsonMutAny from(JsonMutDocument& doc, float arg) noexcept + { + return JsonTraits::from(doc, double(arg)); + } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_STR)) + return StringView(reinterpret_cast(json.mVal)[1], detail::json_get_length(json.mVal)); + return std::nullopt; + } + SQEE_API static JsonMutAny from(JsonMutDocument& doc, StringView arg) noexcept; +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_STR)) + return String(reinterpret_cast(json.mVal)[1], detail::json_get_length(json.mVal)); + return std::nullopt; + } + inline static JsonMutAny from(JsonMutDocument& doc, const String& arg) noexcept + { + return JsonTraits::from(doc, StringView(arg)); + } +}; + +//------------------------------------------------------------------------------ + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept { return json; } +}; + +template <> struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_ARR)) return JsonArray(json); + return std::nullopt; + } +}; + +template <> struct JsonTraits { - template - auto format(const sq::JsonValue& json, FormatContext& ctx) + inline static std::optional as(JsonAny json) noexcept { - return formatter::format(impl_dump(json), ctx); + if (detail::json_check_tag(json.mVal, detail::JSON_TYPE_OBJ)) return JsonObject(json); + return std::nullopt; } +}; + +template <> struct JsonTraits +{ + inline static JsonMutAny from(JsonMutDocument&, JsonMutAny arg) noexcept { return arg; } +}; + +template <> struct JsonTraits +{ + inline static JsonMutArray from(JsonMutDocument&, JsonMutArray arg) noexcept { return arg; } +}; - SQEE_API std::string impl_dump(const sq::JsonValue& json); +template <> struct JsonTraits +{ + inline static JsonMutObject from(JsonMutDocument&, JsonMutObject arg) noexcept { return arg; } }; + +//============================================================================== + +template +struct JsonTraits> +{ + inline static std::optional> as(JsonAny json) noexcept + { + if (auto sv = JsonTraits::as(json); sv && sv->length() <= Capacity) return StackString(*sv); + return std::nullopt; + } + + inline static JsonMutAny from(JsonMutDocument& doc, const StackString& arg) noexcept + { + return JsonTraits::from(doc, StringView(arg)); + } +}; + +//------------------------------------------------------------------------------ + +template +struct JsonTraits> +{ + inline static std::optional> as(JsonAny json) noexcept + { + if (auto array = JsonTraits::as(json); array && array->size() <= Capacity) + { + StackVector result; + for (auto [_, value] : *array) + if (auto v = JsonTraits::as(value)) result.emplace_back(*v); + else return std::nullopt; + return result; + } + return std::nullopt; + } + + inline static JsonMutArray from(JsonMutDocument& doc, const StackVector& arg) noexcept + { + auto array = JsonMutArray(doc); + for (const auto& v : arg) array.append(arg); + return array; + } +}; + +//------------------------------------------------------------------------------ + +template +struct JsonTraits> +{ + inline static std::optional> as(JsonAny json) noexcept + { + if (auto array = JsonTraits::as(json); array && array->size() == Size) + { + maths::Vector result; + for (int i = 0; i < Size; ++i) + if (auto v = JsonTraits::as(*(array->get_safe(i)))) result[i] = *v; + else return std::nullopt; + return result; + } + return std::nullopt; + } + + inline static JsonMutArray from(JsonMutDocument& doc, const maths::Vector& arg) noexcept + { + auto array = JsonMutArray(doc); + for (int i = 0; i < Size; ++i) array.append(arg[i]); + return array; + } +}; + +//------------------------------------------------------------------------------ + +template +struct JsonTraits> +{ + inline static std::optional> as(JsonAny json) noexcept + { + if (auto array = JsonTraits::as(json); array && array->size() == 4) + { + maths::Quaternion result; + for (int i = 0; i < 4; ++i) + if (auto v = JsonTraits::as(*(array->get_safe(i)))) result[i] = *v; + else return std::nullopt; + return result; + } + return std::nullopt; + } + + inline static JsonMutArray from(JsonMutDocument& doc, const maths::Quaternion& arg) noexcept + { + auto array = JsonMutArray(doc); + for (int i = 0; i < 4; ++i) array.append(arg[i]); + return array; + } +}; + +//------------------------------------------------------------------------------ + +template +struct JsonTraits> +{ + inline static std::optional> as(JsonAny json) noexcept + { + if (auto array = JsonTraits::as(json); array && array->size() == 2) + { + maths::RandomRange result; + if (auto v = JsonTraits::as(*(array->get_safe(0)))) result.min = *v; + else return std::nullopt; + if (auto v = JsonTraits::as(*(array->get_safe(1)))) result.max = *v; + else return std::nullopt; + return result; + } + return std::nullopt; + } + + inline static JsonMutArray from(JsonMutDocument& doc, const maths::RandomRange& arg) noexcept + { + auto array = JsonMutArray(doc); + array.append(arg.min); array.append(arg.max); + return array; + } +}; + +//------------------------------------------------------------------------------ + +template +struct JsonTraits +{ + inline static std::optional as(JsonAny json) noexcept + { + if (auto sv = JsonTraits::as(json)) return enum_from_string_safe(*sv); + return std::nullopt; + } + + inline static JsonMutAny from(JsonMutDocument& doc, Enum arg) noexcept + { + return JsonTraits::from(doc, *enum_to_string_safe(arg)); + } +}; + +} // namespace sq ############################################################## diff --git a/include/sqee/misc/JsonFwd.hpp b/include/sqee/misc/JsonFwd.hpp deleted file mode 100644 index 99b3e983..00000000 --- a/include/sqee/misc/JsonFwd.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright(c) 2020 James Gangur -// Part of https://github.com/jagoly/sqee - -#pragma once - -// not useful for the way we handle errors -#define JSON_DIAGNOSTICS 0 - -// don't want to accidentally serialise enums as ints -#define JSON_DISABLE_ENUM_SERIALIZATION 0 - -// sqee doesn't use iostreams anywhere -#define JSON_NO_IO 1 - -// implicit conversions don't play nice with fmtlib -#define JSON_USE_IMPLICIT_CONVERSIONS 0 - -#include // IWYU pragma: export - -// IWYU pragma: no_include -// IWYU pragma: no_include -// IWYU pragma: no_include -// IWYU pragma: no_include - -namespace sq { - -// use 32bit number types for compatibility with wren -using JsonValue = nlohmann::basic_json; - -} // namespace sq - diff --git a/include/sqee/misc/Parsing.hpp b/include/sqee/misc/Parsing.hpp index dda5c0b5..ba66c56b 100644 --- a/include/sqee/misc/Parsing.hpp +++ b/include/sqee/misc/Parsing.hpp @@ -5,7 +5,9 @@ #include -#include +#include +#include +#include #include @@ -13,6 +15,28 @@ namespace sq { //============================================================================// +/// Split a string into a fixed number of segments. Check for success with `!result.back().empty()`. +template +constexpr std::array split_string(StringView sv) noexcept +{ + constexpr char delimiters[] = { Delimiters... }; + + std::array result; + for (size_t index = 0u; index < sizeof...(Delimiters) && !sv.empty(); ++index) + { + size_t segSize = sv.find(delimiters[index]); + if (segSize == StringView::npos) segSize = sv.size(); + result[index] = StringView(sv.data(), segSize); + if (segSize < sv.size()) ++segSize; + sv.remove_prefix(segSize); + } + result.back() = sv; + + return result; +} + +//============================================================================// + /// Split a StringView into a vector of tokens. SQEE_API std::vector tokenise_string(StringView sv, char dlm); @@ -42,6 +66,19 @@ inline void parse_number(Number& out, StringView sv) if (result.ec == std::errc::result_out_of_range) throw std::out_of_range("parse_number"); } +#ifdef _LIBCPP_VERSION // libc++ still doesn't support floating point from_chars as of dec 2023 +template +inline Number parse_number(StringView sv) requires std::floating_point +{ + return Number(std::stod(String(sv))); +} +template +inline void parse_number(Number& out, StringView sv) requires std::floating_point +{ + out = Number(std::stod(String(sv))); +} +#endif + //============================================================================// template diff --git a/include/sqee/misc/ResourceCache.hpp b/include/sqee/misc/ResourceCache.hpp index 259de63f..a4472377 100644 --- a/include/sqee/misc/ResourceCache.hpp +++ b/include/sqee/misc/ResourceCache.hpp @@ -7,6 +7,7 @@ #include #include + #include namespace sq { @@ -41,7 +42,7 @@ class ResourceCache final SQASSERT(mFactoryFunc != nullptr, "no factory assigned"); iter->second.key = &iter->first; try { - iter->second.data = std::make_unique(mFactoryFunc(key)); + iter->second.value = std::make_unique(mFactoryFunc(key)); } catch (const std::exception& ex) { log_error_multiline("unhandled exception when loading resource\nkey: {}\nwhat: {}", key, ex.what()); @@ -51,8 +52,8 @@ class ResourceCache final return Handle(iter->second); } - /// Try to acquire a resource. Return a null handle on failure. - Handle try_acquire(const Key& key, bool silent = false) + /// Try to acquire a resource. Return a handle to an error resource if creation fails. + Handle acquire_safe(const Key& key) noexcept { const auto [iter, created] = mResourceMap.try_emplace(key); if (created == true) @@ -60,11 +61,10 @@ class ResourceCache final SQASSERT(mFactoryFunc != nullptr, "no factory assigned"); iter->second.key = &iter->first; try { - iter->second.data = std::make_unique(mFactoryFunc(key)); + iter->second.value = std::make_unique(mFactoryFunc(key)); } catch (const std::exception& ex) { - if (!silent) log_warning_multiline("exception when loading resource\nkey: {}:\nwhat: {}", key, ex.what()); - mResourceMap.erase(iter); return nullptr; + iter->second.error = ex.what(); } iter->second.count = 0u; } @@ -75,7 +75,11 @@ class ResourceCache final void reload_resources() { for (auto& [key, resource] : mResourceMap) - *resource.data = mFactoryFunc(key); + { + // todo: how should we handle error resources? + if (resource.value != nullptr) + *resource.value = mFactoryFunc(key); + } } /// Free resources that no longer have any handles. diff --git a/include/sqee/misc/ResourceHandle.hpp b/include/sqee/misc/ResourceHandle.hpp index 71fe10c2..3dc540ce 100644 --- a/include/sqee/misc/ResourceHandle.hpp +++ b/include/sqee/misc/ResourceHandle.hpp @@ -5,7 +5,7 @@ #include -#include +#include namespace sq { @@ -21,7 +21,8 @@ struct Resource final SQEE_MOVE_DELETE(Resource) const Key* key; - std::unique_ptr data; + std::unique_ptr value; + std::string error; size_t count; }; @@ -33,30 +34,30 @@ class Handle final { public: //====================================================// - Handle(std::nullptr_t = nullptr) + Handle(std::nullptr_t = nullptr) noexcept { mResourcePtr = nullptr; } - Handle(Resource& resource) + Handle(Resource& resource) noexcept { mResourcePtr = &resource; ++mResourcePtr->count; } - Handle(const Handle& other) + Handle(const Handle& other) noexcept { mResourcePtr = other.mResourcePtr; if (mResourcePtr) ++mResourcePtr->count; } - Handle(Handle&& other) + Handle(Handle&& other) noexcept { mResourcePtr = other.mResourcePtr; other.mResourcePtr = nullptr; } - Handle& operator=(const Handle& other) + Handle& operator=(const Handle& other) noexcept { if (mResourcePtr) --mResourcePtr->count; mResourcePtr = other.mResourcePtr; @@ -64,7 +65,7 @@ class Handle final return *this; } - Handle& operator=(Handle&& other) + Handle& operator=(Handle&& other) noexcept { if (mResourcePtr) --mResourcePtr->count; mResourcePtr = other.mResourcePtr; @@ -72,42 +73,52 @@ class Handle final return *this; } - ~Handle() + ~Handle() noexcept { if (mResourcePtr) --mResourcePtr->count; } //--------------------------------------------------------// - const Type* operator->() const + bool good() const noexcept { - SQASSERT(mResourcePtr, "null handle error"); - return mResourcePtr->data.get(); + assert(mResourcePtr); + return mResourcePtr->value != nullptr; } - const Type& operator*() const + const Key& key() const noexcept { - SQASSERT(mResourcePtr, "null handle error"); - return *mResourcePtr->data; + assert(mResourcePtr); + return *mResourcePtr->key; } - const Type& get() const + const Type* operator->() const noexcept { - SQASSERT(mResourcePtr, "null handle error"); - return *mResourcePtr->data; + assert(mResourcePtr && mResourcePtr->value); + return mResourcePtr->value.get(); } - const Key& get_key() const + const Type& operator*() const noexcept { - SQASSERT(mResourcePtr, "null handle error"); - return *mResourcePtr->key; + assert(mResourcePtr && mResourcePtr->value); + return *mResourcePtr->value; } - //--------------------------------------------------------// + const Type& value() const noexcept + { + assert(mResourcePtr && mResourcePtr->value); + return *mResourcePtr->value; + } - bool operator==(const Handle& other) const { return mResourcePtr == other.mResourcePtr; } + const std::string& error() const noexcept + { + assert(mResourcePtr && !mResourcePtr->value); + return mResourcePtr->error; + } + + //--------------------------------------------------------// - bool operator!=(const Handle& other) const { return mResourcePtr != other.mResourcePtr; } + bool operator==(const Handle& other) const noexcept { return mResourcePtr == other.mResourcePtr; } private: //===================================================// diff --git a/include/sqee/misc/StackString.hpp b/include/sqee/misc/StackString.hpp index dcfbcf22..59a78f74 100644 --- a/include/sqee/misc/StackString.hpp +++ b/include/sqee/misc/StackString.hpp @@ -3,29 +3,26 @@ #pragma once -#include #include #include #include #include -namespace sq { - -//============================================================================// +namespace sq { //############################################################### /// Fast stack only string type, useful for keys. template class StackString final { -public: //====================================================// +public: //====================================================== using Traits = std::char_traits; static constexpr size_t capacity() { return Capacity; } - static constexpr size_t buffer_size() { return Capacity + 1u; } + static constexpr size_t buffer_size() { return Capacity + 1; } - //--------------------------------------------------------// + //---------------------------------------------------------- constexpr char* data() { return mData; } @@ -39,7 +36,11 @@ class StackString final constexpr void clear() { *this = StackString(); } - //--------------------------------------------------------// + constexpr const char* begin() const { return data(); } + + constexpr const char* end() const { return data() + length(); } + + //---------------------------------------------------------- constexpr StackString() noexcept = default; @@ -49,17 +50,17 @@ class StackString final constexpr StackString& operator=(const StackString&) noexcept = default; constexpr StackString& operator=(StackString&&) noexcept = default; - //--------------------------------------------------------// + //---------------------------------------------------------- template constexpr StackString(const char(&chars)[BufSize]) noexcept { static_assert(BufSize <= buffer_size(), "literal too long"); - Traits::copy(mData, chars, BufSize - 1u); + Traits::copy(mData, chars, BufSize - 1); } - template >> + template CharT> constexpr StackString(const CharT* const& cstr) { const size_t numChars = Traits::length(cstr); @@ -86,7 +87,7 @@ class StackString final Traits::copy(mData, str.data(), str.length()); } - //--------------------------------------------------------// + //---------------------------------------------------------- constexpr int compare(const StackString& other) const { @@ -100,7 +101,7 @@ class StackString final return Traits::compare(mData, chars, n); } - template >> + template CharT> constexpr int compare(const CharT* const& cstr) const { // simplified strcmp @@ -137,7 +138,7 @@ class StackString final return compare(str.c_str()); } - //--------------------------------------------------------// + //---------------------------------------------------------- constexpr auto operator<=>(const StackString& other) const { return compare(other) <=> 0; } constexpr bool operator==(const StackString& other) const { return compare(other) == 0; } @@ -147,9 +148,9 @@ class StackString final template constexpr bool operator==(const char(&chars)[BufSize]) const { return compare(chars) == 0; } - template >> + template CharT> constexpr auto operator<=>(const CharT* const& cstr) const { return compare(cstr) <=> 0; } - template >> + template CharT> constexpr bool operator==(const CharT* const& cstr) const { return compare(cstr) == 0; } constexpr auto operator<=>(const std::string_view& sv) const { return compare(sv) <=> 0; } @@ -158,7 +159,7 @@ class StackString final constexpr auto operator<=>(const std::string& str) const { return compare(str) <=> 0; } constexpr bool operator==(const std::string& str) const { return compare(str) == 0; } - //--------------------------------------------------------// + //---------------------------------------------------------- constexpr bool starts_with(std::string_view prefix) const { @@ -172,37 +173,48 @@ class StackString final return Traits::compare(mData + Capacity - suffix.length(), suffix.data(), suffix.length()) == 0; } - //constexpr std::string_view substr(size_t pos, size_t count) const - //{ - // // let string_view do the bounds checking for us - // return std::string_view(mData, length()).substr(pos, count); - //} - - //--------------------------------------------------------// + //---------------------------------------------------------- constexpr operator std::string_view() const noexcept { return std::string_view(mData, length()); } -private: //===================================================// + //---------------------------------------------------------- - char mData[buffer_size()] {}; // initialise with zeros + // public so that the class is structural, and thus usable for non-type template params + char mData[buffer_size()] {}; }; -//============================================================================// +//============================================================================== + +// deduction guide for compile time string stuff +template +StackString(const char(&chars)[BufSize]) -> StackString; + +} // namespace sq ############################################################## + +#include template -constexpr const char* type_to_string(StackString) +struct fmt::formatter> { - if constexpr (Capacity == 15u) return "TinyString"; - if constexpr (Capacity == 23u) return "SmallString"; - return "StackString"; -} + fmt::formatter base; -//============================================================================// + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + return base.parse(ctx); + } -} // namespace sq + template + constexpr FormatContext::iterator format(const sq::StackString& ss, FormatContext& ctx) const + { + return base.format(fmt::string_view(ss.data(), ss.length()), ctx); + } +}; + +#include template struct std::hash> diff --git a/include/sqee/misc/StackVector.hpp b/include/sqee/misc/StackVector.hpp index 5c322ba1..95974e39 100644 --- a/include/sqee/misc/StackVector.hpp +++ b/include/sqee/misc/StackVector.hpp @@ -5,15 +5,14 @@ #include #include +#include #include #include #include #include #include -namespace sq { - -//============================================================================// +namespace sq { //############################################################### namespace detail { @@ -29,20 +28,15 @@ template using capacity_size_t = std::conditional_t::max(), uint32_t, size_t>>>; -template -using stackvector_size_t = std::conditional_t < - sizeof(alignment_size_t) >= sizeof(capacity_size_t), - alignment_size_t, capacity_size_t >; - } // namespace detail -//============================================================================// +//============================================================================== /// Dynamically-resizable fixed-capacity vector. template -struct StackVector final +class StackVector final { -public: //====================================================// +public: //====================================================== static_assert(Capacity != 0u, "capacity must be non-zero"); @@ -58,11 +52,13 @@ struct StackVector final using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - using size_type = detail::stackvector_size_t; + using size_type = std::conditional_t < + sizeof(detail::alignment_size_t) >= sizeof(detail::capacity_size_t), + detail::alignment_size_t, detail::capacity_size_t >; static size_type capacity() { return Capacity; } - //--------------------------------------------------------// + //---------------------------------------------------------- Type* data() { return reinterpret_cast(mData); } @@ -74,7 +70,7 @@ struct StackVector final bool full() const { return mSize == Capacity; } - //--------------------------------------------------------// + //---------------------------------------------------------- iterator begin() { return data(); } const_iterator begin() const { return data(); } @@ -92,7 +88,7 @@ struct StackVector final const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return rend(); } - //--------------------------------------------------------// + //---------------------------------------------------------- template Type& emplace_back(Args&&... args) @@ -113,7 +109,7 @@ struct StackVector final emplace_back(std::move(value)); } - //--------------------------------------------------------// + //---------------------------------------------------------- template iterator emplace(iterator iter, Args&&... args) @@ -135,7 +131,7 @@ struct StackVector final return emplace(iter, std::move(value)); } - //--------------------------------------------------------// + //---------------------------------------------------------- void pop_back() { @@ -162,7 +158,7 @@ struct StackVector final return first; } - //--------------------------------------------------------// + //---------------------------------------------------------- Type& operator[](size_type pos) { assert(pos < size()); return data()[pos]; } const Type& operator[](size_type pos) const { assert(pos < size()); return data()[pos]; } @@ -173,22 +169,24 @@ struct StackVector final Type& back() { assert(!empty()); return data()[size()-1]; } const Type& back() const { assert(!empty()); return data()[size()-1]; } - //--------------------------------------------------------// + //---------------------------------------------------------- StackVector() noexcept = default; - StackVector(const StackVector& other) + StackVector(const StackVector& other) noexcept(std::is_nothrow_copy_constructible_v) { std::uninitialized_copy_n(other.data(), other.size(), data()); mSize = other.size(); } - StackVector(StackVector&& other) + StackVector(StackVector&& other) noexcept(std::is_nothrow_move_constructible_v) { std::uninitialized_move_n(other.data(), other.size(), data()); mSize = other.mSize; other.mSize = 0u; } + //---------------------------------------------------------- + StackVector(std::initializer_list il) { assert(il.size() <= capacity()); @@ -204,9 +202,9 @@ struct StackVector final emplace_back(*iter); } - //--------------------------------------------------------// + //---------------------------------------------------------- - ~StackVector() + ~StackVector() noexcept { std::destroy_n(data(), size()); } @@ -217,9 +215,9 @@ struct StackVector final mSize = 0u; } - //--------------------------------------------------------// + //---------------------------------------------------------- - StackVector& operator=(const StackVector& other) + StackVector& operator=(const StackVector& other) noexcept(std::is_nothrow_copy_constructible_v) { std::destroy_n(data(), size()); std::uninitialized_copy_n(other.data(), other.size(), data()); @@ -227,7 +225,7 @@ struct StackVector final return *this; } - StackVector& operator=(StackVector&& other) + StackVector& operator=(StackVector&& other) noexcept(std::is_nothrow_move_constructible_v) { std::destroy_n(data(), size()); std::uninitialized_move_n(other.data(), other.size(), data()); @@ -235,26 +233,38 @@ struct StackVector final return *this; } - //--------------------------------------------------------// + //---------------------------------------------------------- - auto operator<=>(const StackVector& other) const + auto operator<=>(const StackVector& other) const requires std::three_way_comparable { + // not supported by libc++ as of december 2023 + #ifdef __cpp_lib_three_way_comparison return std::lexicographical_compare_three_way(begin(), end(), other.begin(), other.end()); + #else + for (auto iterA = begin(), iterB = other.begin();;) + { + using Order = std::compare_three_way_result; + if (iterA == end() && iterB == other.end()) return Order::equivalent; + if (iterA == end()) return Order::less; + if (iterB == end()) return Order::greater; + if (Order cmp = *(iterA++) <=> *(iterB++); cmp != 0) return cmp; + } + #endif } - bool operator==(const StackVector& other) const + bool operator==(const StackVector& other) const requires std::equality_comparable { return std::equal(begin(), end(), other.begin(), other.end()); } -private: //===================================================// +private: //===================================================== size_type mSize = 0u; - std::aligned_storage_t mData[Capacity]; + alignas(Type) std::byte mData[sizeof(Type) * Capacity]; }; -//============================================================================// +//============================================================================== template inline auto erase(StackVector& container, const Value& value) @@ -274,6 +284,4 @@ inline auto erase_if(StackVector& container, Predicate pred) return distance; } -//============================================================================// - -} // namespace sq +} // namespace sq ############################################################## diff --git a/include/sqee/objects/Armature.hpp b/include/sqee/objects/Armature.hpp index a7a7ba6a..b173b453 100644 --- a/include/sqee/objects/Armature.hpp +++ b/include/sqee/objects/Armature.hpp @@ -6,7 +6,11 @@ #include #include -#include +#include + +#include +#include +#include #include // Flags @@ -112,20 +116,20 @@ class SQEE_API Armature //--------------------------------------------------------// - /// Get the index of a bone by name, throw on failure. - uint8_t get_bone_index(TinyString name) const; - - /// Get the index of a block by name, throw on failure. - uint8_t get_block_index(TinyString name) const; + /// Get the index of a bone by name, or -1 if not found. + int8_t get_bone_index(TinyString name) const noexcept; - /// Get the index of a block's track by name, throw on failure. - uint16_t get_block_track_index(uint8_t blockIndex, TinyString trackName) const; + /// Get the index of a block by name, or -1 if not found. + int8_t get_block_index(TinyString name) const noexcept; - //--------------------------------------------------------// + /// Get the index of a block track by name, or -1 if not found. + int16_t get_block_track_index(TinyString blockName, TinyString trackName) const noexcept; - int8_t bone_from_json(const JsonValue& json) const; + /// Get the index of a bone by name, or -1 if the json is null. + int8_t json_as_bone_index(JsonAny json) const; - JsonValue bone_to_json(int8_t bone) const; + /// Get the name of a bone by index, or null if the index is -1. + JsonMutAny json_from_bone_index(JsonMutDocument& document, int8_t index) const noexcept; //--------------------------------------------------------// @@ -145,16 +149,25 @@ class SQEE_API Armature //--------------------------------------------------------// + // Bone matrices are absolute transforms. Used to transform objects not + // bound to this armature, or for drawing a skeleton. + // + // Model matrices are relative to each bone's rest transform. Mainly used to + // transform the vertices of a mesh (vertex skinning). + // + // todo: Are there better terms for these? Using the same terms as blender + // would probably be a good idea. + /// Compute the absolute transform of a bone. Mat4F compute_bone_matrix(const AnimSample& sample, uint8_t index) const; - /// Compute the absolute transforms for all bones. - std::vector compute_skeleton_matrices(const AnimSample& sample) const; + /// Compute the absolute transforms of all bones. + std::vector compute_bone_matrices(const AnimSample& sample) const; - /// Compute the model matrix of a single bone. + /// Compute the transform of a bone. Mat4F compute_model_matrix(const AnimSample& sample, Mat4F modelMatrix, uint8_t index) const; - /// Compute model matrices for all bones, transposed for shaders. + /// Compute the transforms of all bones, transposed for shaders. void compute_model_matrices ( const AnimSample& sample, Mat4F viewMatrix, Mat4F invViewMatrix, Mat4F modelMatrix, Vec2F billboardScale, Mat34F* modelMats, size_t len ) const; diff --git a/include/sqee/objects/DrawItem.hpp b/include/sqee/objects/DrawItem.hpp index 2f1f7b2c..e16a16a5 100644 --- a/include/sqee/objects/DrawItem.hpp +++ b/include/sqee/objects/DrawItem.hpp @@ -25,11 +25,11 @@ class Texture; struct SQEE_API DrawItem { using MeshCache = ResourceCache; - using PipelineCache = ResourceCache; + using PipelineCache = ResourceCache; using TextureCache = ResourceCache; using MeshHandle = Handle; - using PipelineHandle = Handle; + using PipelineHandle = Handle; using TextureHandle = Handle; /// Type of a push constant block member, and how to compute it. @@ -37,11 +37,20 @@ struct SQEE_API DrawItem { ConstFloat, ConstFloat2, ConstFloat3, ConstFloat4, // float / vec2 / vec3 / vec4 ConstInt, ConstInt2, ConstInt3, ConstInt4, // int / ivec2 / ivec3 / ivec4 - ModelMatrixIndex, NormalMatrixIndex, // uint / uint + ConstPackedBits, // uint + ModelMatIndex, NormalMatIndex, // uint / uint TextureIndex, // uint AnimFloat, AnimFloat2, AnimFloat3, AnimFloat4, // float / vec2 / vec3 / vec4 AnimInt, AnimInt2, AnimInt3, AnimInt4, // int / ivec2 / ivec3 / ivec4 - AnimTextureTransform, // mat2x3 + ConstTexTransform, AnimTexTransform, // mat2x3 / mat2x3 + }; + + /// Type of sample value to use for visibility. + enum class VisDataType : uint8_t + { + None, // always visible + Float, // 0.0 == not visible + Int, // 0 == not visible }; /// Data needed to compute one member of a push constant block. @@ -53,7 +62,8 @@ struct SQEE_API DrawItem { float constFloat; Vec2F constFloat2; Vec3F constFloat3; Vec4F constFloat4; int constInt; Vec2I constInt2; Vec3I constInt3; Vec4I constInt4; - uint matrixIndex; TextureHandle texture; uint sampleOffset; uint sampleOffsets[3]; + uint32_t constPackedBits; uint matrixIndex; TextureHandle texture; + uint sampleOffset; float constFloat2x3[2][3]; uint sampleOffsets[3]; }; Param() @@ -95,14 +105,18 @@ struct SQEE_API DrawItem } }; - // todo: move defs into named groups that can be enabled or disabled in wren TinyString condition; MeshHandle mesh; PipelineHandle pipeline; + int16_t order = 0; + int8_t subMesh = -1; + VisDataType visDataType = {}; + uint visSampleOffset = 0u; + std::vector params; /// Load resources and draw items from a Render.json file. @@ -110,6 +124,9 @@ struct SQEE_API DrawItem const String& path, const Armature& armature, MeshCache& meshes, PipelineCache& pipelines, TextureCache& textures ); + /// Check if the draw item should be drawn. + bool check_visibility(const AnimSample& sample) const; + /// Extract params from an animation sample for use as push constants. void compute_push_constants ( const AnimSample& sample, uint modelMatsIndex, uint normalMatsIndex, std::array& out @@ -125,9 +142,10 @@ SQEE_ENUM_HELPER sq::DrawItem::ParamType, ConstFloat, ConstFloat2, ConstFloat3, ConstFloat4, ConstInt, ConstInt2, ConstInt3, ConstInt4, - ModelMatrixIndex, NormalMatrixIndex, + ConstPackedBits, + ModelMatIndex, NormalMatIndex, TextureIndex, AnimFloat, AnimFloat2, AnimFloat3, AnimFloat4, AnimInt, AnimInt2, AnimInt3, AnimInt4, - AnimTextureTransform + ConstTexTransform, AnimTexTransform ) diff --git a/include/sqee/objects/Mesh.hpp b/include/sqee/objects/Mesh.hpp index b175774a..8411669c 100644 --- a/include/sqee/objects/Mesh.hpp +++ b/include/sqee/objects/Mesh.hpp @@ -62,8 +62,13 @@ class SQEE_API Mesh //--------------------------------------------------------// - /// Get the index of sub mesh by name, throw on failure. - uint8_t get_sub_mesh_index(TinyString name) const; + /// Get the index of a sub mesh by name, or -1 if not found. + int8_t get_sub_mesh_index(TinyString name) const noexcept; + + /// Get the index of a sub mesh by name, or -1 if the json is null. + int8_t json_as_sub_mesh_index(JsonAny json) const; + + //--------------------------------------------------------// /// Bind vertex and index buffers. void bind_buffers(vk::CommandBuffer cmdbuf) const; diff --git a/include/sqee/objects/Pipeline.hpp b/include/sqee/objects/Pipeline.hpp index 409079dd..4c07479a 100644 --- a/include/sqee/objects/Pipeline.hpp +++ b/include/sqee/objects/Pipeline.hpp @@ -31,10 +31,12 @@ class SQEE_API Pipeline Mat23F, Mat34F, Mat4F }; - struct PushConstantInfo + struct PushConstant { + SmallString name; PushConstantType type; uint8_t offset; + bool vertex, fragment; }; //--------------------------------------------------------// @@ -50,8 +52,8 @@ class SQEE_API Pipeline //--------------------------------------------------------// - /// Load the pipeline from a json object. - void load_from_json(const JsonValue& json, const PassConfigMap& passes); + /// Load the pipeline from a minified json string. + void load_from_minified_json(const String& minified, const PassConfigMap& passes); /// Bind the pipeline for rendering. void bind(vk::CommandBuffer cmdbuf) const; @@ -64,7 +66,7 @@ class SQEE_API Pipeline vk::Pipeline get_pipeline() const { return mPipeline; } - PushConstantInfo get_push_constant_info(SmallString name) const; + const std::vector& get_push_constants() const { return mPushConstants; } protected: //=================================================// @@ -72,7 +74,7 @@ class SQEE_API Pipeline vk::Pipeline mPipeline; - std::map mPushConstantMap; + std::vector mPushConstants; }; //============================================================================// diff --git a/include/sqee/redist/expected.hpp b/include/sqee/redist/expected.hpp new file mode 100644 index 00000000..afee404d --- /dev/null +++ b/include/sqee/redist/expected.hpp @@ -0,0 +1,2444 @@ +/// +// expected - An implementation of std::expected with extensions +// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama) +// +// Documentation available at http://tl.tartanllama.xyz/ +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. If not, see +// . +/// + +#ifndef TL_EXPECTED_HPP +#define TL_EXPECTED_HPP + +#define TL_EXPECTED_VERSION_MAJOR 1 +#define TL_EXPECTED_VERSION_MINOR 1 +#define TL_EXPECTED_VERSION_PATCH 0 + +#include +#include +#include +#include + +#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) +#define TL_EXPECTED_EXCEPTIONS_ENABLED +#endif + +#if (defined(_MSC_VER) && _MSC_VER == 1900) +#define TL_EXPECTED_MSVC2015 +#define TL_EXPECTED_MSVC2015_CONSTEXPR +#else +#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC49 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC54 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC55 +#endif + +#if !defined(TL_ASSERT) +//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug +#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49) +#include +#define TL_ASSERT(x) assert(x) +#else +#define TL_ASSERT(x) +#endif +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ + !defined(__clang__)) +// GCC < 5 doesn't support overloading on const&& for member functions + +#define TL_EXPECTED_NO_CONSTRR +// GCC < 5 doesn't support some standard C++11 type traits +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::has_trivial_copy_constructor +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::has_trivial_copy_assign + +// This one will be different for GCC 5.7 if it's ever supported +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible + +// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks +// std::vector for non-copyable types +#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) +#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +namespace tl { +namespace detail { +template +struct is_trivially_copy_constructible + : std::is_trivially_copy_constructible {}; +#ifdef _GLIBCXX_VECTOR +template +struct is_trivially_copy_constructible> : std::false_type {}; +#endif +} // namespace detail +} // namespace tl +#endif + +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + tl::detail::is_trivially_copy_constructible +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::is_trivially_copy_assignable +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible +#else +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::is_trivially_copy_constructible +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::is_trivially_copy_assignable +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible +#endif + +#if __cplusplus > 201103L +#define TL_EXPECTED_CXX14 +#endif + +#ifdef TL_EXPECTED_GCC49 +#define TL_EXPECTED_GCC49_CONSTEXPR +#else +#define TL_EXPECTED_GCC49_CONSTEXPR constexpr +#endif + +#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ + defined(TL_EXPECTED_GCC49)) +#define TL_EXPECTED_11_CONSTEXPR +#else +#define TL_EXPECTED_11_CONSTEXPR constexpr +#endif + +namespace tl { +template class expected; + +#ifndef TL_MONOSTATE_INPLACE_MUTEX +#define TL_MONOSTATE_INPLACE_MUTEX +class monostate {}; + +struct in_place_t { + explicit in_place_t() = default; +}; +static constexpr in_place_t in_place{}; +#endif + +template class unexpected { +public: + static_assert(!std::is_same::value, "E must not be void"); + + unexpected() = delete; + constexpr explicit unexpected(const E &e) : m_val(e) {} + + constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} + + template ::value>::type * = nullptr> + constexpr explicit unexpected(Args &&...args) + : m_val(std::forward(args)...) {} + template < + class U, class... Args, + typename std::enable_if &, Args &&...>::value>::type * = nullptr> + constexpr explicit unexpected(std::initializer_list l, Args &&...args) + : m_val(l, std::forward(args)...) {} + + constexpr const E &value() const & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } + constexpr const E &&value() const && { return std::move(m_val); } + +private: + E m_val; +}; + +#ifdef __cpp_deduction_guides +template unexpected(E) -> unexpected; +#endif + +template +constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() == rhs.value(); +} +template +constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() != rhs.value(); +} +template +constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() < rhs.value(); +} +template +constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() <= rhs.value(); +} +template +constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() > rhs.value(); +} +template +constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() >= rhs.value(); +} + +template +unexpected::type> make_unexpected(E &&e) { + return unexpected::type>(std::forward(e)); +} + +struct unexpect_t { + unexpect_t() = default; +}; +static constexpr unexpect_t unexpect{}; + +namespace detail { +template +[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + throw std::forward(e); +#else + (void)e; +#ifdef _MSC_VER + __assume(0); +#else + __builtin_unreachable(); +#endif +#endif +} + +#ifndef TL_TRAITS_MUTEX +#define TL_TRAITS_MUTEX +// C++14-style aliases for brevity +template using remove_const_t = typename std::remove_const::type; +template +using remove_reference_t = typename std::remove_reference::type; +template using decay_t = typename std::decay::type; +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; + +// std::conjunction from C++17 +template struct conjunction : std::true_type {}; +template struct conjunction : B {}; +template +struct conjunction + : std::conditional, B>::type {}; + +#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L +#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND +#endif + +// In C++11 mode, there's an issue in libc++'s std::mem_fn +// which results in a hard-error when using it in a noexcept expression +// in some cases. This is a check to workaround the common failing case. +#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND +template +struct is_pointer_to_non_const_member_func : std::false_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; + +template struct is_const_or_const_ref : std::false_type {}; +template struct is_const_or_const_ref : std::true_type {}; +template struct is_const_or_const_ref : std::true_type {}; +#endif + +// std::invoke from C++17 +// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround +template < + typename Fn, typename... Args, +#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND + typename = enable_if_t::value && + is_const_or_const_ref::value)>, +#endif + typename = enable_if_t>::value>, int = 0> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( + noexcept(std::mem_fn(f)(std::forward(args)...))) + -> decltype(std::mem_fn(f)(std::forward(args)...)) { + return std::mem_fn(f)(std::forward(args)...); +} + +template >::value>> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( + noexcept(std::forward(f)(std::forward(args)...))) + -> decltype(std::forward(f)(std::forward(args)...)) { + return std::forward(f)(std::forward(args)...); +} + +// std::invoke_result from C++17 +template struct invoke_result_impl; + +template +struct invoke_result_impl< + F, + decltype(detail::invoke(std::declval(), std::declval()...), void()), + Us...> { + using type = + decltype(detail::invoke(std::declval(), std::declval()...)); +}; + +template +using invoke_result = invoke_result_impl; + +template +using invoke_result_t = typename invoke_result::type; + +#if defined(_MSC_VER) && _MSC_VER <= 1900 +// TODO make a version which works with MSVC 2015 +template struct is_swappable : std::true_type {}; + +template struct is_nothrow_swappable : std::true_type {}; +#else +// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept +namespace swap_adl_tests { +// if swap ADL finds this then it would call std::swap otherwise (same +// signature) +struct tag {}; + +template tag swap(T &, T &); +template tag swap(T (&a)[N], T (&b)[N]); + +// helper functions to test if an unqualified swap is possible, and if it +// becomes std::swap +template std::false_type can_swap(...) noexcept(false); +template (), std::declval()))> +std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), + std::declval()))); + +template std::false_type uses_std(...); +template +std::is_same(), std::declval())), tag> +uses_std(int); + +template +struct is_std_swap_noexcept + : std::integral_constant::value && + std::is_nothrow_move_assignable::value> {}; + +template +struct is_std_swap_noexcept : is_std_swap_noexcept {}; + +template +struct is_adl_swap_noexcept + : std::integral_constant(0))> {}; +} // namespace swap_adl_tests + +template +struct is_swappable + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std(0))::value || + (std::is_move_assignable::value && + std::is_move_constructible::value))> {}; + +template +struct is_swappable + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std( + 0))::value || + is_swappable::value)> {}; + +template +struct is_nothrow_swappable + : std::integral_constant< + bool, + is_swappable::value && + ((decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_std_swap_noexcept::value) || + (!decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; +#endif +#endif + +// Trait for checking if a type is a tl::expected +template struct is_expected_impl : std::false_type {}; +template +struct is_expected_impl> : std::true_type {}; +template using is_expected = is_expected_impl>; + +template +using expected_enable_forward_value = detail::enable_if_t< + std::is_constructible::value && + !std::is_same, in_place_t>::value && + !std::is_same, detail::decay_t>::value && + !std::is_same, detail::decay_t>::value>; + +template +using expected_enable_from_other = detail::enable_if_t< + std::is_constructible::value && + std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value>; + +template +using is_void_or = conditional_t::value, std::true_type, U>; + +template +using is_copy_constructible_or_void = + is_void_or>; + +template +using is_move_constructible_or_void = + is_void_or>; + +template +using is_copy_assignable_or_void = is_void_or>; + +template +using is_move_assignable_or_void = is_void_or>; + +} // namespace detail + +namespace detail { +struct no_init_t {}; +static constexpr no_init_t no_init{}; + +// Implements the storage of the values, and ensures that the destructor is +// trivial if it can be. +// +// This specialization is for where neither `T` or `E` is trivially +// destructible, so the destructors must be called on destruction of the +// `expected` +template ::value, + bool = std::is_trivially_destructible::value> +struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } else { + m_unexpect.~unexpected(); + } + } + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// This specialization is for when both `T` and `E` are trivially-destructible, +// so the destructor of the `expected` can be trivial. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// T is trivial, E is not. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) + : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// E is trivial, T is not. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } + } + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// `T` is `void`, `E` is trivially-destructible +template struct expected_storage_base { + #if __GNUC__ <= 5 + //no constexpr for GCC 4/5 bug + #else + TL_EXPECTED_MSVC2015_CONSTEXPR + #endif + expected_storage_base() : m_has_val(true) {} + + constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} + + constexpr expected_storage_base(in_place_t) : m_has_val(true) {} + + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + struct dummy {}; + union { + unexpected m_unexpect; + dummy m_val; + }; + bool m_has_val; +}; + +// `T` is `void`, `E` is not trivially-destructible +template struct expected_storage_base { + constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} + + constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} + + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + unexpected m_unexpect; + char m_dummy; + }; + bool m_has_val; +}; + +// This base class provides some handy member functions which can be used in +// further derived classes +template +struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; + + template void construct(Args &&...args) noexcept { + new (std::addressof(this->m_val)) T(std::forward(args)...); + this->m_has_val = true; + } + + template void construct_with(Rhs &&rhs) noexcept { + new (std::addressof(this->m_val)) T(std::forward(rhs).get()); + this->m_has_val = true; + } + + template void construct_error(Args &&...args) noexcept { + new (std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + + // These assign overloads ensure that the most efficient assignment + // implementation is used while maintaining the strong exception guarantee. + // The problematic case is where rhs has a value, but *this does not. + // + // This overload handles the case where we can just copy-construct `T` + // directly into place without throwing. + template ::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } + + // This overload handles the case where we can attempt to create a copy of + // `T`, then no-throw move it into place if the copy was successful. + template ::value && + std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + T tmp = rhs.get(); + geterr().~unexpected(); + construct(std::move(tmp)); + } else { + assign_common(rhs); + } + } + + // This overload is the worst-case, where we have to move-construct the + // unexpected value into temporary storage, then try to copy the T into place. + // If the construction succeeds, then everything is fine, but if it throws, + // then we move the old unexpected value back into place before rethrowing the + // exception. + template ::value && + !std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + construct(rhs.get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } +#else + construct(rhs.get()); +#endif + } else { + assign_common(rhs); + } + } + + // These overloads do the same as above, but for rvalues + template ::value> + * = nullptr> + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(std::move(rhs)); + } + } + + template ::value> + * = nullptr> + void assign(expected_operations_base &&rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + construct(std::move(rhs).get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } +#else + construct(std::move(rhs).get()); +#endif + } else { + assign_common(std::move(rhs)); + } + } + +#else + + // If exceptions are disabled then we can just copy-construct + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } + + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(std::move(rhs)); + } + } + +#endif + + // The common part of move/copy assigning + template void assign_common(Rhs &&rhs) { + if (this->m_has_val) { + if (rhs.m_has_val) { + get() = std::forward(rhs).get(); + } else { + destroy_val(); + construct_error(std::forward(rhs).geterr()); + } + } else { + if (!rhs.m_has_val) { + geterr() = std::forward(rhs).geterr(); + } + } + } + + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } + constexpr const T &get() const & { return this->m_val; } + TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const T &&get() const && { return std::move(this->m_val); } +#endif + + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + return this->m_unexpect; + } + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + return std::move(this->m_unexpect); + } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const unexpected &&geterr() const && { + return std::move(this->m_unexpect); + } +#endif + + TL_EXPECTED_11_CONSTEXPR void destroy_val() { get().~T(); } +}; + +// This base class provides some handy member functions which can be used in +// further derived classes +template +struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; + + template void construct() noexcept { this->m_has_val = true; } + + // This function doesn't use its argument, but needs it so that code in + // levels above this can work independently of whether T is void + template void construct_with(Rhs &&) noexcept { + this->m_has_val = true; + } + + template void construct_error(Args &&...args) noexcept { + new (std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } + + template void assign(Rhs &&rhs) noexcept { + if (!this->m_has_val) { + if (rhs.m_has_val) { + geterr().~unexpected(); + construct(); + } else { + geterr() = std::forward(rhs).geterr(); + } + } else { + if (!rhs.m_has_val) { + construct_error(std::forward(rhs).geterr()); + } + } + } + + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + return this->m_unexpect; + } + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + return std::move(this->m_unexpect); + } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const unexpected &&geterr() const && { + return std::move(this->m_unexpect); + } +#endif + + TL_EXPECTED_11_CONSTEXPR void destroy_val() { + // no-op + } +}; + +// This class manages conditionally having a trivial copy constructor +// This specialization is for when T and E are trivially copy constructible +template :: + value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; +}; + +// This specialization is for when T or E are not trivially copy constructible +template +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; + + expected_copy_base() = default; + expected_copy_base(const expected_copy_base &rhs) + : expected_operations_base(no_init) { + if (rhs.has_value()) { + this->construct_with(rhs); + } else { + this->construct_error(rhs.geterr()); + } + } + + expected_copy_base(expected_copy_base &&rhs) = default; + expected_copy_base &operator=(const expected_copy_base &rhs) = default; + expected_copy_base &operator=(expected_copy_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial move constructor +// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it +// doesn't implement an analogue to std::is_trivially_move_constructible. We +// have to make do with a non-trivial move constructor even if T is trivially +// move constructible +#ifndef TL_EXPECTED_GCC49 +template >::value + &&std::is_trivially_move_constructible::value> +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; +}; +#else +template struct expected_move_base; +#endif +template +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; + + expected_move_base() = default; + expected_move_base(const expected_move_base &rhs) = default; + + expected_move_base(expected_move_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value) + : expected_copy_base(no_init) { + if (rhs.has_value()) { + this->construct_with(std::move(rhs)); + } else { + this->construct_error(std::move(rhs.geterr())); + } + } + expected_move_base &operator=(const expected_move_base &rhs) = default; + expected_move_base &operator=(expected_move_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial copy assignment operator +template >::value + &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value + &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value + &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; +}; + +template +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; + + expected_copy_assign_base() = default; + expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; + + expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; + expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { + this->assign(rhs); + return *this; + } + expected_copy_assign_base & + operator=(expected_copy_assign_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial move assignment operator +// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it +// doesn't implement an analogue to std::is_trivially_move_assignable. We have +// to make do with a non-trivial move assignment operator even if T is trivially +// move assignable +#ifndef TL_EXPECTED_GCC49 +template , + std::is_trivially_move_constructible, + std::is_trivially_move_assignable>>:: + value &&std::is_trivially_destructible::value + &&std::is_trivially_move_constructible::value + &&std::is_trivially_move_assignable::value> +struct expected_move_assign_base : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; +}; +#else +template struct expected_move_assign_base; +#endif + +template +struct expected_move_assign_base + : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; + + expected_move_assign_base() = default; + expected_move_assign_base(const expected_move_assign_base &rhs) = default; + + expected_move_assign_base(expected_move_assign_base &&rhs) = default; + + expected_move_assign_base & + operator=(const expected_move_assign_base &rhs) = default; + + expected_move_assign_base & + operator=(expected_move_assign_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value + &&std::is_nothrow_move_assignable::value) { + this->assign(std::move(rhs)); + return *this; + } +}; + +// expected_delete_ctor_base will conditionally delete copy and move +// constructors depending on whether T is copy/move constructible +template ::value && + std::is_copy_constructible::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value)> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +// expected_delete_assign_base will conditionally delete copy and move +// constructors depending on whether T and E are copy/move constructible + +// assignable +template ::value && + std::is_copy_constructible::value && + is_copy_assignable_or_void::value && + std::is_copy_assignable::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value && + is_move_assignable_or_void::value && + std::is_move_assignable::value)> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; +}; + +// This is needed to be able to construct the expected_default_ctor_base which +// follows, while still conditionally deleting the default constructor. +struct default_constructor_tag { + explicit constexpr default_constructor_tag() = default; +}; + +// expected_default_ctor_base will ensure that expected has a deleted default +// consturctor if T is not default constructible. +// This specialization is for when T is default constructible +template ::value || std::is_void::value> +struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = default; + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; + +// This specialization is for when T is not default constructible +template struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = delete; + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; +} // namespace detail + +template class bad_expected_access : public std::exception { +public: + explicit bad_expected_access(E e) : m_val(std::move(e)) {} + + virtual const char *what() const noexcept override { + return "Bad expected access"; + } + + const E &error() const & { return m_val; } + E &error() & { return m_val; } + const E &&error() const && { return std::move(m_val); } + E &&error() && { return std::move(m_val); } + +private: + E m_val; +}; + +/// An `expected` object is an object that contains the storage for +/// another object and manages the lifetime of this contained object `T`. +/// Alternatively it could contain the storage for another unexpected object +/// `E`. The contained object may not be initialized after the expected object +/// has been initialized, and may not be destroyed before the expected object +/// has been destroyed. The initialization state of the contained object is +/// tracked by the expected object. +template +class expected : private detail::expected_move_assign_base, + private detail::expected_delete_ctor_base, + private detail::expected_delete_assign_base, + private detail::expected_default_ctor_base { + static_assert(!std::is_reference::value, "T must not be a reference"); + static_assert(!std::is_same::type>::value, + "T must not be in_place_t"); + static_assert(!std::is_same::type>::value, + "T must not be unexpect_t"); + static_assert( + !std::is_same>::type>::value, + "T must not be unexpected"); + static_assert(!std::is_reference::value, "E must not be a reference"); + + T *valptr() { return std::addressof(this->m_val); } + const T *valptr() const { return std::addressof(this->m_val); } + unexpected *errptr() { return std::addressof(this->m_unexpect); } + const unexpected *errptr() const { + return std::addressof(this->m_unexpect); + } + + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &val() { + return this->m_val; + } + TL_EXPECTED_11_CONSTEXPR unexpected &err() { return this->m_unexpect; } + + template ::value> * = nullptr> + constexpr const U &val() const { + return this->m_val; + } + constexpr const unexpected &err() const { return this->m_unexpect; } + + using impl_base = detail::expected_move_assign_base; + using ctor_base = detail::expected_default_ctor_base; + +public: + typedef T value_type; + typedef E error_type; + typedef unexpected unexpected_type; + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { + return and_then_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { + return and_then_impl(std::move(*this), std::forward(f)); + } + template constexpr auto and_then(F &&f) const & { + return and_then_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template constexpr auto and_then(F &&f) const && { + return and_then_impl(std::move(*this), std::forward(f)); + } +#endif + +#else + template + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) & -> decltype(and_then_impl(std::declval(), + std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) && -> decltype(and_then_impl(std::declval(), + std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } + template + constexpr auto and_then(F &&f) const & -> decltype(and_then_impl( + std::declval(), std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr auto and_then(F &&f) const && -> decltype(and_then_impl( + std::declval(), std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template constexpr auto map(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + template constexpr auto map(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + map(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template constexpr auto transform(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + template constexpr auto transform(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + transform(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template constexpr auto map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + template constexpr auto map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif +#endif +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template constexpr auto transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + template constexpr auto transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + return or_else_impl(*this, std::forward(f)); + } + + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + return or_else_impl(std::move(*this), std::forward(f)); + } + + template expected constexpr or_else(F &&f) const & { + return or_else_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template expected constexpr or_else(F &&f) const && { + return or_else_impl(std::move(*this), std::forward(f)); + } +#endif + constexpr expected() = default; + constexpr expected(const expected &rhs) = default; + constexpr expected(expected &&rhs) = default; + expected &operator=(const expected &rhs) = default; + expected &operator=(expected &&rhs) = default; + + template ::value> * = + nullptr> + constexpr expected(in_place_t, Args &&...args) + : impl_base(in_place, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args &&...args) + : impl_base(in_place, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value> * = + nullptr, + detail::enable_if_t::value> * = + nullptr> + explicit constexpr expected(const unexpected &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected const &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + explicit constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value> * = + nullptr> + constexpr explicit expected(unexpect_t, Args &&...args) + : impl_base(unexpect, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected(unexpect_t, std::initializer_list il, + Args &&...args) + : impl_base(unexpect, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other + * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template ::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other + * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template < + class U, class G, + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template < + class U, class G, + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} + + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} + + template < + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + err().~unexpected(); + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; + } + + return *this; + } + + template < + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; +#endif + } + + return *this; + } + + template ::value && + std::is_assignable::value> * = nullptr> + expected &operator=(const unexpected &rhs) { + if (!has_value()) { + err() = rhs; + } else { + this->destroy_val(); + ::new (errptr()) unexpected(rhs); + this->m_has_val = false; + } + + return *this; + } + + template ::value && + std::is_move_assignable::value> * = nullptr> + expected &operator=(unexpected &&rhs) noexcept { + if (!has_value()) { + err() = std::move(rhs); + } else { + this->destroy_val(); + ::new (errptr()) unexpected(std::move(rhs)); + this->m_has_val = false; + } + + return *this; + } + + template ::value> * = nullptr> + void emplace(Args &&...args) { + if (has_value()) { + val().~T(); + } else { + err().~unexpected(); + this->m_has_val = true; + } + ::new (valptr()) T(std::forward(args)...); + } + + template ::value> * = nullptr> + void emplace(Args &&...args) { + if (has_value()) { + val().~T(); + ::new (valptr()) T(std::forward(args)...); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::forward(args)...); + this->m_has_val = true; +#endif + } + } + + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + err().~unexpected(); + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } + } + + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; +#endif + } + } + +private: + using t_is_void = std::true_type; + using t_is_not_void = std::false_type; + using t_is_nothrow_move_constructible = std::true_type; + using move_constructing_t_can_throw = std::false_type; + using e_is_nothrow_move_constructible = std::true_type; + using move_constructing_e_can_throw = std::false_type; + + void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept { + // swapping void is a no-op + } + + void swap_where_both_have_value(expected &rhs, t_is_not_void) { + using std::swap; + swap(val(), rhs.val()); + } + + void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept( + std::is_nothrow_move_constructible::value) { + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + std::swap(this->m_has_val, rhs.m_has_val); + } + + void swap_where_only_one_has_value(expected &rhs, t_is_not_void) { + swap_where_only_one_has_value_and_t_is_not_void( + rhs, typename std::is_nothrow_move_constructible::type{}, + typename std::is_nothrow_move_constructible::type{}); + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, t_is_nothrow_move_constructible, + e_is_nothrow_move_constructible) noexcept { + auto temp = std::move(val()); + val().~T(); + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, t_is_nothrow_move_constructible, + move_constructing_e_can_throw) { + auto temp = std::move(val()); + val().~T(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } catch (...) { + val() = std::move(temp); + throw; + } +#else + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); +#endif + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, move_constructing_t_can_throw, + e_is_nothrow_move_constructible) { + auto temp = std::move(rhs.err()); + rhs.err().~unexpected_type(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (rhs.valptr()) T(std::move(val())); + val().~T(); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } catch (...) { + rhs.err() = std::move(temp); + throw; + } +#else + ::new (rhs.valptr()) T(std::move(val())); + val().~T(); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); +#endif + } + +public: + template + detail::enable_if_t::value && + detail::is_swappable::value && + (std::is_nothrow_move_constructible::value || + std::is_nothrow_move_constructible::value)> + swap(expected &rhs) noexcept( + std::is_nothrow_move_constructible::value + &&detail::is_nothrow_swappable::value + &&std::is_nothrow_move_constructible::value + &&detail::is_nothrow_swappable::value) { + if (has_value() && rhs.has_value()) { + swap_where_both_have_value(rhs, typename std::is_void::type{}); + } else if (!has_value() && rhs.has_value()) { + rhs.swap(*this); + } else if (has_value()) { + swap_where_only_one_has_value(rhs, typename std::is_void::type{}); + } else { + using std::swap; + swap(err(), rhs.err()); + } + } + + constexpr const T *operator->() const { + TL_ASSERT(has_value()); + return valptr(); + } + TL_EXPECTED_11_CONSTEXPR T *operator->() { + TL_ASSERT(has_value()); + return valptr(); + } + + template ::value> * = nullptr> + constexpr const U &operator*() const & { + TL_ASSERT(has_value()); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &operator*() & { + TL_ASSERT(has_value()); + return val(); + } + template ::value> * = nullptr> + constexpr const U &&operator*() const && { + TL_ASSERT(has_value()); + return std::move(val()); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&operator*() && { + TL_ASSERT(has_value()); + return std::move(val()); + } + + constexpr bool has_value() const noexcept { return this->m_has_val; } + constexpr explicit operator bool() const noexcept { return this->m_has_val; } + + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &value() const & { + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &value() & { + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &&value() const && { + if (!has_value()) + detail::throw_exception(bad_expected_access(std::move(err()).value())); + return std::move(val()); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&value() && { + if (!has_value()) + detail::throw_exception(bad_expected_access(std::move(err()).value())); + return std::move(val()); + } + + constexpr const E &error() const & { + TL_ASSERT(!has_value()); + return err().value(); + } + TL_EXPECTED_11_CONSTEXPR E &error() & { + TL_ASSERT(!has_value()); + return err().value(); + } + constexpr const E &&error() const && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } + TL_EXPECTED_11_CONSTEXPR E &&error() && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } + + template constexpr T value_or(U &&v) const & { + static_assert(std::is_copy_constructible::value && + std::is_convertible::value, + "T must be copy-constructible and convertible to from U&&"); + return bool(*this) ? **this : static_cast(std::forward(v)); + } + template TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { + static_assert(std::is_move_constructible::value && + std::is_convertible::value, + "T must be move-constructible and convertible to from U&&"); + return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); + } +}; + +namespace detail { +template using exp_t = typename detail::decay_t::value_type; +template using err_t = typename detail::decay_t::error_type; +template using ret_t = expected>; + +#ifdef TL_EXPECTED_CXX14 +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval()))> +constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval()))> +constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); +} +#else +template struct TC; +template (), + *std::declval())), + detail::enable_if_t>::value> * = nullptr> +auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); +} + +template ())), + detail::enable_if_t>::value> * = nullptr> +constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); +} +#endif + +#ifdef TL_EXPECTED_CXX14 +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return result(); + } + + return result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return result(); + } + + return result(unexpect, std::forward(exp).error()); +} +#else +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + +constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; + + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return {}; + } + + return unexpected>(std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + +constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; + + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return {}; + } + + return unexpected>(std::forward(exp).error()); +} +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +#else +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; + + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; + + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +#endif + +#ifdef TL_EXPECTED_CXX14 +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto or_else_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); +} + +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); +} +#else +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto or_else_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); +} + +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); +} +#endif +} // namespace detail + +template +constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); +} +template +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); +} +template +constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : true); +} +template +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() == rhs.error() : false); +} + +template +constexpr bool operator==(const expected &x, const U &v) { + return x.has_value() ? *x == v : false; +} +template +constexpr bool operator==(const U &v, const expected &x) { + return x.has_value() ? *x == v : false; +} +template +constexpr bool operator!=(const expected &x, const U &v) { + return x.has_value() ? *x != v : true; +} +template +constexpr bool operator!=(const U &v, const expected &x) { + return x.has_value() ? *x != v : true; +} + +template +constexpr bool operator==(const expected &x, const unexpected &e) { + return x.has_value() ? false : x.error() == e.value(); +} +template +constexpr bool operator==(const unexpected &e, const expected &x) { + return x.has_value() ? false : x.error() == e.value(); +} +template +constexpr bool operator!=(const expected &x, const unexpected &e) { + return x.has_value() ? true : x.error() != e.value(); +} +template +constexpr bool operator!=(const unexpected &e, const expected &x) { + return x.has_value() ? true : x.error() != e.value(); +} + +template ::value || + std::is_move_constructible::value) && + detail::is_swappable::value && + std::is_move_constructible::value && + detail::is_swappable::value> * = nullptr> +void swap(expected &lhs, + expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { + lhs.swap(rhs); +} +} // namespace tl + +#endif diff --git a/include/sqee/redist/json.hpp b/include/sqee/redist/json.hpp deleted file mode 100644 index a1dc5aaf..00000000 --- a/include/sqee/redist/json.hpp +++ /dev/null @@ -1,24611 +0,0 @@ -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - -/****************************************************************************\ - * Note on documentation: The source files contain links to the online * - * documentation of the public API at https://json.nlohmann.me. This URL * - * contains the most recent documentation and should also be applicable to * - * previous versions; documentation for deprecated functions is not * - * removed, but marked deprecated. See "Generate documentation" section in * - * file docs/README.md. * -\****************************************************************************/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#ifndef JSON_NO_IO - #include // istream, ostream -#endif // JSON_NO_IO -#include // random_access_iterator_tag -#include // unique_ptr -#include // accumulate -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// This file contains all macro definitions affecting or depending on the ABI - -#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 - #warning "Already included a different version of the library!" - #endif - #endif -#endif - -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) - -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - -#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 -#endif - -#if JSON_DIAGNOSTICS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag -#else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS -#endif - -#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp -#else - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 -#endif - -// Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) - -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) - -// Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) - -#if NLOHMANN_JSON_NAMESPACE_NO_VERSION -#define NLOHMANN_JSON_NAMESPACE_VERSION -#else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) -#endif - -// Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) - -#ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ - { -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann -#endif - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // nullptr_t -#include // exception -#include // runtime_error -#include // to_string -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // declval, pair -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -// https://en.cppreference.com/w/cpp/experimental/is_detected -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson -// SPDX-License-Identifier: MIT - -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 15 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #undef JSON_HEDLEY_MCST_LCC_VERSION -#endif -#if defined(__LCC__) && defined(__LCC_MINOR__) - #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) - #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_CRAY_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) && \ - !defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if \ - defined(__has_attribute) && \ - ( \ - (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ - ) -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions (except those affecting ABI) -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// #include - - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -// if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 -#endif - -#ifdef __has_include - #if __has_include() - #include - #endif -#endif - -#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) - #ifdef JSON_HAS_CPP_17 - #if defined(__cpp_lib_filesystem) - #define JSON_HAS_FILESYSTEM 1 - #elif defined(__cpp_lib_experimental_filesystem) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif !defined(__has_include) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #endif - - // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ - #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__clang_major__) && __clang_major__ < 7 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1914 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before iOS 13 - #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before macOS Catalina - #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - #endif -#endif - -#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_FILESYSTEM - #define JSON_HAS_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_THREE_WAY_COMPARISON - #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ - && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L - #define JSON_HAS_THREE_WAY_COMPARISON 1 - #else - #define JSON_HAS_THREE_WAY_COMPARISON 0 - #endif -#endif - -#ifndef JSON_HAS_RANGES - // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error - #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 - #define JSON_HAS_RANGES 0 - #elif defined(__cpp_lib_ranges) - #define JSON_HAS_RANGES 1 - #else - #define JSON_HAS_RANGES 0 - #endif -#endif - -#ifdef JSON_HAS_CPP_17 - #define JSON_INLINE_VARIABLE inline -#else - #define JSON_INLINE_VARIABLE -#endif - -#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) - #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] -#else - #define JSON_NO_UNIQUE_ADDRESS -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -#endif - -// allow disabling exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow overriding assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); -#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - - -// inspired from https://stackoverflow.com/a/26745591 -// allows to call any std function as if (e.g. with begin): -// using std::begin; begin(x); -// -// it allows using the detected idiom to retrieve the return type -// of such an expression -#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ - namespace detail { \ - using std::std_name; \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - } \ - \ - namespace detail2 { \ - struct std_name##_tag \ - { \ - }; \ - \ - template \ - std_name##_tag std_name(T&&...); \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - \ - template \ - struct would_call_std_##std_name \ - { \ - static constexpr auto const value = ::nlohmann::detail:: \ - is_detected_exact::value; \ - }; \ - } /* namespace detail2 */ \ - \ - template \ - struct would_call_std_##std_name : detail2::would_call_std_##std_name \ - { \ - } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - -#ifndef JSON_DISABLE_ENUM_SERIALIZATION - #define JSON_DISABLE_ENUM_SERIALIZATION 0 -#endif - -#ifndef JSON_USE_GLOBAL_UDLS - #define JSON_USE_GLOBAL_UDLS 1 -#endif - -#if JSON_HAS_THREE_WAY_COMPARISON - #include // partial_ordering -#endif - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -#if JSON_HAS_THREE_WAY_COMPARISON - inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* -#else - inline bool operator<(const value_t lhs, const value_t rhs) noexcept -#endif -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); -#if JSON_HAS_THREE_WAY_COMPARISON - if (l_index < order.size() && r_index < order.size()) - { - return order[l_index] <=> order[r_index]; // *NOPAD* - } - return std::partial_ordering::unordered; -#else - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -#endif -} - -// GCC selects the built-in operator< over an operator rewritten from -// a user-defined spaceship operator -// Clang, MSVC, and ICC select the rewritten candidate -// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) -#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - return std::is_lt(lhs <=> rhs); // *NOPAD* -} -#endif - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/*! -@brief replace all occurrences of a substring by another string - -@param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t -@param[in] f the substring to replace with @a t -@param[in] t the string to replace @a f - -@pre The search string @a f must not be empty. **This precondition is -enforced with an assertion.** - -@since version 2.0.0 -*/ -template -inline void replace_substring(StringType& s, const StringType& f, - const StringType& t) -{ - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -static void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -inline constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval -#include // tuple - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // random_access_iterator_tag - -// #include - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); - -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); - -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector - - // #include - - - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN - - /*! - @brief default JSONSerializer template argument - - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> - class basic_json; - - /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document - /// @sa https://json.nlohmann.me/api/json_pointer/ - template - class json_pointer; - - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; - - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; - - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; - - NLOHMANN_JSON_NAMESPACE_END - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ - -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -// used by exceptions create() member functions -// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t -// false_type otherwise -template -struct is_basic_json_context : - std::integral_constant < bool, - is_basic_json::type>::type>::value - || std::is_same::value > -{}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -template -using detect_key_compare = typename T::key_compare; - -template -struct has_key_compare : std::integral_constant::value> {}; - -// obtains the actual object key comparator -template -struct actual_object_comparator -{ - using object_t = typename BasicJsonType::object_t; - using object_comparator_t = typename BasicJsonType::default_object_comparator_t; - using type = typename std::conditional < has_key_compare::value, - typename object_t::key_compare, object_comparator_t>::type; -}; - -template -using actual_object_comparator_t = typename actual_object_comparator::type; - -/////////////////// -// is_ functions // -/////////////////// - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B { }; -template -struct conjunction -: std::conditional(B::value), conjunction, B>::type {}; - -// https://en.cppreference.com/w/cpp/types/negation -template struct negation : std::integral_constant < bool, !B::value > { }; - -// Reimplementation of is_constructible and is_default_constructible, due to them being broken for -// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). -// This causes compile errors in e.g. clang 3.5 or gcc 4.9. -template -struct is_default_constructible : std::is_default_constructible {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - - -template -struct is_constructible : std::is_constructible {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -template -struct is_range -{ - private: - using t_ref = typename std::add_lvalue_reference::type; - - using iterator = detected_t; - using sentinel = detected_t; - - // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator - // and https://en.cppreference.com/w/cpp/iterator/sentinel_for - // but reimplementing these would be too much work, as a lot of other concepts are used underneath - static constexpr auto is_iterator_begin = - is_iterator_traits>::value; - - public: - static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; -}; - -template -using iterator_t = enable_if_t::value, result_of_begin())>>; - -template -using range_value_t = value_type_t>>; - -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - is_constructible::value && - is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_constructible_string_type -{ - // launder type through decltype() to fix compilation failure on ICPC -#ifdef __INTEL_COMPILER - using laundered_type = decltype(std::declval()); -#else - using laundered_type = ConstructibleStringType; -#endif - - static constexpr auto value = - conjunction < - is_constructible, - is_detected_exact>::value; -}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < - is_detected::value&& - is_iterator_traits>>::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 - !std::is_same>::value >> -{ - static constexpr bool value = - is_constructible>::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - !is_compatible_string_type::value&& - is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_iterator_traits>>::value&& -is_detected::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 -!std::is_same>::value&& - is_complete_type < - detected_t>::value >> -{ - using value_type = range_value_t; - - static constexpr bool value = - std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, - value_type >::value; -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; - -template -struct is_json_iterator_of : std::false_type {}; - -template -struct is_json_iterator_of : std::true_type {}; - -template -struct is_json_iterator_of : std::true_type -{}; - -// checks if a given type T is a template specialization of Primary -template