Ajout du schéma JSON pour lecture de scènes + ajout des composants son avec OpenAL + composants scripts et libraire de script + ajout de librairies pour le son dr_libs et openAL + librairie schéma json validator + correctifs divers d'oubli et autres + entity et components factory fonctionnelles + rework API graphique et systèmes mergés dans Systèmes (audio physique, etc...) + rework sauvegarde des resources de façon unique pour éviter les reload (correctifs associés)

This commit is contained in:
Tom Ray
2026-04-17 21:00:35 +02:00
parent f49b050e85
commit 595f28ecda
167 changed files with 32352 additions and 2229 deletions
+81 -26
View File
@@ -1,6 +1,8 @@
# Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités. # Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités.
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
set (CMAKE_CXX_STANDARD 23) set (CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
# Nom du projet. # Nom du projet.
set(PROJECT CosmicEngine) set(PROJECT CosmicEngine)
project(${PROJECT}) project(${PROJECT})
@@ -11,6 +13,11 @@ file(GLOB_RECURSE
src/Engine/* src/Engine/*
) )
file(GLOB_RECURSE
SRCS_SCRIPTS
src/Modules/Scripts/*
)
file(GLOB_RECURSE file(GLOB_RECURSE
SRCS SRCS
src/main.cpp) src/main.cpp)
@@ -20,6 +27,12 @@ file(GLOB_RECURSE
test/* test/*
) )
file(GLOB_RECURSE
HEADERS_ENGINE
src/Engine/*.h
src/Engine/*.hpp
)
# ---------- Inclusion des packages sous windows ----------- # ---------- Inclusion des packages sous windows -----------
if(WIN32) if(WIN32)
endif() endif()
@@ -235,13 +248,25 @@ if(UNIX)
# OpenAL Lib gérer le son. # OpenAL Lib gérer le son.
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# set(OPENAL_DIR ./lib/CMake/Linux) # set(OPENAL_DIR ./lib/CMake/Linux)
# find_package(OPENAL REQUIRED) find_package(OpenAL REQUIRED)
# if(OPENAL_FOUND) if(OpenAL_FOUND)
# message("lib OpenAL Trouvé") message("lib OpenAL Trouvé")
# else() else()
# message("lib OpenAL Introuvable") message("lib OpenAL Introuvable")
# endif() endif()
# ---------------------------------------
# ------- Inclusion de dr_libs --------
# dr_libs Lib pour gestion du son en mode header only.
set(drlibs_DIR ./lib/CMake/Linux)
find_package(drlibs REQUIRED)
if(drlibs_FOUND)
message("lib dr_libs Trouvé")
else()
message("lib dr_libs Introuvable")
endif()
# --------------------------------------- # ---------------------------------------
# ---------- Inclusion de Catch2----------- # ---------- Inclusion de Catch2-----------
@@ -335,8 +360,7 @@ endif()
# --------------------------------------- # ---------------------------------------
add_library(spirv-reflect STATIC ${SPIRV_EXT_SRC}) add_library(spirv-reflect STATIC ${SPIRV_EXT_SRC})
# ------- Inclusion de JSONfMC++ -------- # ------- Inclusion de VulkanAllocator --------
# JSONfMC++ Lib pour gestion fichier JSON, en mode header only.
set(VulkanMemoryAllocatorlib_DIR ./lib/CMake/Linux) set(VulkanMemoryAllocatorlib_DIR ./lib/CMake/Linux)
find_package(VulkanMemoryAllocatorlib REQUIRED) find_package(VulkanMemoryAllocatorlib REQUIRED)
@@ -351,6 +375,7 @@ endif()
# JoltPhysics Lib Moteur physique. # JoltPhysics Lib Moteur physique.
set(JoltPhysicslib_DIR ./lib/CMake/Linux) set(JoltPhysicslib_DIR ./lib/CMake/Linux)
# # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. # # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
find_package(JoltPhysicslib REQUIRED) find_package(JoltPhysicslib REQUIRED)
if(JoltPhysicslib_FOUND) if(JoltPhysicslib_FOUND)
message("lib JOLT Trouvé") message("lib JOLT Trouvé")
@@ -415,9 +440,23 @@ function(compile_slang_shaders SLANG_FILES OUTPUT_DIR)
endfunction() endfunction()
add_library(Engine STATIC ${SRCS_ENGINE} ${SRCS_EXTERNAL_GLAD}) add_library(Engine STATIC ${SRCS_ENGINE} ${SRCS_EXTERNAL_GLAD} ${ENGINE_HEADERS})
target_include_directories(Engine
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/Engine
)
add_library(ScriptModule SHARED ${SRCS_SCRIPTS})
target_include_directories(ScriptModule PRIVATE ${HEADERS_ENGINE})
set_property(TARGET Engine PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
add_executable(${PROJECT} ${SRCS}) add_executable(${PROJECT} ${SRCS})
set_property(TARGET ${PROJECT} PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
add_executable(CosmicTest ${SRCS_TESTS}) add_executable(CosmicTest ${SRCS_TESTS})
set_property(TARGET CosmicTest PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set_property(TARGET ScriptModule PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
# On indique que l'on veut un exécutable nommé PROJECT compilé à partir des fichiers décrits par les variables SRCS et HEADERS. # On indique que l'on veut un exécutable nommé PROJECT compilé à partir des fichiers décrits par les variables SRCS et HEADERS.
file(GLOB_RECURSE SLANG_SHADERS "${PATH_TO_SHADER_BUILD_TYPE}/assets/shaders/slang/*.slang") file(GLOB_RECURSE SLANG_SHADERS "${PATH_TO_SHADER_BUILD_TYPE}/assets/shaders/slang/*.slang")
@@ -434,6 +473,7 @@ endif()
add_dependencies(${PROJECT} Engine) add_dependencies(${PROJECT} Engine)
add_dependencies(Engine CompileSlangShaders) add_dependencies(Engine CompileSlangShaders)
add_dependencies(ScriptModule Engine)
target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine) target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine)
@@ -467,9 +507,28 @@ include_directories(${JOLT_INCLUDE_DIRS})
# SNDFILE # SNDFILE
#include_directories(${SNDFILE_INCLUDE_DIRS}) #include_directories(${SNDFILE_INCLUDE_DIRS})
# OPENAL # OPENAL
#include_directories(${OPENAL_INCLUDE_DIRS}) include_directories(${OPENAL_INCLUDE_DIRS})
include_directories(${JSONVALIDATOR_INCLUDE_DIRS}) include_directories(${JSONVALIDATOR_INCLUDE_DIRS})
include_directories(${DRLIBS_INCLUDE_DIRS})
target_link_libraries(Engine ${JSONVALIDATOR_LIBRARIES})
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(Engine PRIVATE
JPH_ENABLE_ASSERTS
JPH_PROFILE_ENABLED
JPH_OBJECT_STREAM
JPH_DEBUG_RENDERER
)
else() # Release
target_compile_definitions(Engine PRIVATE
JPH_OBJECT_STREAM
)
endif()
target_link_libraries(Engine
debug ${JOLT_LIBRARIES_DEBUG}
optimized ${JOLT_LIBRARIES_RELEASE}
)
# Fichier lib # Fichier lib
# OpenGL # OpenGL
#target_link_libraries(Engine OpenMP::OpenMP_CXX) #target_link_libraries(Engine OpenMP::OpenMP_CXX)
@@ -502,23 +561,16 @@ target_link_libraries(Engine spirv-reflect)
# ASSIMP # ASSIMP
target_link_libraries(Engine ${ASSIMP_LIBRARIES}) target_link_libraries(Engine ${ASSIMP_LIBRARIES})
target_link_libraries(Engine ${JSONVALIDATOR_LIBRARIES})
# ODE # ODE
#target_link_libraries(Engine ${ODE_LIBRARIES}) #target_link_libraries(Engine ${ODE_LIBRARIES})
target_compile_definitions(Engine PRIVATE
JPH_PROFILE_ENABLED
JPH_DEBUG_RENDERER
JPH_OBJECT_STREAM
)
target_link_libraries(Engine ${JOLT_LIBRARIES})
# SNDFILE # SNDFILE
#target_link_libraries(Engine sndfile) #target_link_libraries(Engine sndfile)
# OPENAL # OPENAL
#target_link_libraries(Engine ${OPENAL_LIBRARIES}) target_link_libraries(Engine OpenAL::OpenAL)
#target_link_libraries(Engine ${CMAKE_DL_LIBS}) #target_link_libraries(Engine ${CMAKE_DL_LIBS})
@@ -536,19 +588,22 @@ target_link_libraries(Engine ${JOLT_LIBRARIES})
# target_link_libraries(Engine Boost::log) # target_link_libraries(Engine Boost::log)
# target_link_libraries(Engine Boost::log_setup) # target_link_libraries(Engine Boost::log_setup)
target_link_libraries(ScriptModule Engine)
target_link_libraries(${PROJECT} Engine) target_link_libraries(${PROJECT} Engine)
#if(UNIX) if(UNIX)
#add_custom_command( add_custom_command(
# TARGET Engine POST_BUILD TARGET ScriptModule POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy COMMAND ${CMAKE_COMMAND} -E copy
# ${CMAKE_CURRENT_BINARY_DIR}/libEngine.so ${CMAKE_CURRENT_BINARY_DIR}/libScriptModule.so
# ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
#endif() endif()
# Paramètre de compilation # Paramètre de compilation
if (UNIX) if (UNIX)
set(CMAKE_CXX_FLAGS "-Wall -fPIC") set(CMAKE_CXX_FLAGS "-Wall -fPIC")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
endif () endif ()
# Valgrind ne marche que pour Linux... # Valgrind ne marche que pour Linux...
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -12,20 +12,24 @@
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) #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 != 3 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
#warning "Already included a different version of the library!" #warning "Already included a different version of the library!"
#endif #endif
#endif #endif
#endif #endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) #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_MINOR 12 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) #define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS #ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0 #define JSON_DIAGNOSTICS 0
#endif #endif
#ifndef JSON_DIAGNOSTIC_POSITIONS
#define JSON_DIAGNOSTIC_POSITIONS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif #endif
@@ -36,6 +40,12 @@
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif #endif
#if JSON_DIAGNOSTIC_POSITIONS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else #else
@@ -47,14 +57,15 @@
#endif #endif
// Construct the namespace ABI tags component // 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_EX(a, b, c) json_abi ## a ## b ## c
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
#define NLOHMANN_JSON_ABI_TAGS \ #define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
// Construct the namespace version component // Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -13,6 +13,9 @@
#include <forward_list> // forward_list #include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end #include <iterator> // inserter, front_inserter, end
#include <map> // map #include <map> // map
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <string> // string #include <string> // string
#include <tuple> // tuple, make_tuple #include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
@@ -43,6 +46,24 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
n = nullptr; n = nullptr;
} }
#ifdef JSON_HAS_CPP_17
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
if (j.is_null())
{
opt = std::nullopt;
}
else
{
opt.emplace(j.template get<T>());
}
}
#endif // JSON_USE_IMPLICIT_CONVERSIONS
#endif // JSON_HAS_CPP_17
// overloads for basic_json template parameters // overloads for basic_json template parameters
template < typename BasicJsonType, typename ArithmeticType, template < typename BasicJsonType, typename ArithmeticType,
enable_if_t < std::is_arithmetic<ArithmeticType>::value&& enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
@@ -190,6 +211,54 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines
} }
} }
template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i1 = 0; i1 < N1; ++i1)
{
for (std::size_t i2 = 0; i2 < N2; ++i2)
{
arr[i1][i2] = j.at(i1).at(i2).template get<T>();
}
}
}
template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i1 = 0; i1 < N1; ++i1)
{
for (std::size_t i2 = 0; i2 < N2; ++i2)
{
for (std::size_t i3 = 0; i3 < N3; ++i3)
{
arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
}
}
}
}
template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i1 = 0; i1 < N1; ++i1)
{
for (std::size_t i2 = 0; i2 < N2; ++i2)
{
for (std::size_t i3 = 0; i3 < N3; ++i3)
{
for (std::size_t i4 = 0; i4 < N4; ++i4)
{
arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
}
}
}
}
}
template<typename BasicJsonType> template<typename BasicJsonType>
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{ {
@@ -379,6 +448,12 @@ std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
} }
template<typename BasicJsonType>
std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
{
return {};
}
template < typename BasicJsonType, class A1, class A2 > template < typename BasicJsonType, class A1, class A2 >
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
{ {
@@ -464,7 +539,12 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
{ {
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
} }
p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
#ifdef JSON_HAS_CPP_20
p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
#else
p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
#endif
} }
#endif #endif
@@ -1,10 +1,10 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -239,10 +239,10 @@ boundaries compute_boundaries(FloatType value)
// v- m- v m+ v+ // v- m- v m+ v+
const bool lower_boundary_is_closer = F == 0 && E > 1; const bool lower_boundary_is_closer = F == 0 && E > 1;
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
const diyfp m_minus = lower_boundary_is_closer const diyfp m_minus = lower_boundary_is_closer
? diyfp(4 * v.f - 1, v.e - 2) // (B) ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
: diyfp(2 * v.f - 1, v.e - 1); // (A) : diyfp((2 * v.f) - 1, v.e - 1); // (A)
// Determine the normalized w+ = m+. // Determine the normalized w+ = m+.
const diyfp w_plus = diyfp::normalize(m_plus); const diyfp w_plus = diyfp::normalize(m_plus);
@@ -472,7 +472,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
JSON_ASSERT(e >= -1500); JSON_ASSERT(e >= -1500);
JSON_ASSERT(e <= 1500); JSON_ASSERT(e <= 1500);
const int f = kAlpha - e - 1; const int f = kAlpha - e - 1;
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0); const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
JSON_ASSERT(index >= 0); JSON_ASSERT(index >= 0);
@@ -950,15 +950,15 @@ inline char* append_exponent(char* buf, int e)
} }
else if (k < 100) else if (k < 100)
{ {
*buf++ = static_cast<char>('0' + k / 10); *buf++ = static_cast<char>('0' + (k / 10));
k %= 10; k %= 10;
*buf++ = static_cast<char>('0' + k); *buf++ = static_cast<char>('0' + k);
} }
else else
{ {
*buf++ = static_cast<char>('0' + k / 100); *buf++ = static_cast<char>('0' + (k / 100));
k %= 100; k %= 100;
*buf++ = static_cast<char>('0' + k / 10); *buf++ = static_cast<char>('0' + (k / 10));
k %= 10; k %= 10;
*buf++ = static_cast<char>('0' + k); *buf++ = static_cast<char>('0' + k);
} }
@@ -1,13 +1,18 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
#include <nlohmann/detail/macro_scope.hpp> // JSON_HAS_CPP_17
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <algorithm> // copy #include <algorithm> // copy
#include <iterator> // begin, end #include <iterator> // begin, end
#include <string> // string #include <string> // string
@@ -18,7 +23,6 @@
#include <vector> // vector #include <vector> // vector
#include <nlohmann/detail/iterators/iteration_proxy.hpp> #include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/std_fs.hpp> #include <nlohmann/detail/meta/std_fs.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
@@ -260,6 +264,22 @@ struct external_constructor<value_t::object>
// to_json // // to_json //
///////////// /////////////
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
{
if (opt.has_value())
{
j = *opt;
}
else
{
j = nullptr;
}
}
#endif
template<typename BasicJsonType, typename T, template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
inline void to_json(BasicJsonType& j, T b) noexcept inline void to_json(BasicJsonType& j, T b) noexcept
@@ -320,7 +340,8 @@ template<typename BasicJsonType, typename EnumType,
inline void to_json(BasicJsonType& j, EnumType e) noexcept inline void to_json(BasicJsonType& j, EnumType e) noexcept
{ {
using underlying_type = typename std::underlying_type<EnumType>::type; using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
} }
#endif // JSON_DISABLE_ENUM_SERIALIZATION #endif // JSON_DISABLE_ENUM_SERIALIZATION
@@ -405,6 +426,13 @@ inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<
j = { std::get<Idx>(t)... }; j = { std::get<Idx>(t)... };
} }
template<typename BasicJsonType, typename Tuple>
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
{
using array_t = typename BasicJsonType::array_t;
j = array_t();
}
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
inline void to_json(BasicJsonType& j, const T& t) inline void to_json(BasicJsonType& j, const T& t)
{ {
@@ -415,7 +443,12 @@ inline void to_json(BasicJsonType& j, const T& t)
template<typename BasicJsonType> template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std_fs::path& p) inline void to_json(BasicJsonType& j, const std_fs::path& p)
{ {
j = p.string(); #ifdef JSON_HAS_CPP_20
const std::u8string s = p.u8string();
j = std::string(s.begin(), s.end());
#else
j = p.u8string(); // returns std::string in C++17
#endif
} }
#endif #endif
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -25,6 +25,18 @@
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/string_concat.hpp>
// With -Wweak-vtables, Clang will complain about the exception classes as they
// have no out-of-line virtual method definitions and their vtable will be
// emitted in every translation unit. This issue cannot be fixed with a
// header-only library as there is no implementation file to move these
// functions to. As a result, we suppress this warning here to avoid client
// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
// for a discussion.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail namespace detail
{ {
@@ -119,16 +131,34 @@ class exception : public std::exception
{ {
return concat(a, '/', detail::escape(b)); return concat(a, '/', detail::escape(b));
}); });
return concat('(', str, ") ");
return concat('(', str, ") ", get_byte_positions(leaf_element));
#else #else
static_cast<void>(leaf_element); return get_byte_positions(leaf_element);
return "";
#endif #endif
} }
private: private:
/// an exception object as storage for error messages /// an exception object as storage for error messages
std::runtime_error m; std::runtime_error m;
#if JSON_DIAGNOSTIC_POSITIONS
template<typename BasicJsonType>
static std::string get_byte_positions(const BasicJsonType* leaf_element)
{
if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
{
return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
}
return "";
}
#else
template<typename BasicJsonType>
static std::string get_byte_positions(const BasicJsonType* leaf_element)
{
static_cast<void>(leaf_element);
return "";
}
#endif
}; };
/// @brief exception indicating a parse error /// @brief exception indicating a parse error
@@ -255,3 +285,7 @@ class other_error : public exception
} // namespace detail } // namespace detail
NLOHMANN_JSON_NAMESPACE_END NLOHMANN_JSON_NAMESPACE_END
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -20,6 +20,9 @@
#include <string> // char_traits, string #include <string> // char_traits, string
#include <utility> // make_pair, move #include <utility> // make_pair, move
#include <vector> // vector #include <vector> // vector
#ifdef __cpp_lib_byteswap
#include <bit> //byteswap
#endif
#include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/input_adapters.hpp> #include <nlohmann/detail/input/input_adapters.hpp>
@@ -62,7 +65,7 @@ static inline bool little_endianness(int num = 1) noexcept
/*! /*!
@brief deserialization of CBOR, MessagePack, and UBJSON values @brief deserialization of CBOR, MessagePack, and UBJSON values
*/ */
template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>> template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
class binary_reader class binary_reader
{ {
using number_integer_t = typename BasicJsonType::number_integer_t; using number_integer_t = typename BasicJsonType::number_integer_t;
@@ -169,7 +172,7 @@ class binary_reader
std::int32_t document_size{}; std::int32_t document_size{};
get_number<std::int32_t, true>(input_format_t::bson, document_size); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -325,6 +328,12 @@ class binary_reader
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value); return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
} }
case 0x11: // uint64
{
std::uint64_t value{};
return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
}
default: // anything else not supported (yet) default: // anything else not supported (yet)
{ {
std::array<char, 3> cr{{}}; std::array<char, 3> cr{{}};
@@ -391,7 +400,7 @@ class binary_reader
std::int32_t document_size{}; std::int32_t document_size{};
get_number<std::int32_t, true>(input_format_t::bson, document_size); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -651,7 +660,7 @@ class binary_reader
} }
case 0x9F: // array (indefinite length) case 0x9F: // array (indefinite length)
return get_cbor_array(static_cast<std::size_t>(-1), tag_handler); return get_cbor_array(detail::unknown_size(), tag_handler);
// map (0x00..0x17 pairs of data items follow) // map (0x00..0x17 pairs of data items follow)
case 0xA0: case 0xA0:
@@ -705,7 +714,7 @@ class binary_reader
} }
case 0xBF: // map (indefinite length) case 0xBF: // map (indefinite length)
return get_cbor_object(static_cast<std::size_t>(-1), tag_handler); return get_cbor_object(detail::unknown_size(), tag_handler);
case 0xC6: // tagged item case 0xC6: // tagged item
case 0xC7: case 0xC7:
@@ -1093,7 +1102,7 @@ class binary_reader
} }
/*! /*!
@param[in] len the length of the array or static_cast<std::size_t>(-1) for an @param[in] len the length of the array or detail::unknown_size() for an
array of indefinite size array of indefinite size
@param[in] tag_handler how CBOR tags should be treated @param[in] tag_handler how CBOR tags should be treated
@return whether array creation completed @return whether array creation completed
@@ -1106,7 +1115,7 @@ class binary_reader
return false; return false;
} }
if (len != static_cast<std::size_t>(-1)) if (len != detail::unknown_size())
{ {
for (std::size_t i = 0; i < len; ++i) for (std::size_t i = 0; i < len; ++i)
{ {
@@ -1131,7 +1140,7 @@ class binary_reader
} }
/*! /*!
@param[in] len the length of the object or static_cast<std::size_t>(-1) for an @param[in] len the length of the object or detail::unknown_size() for an
object of indefinite size object of indefinite size
@param[in] tag_handler how CBOR tags should be treated @param[in] tag_handler how CBOR tags should be treated
@return whether object creation completed @return whether object creation completed
@@ -1147,7 +1156,7 @@ class binary_reader
if (len != 0) if (len != 0)
{ {
string_t key; string_t key;
if (len != static_cast<std::size_t>(-1)) if (len != detail::unknown_size())
{ {
for (std::size_t i = 0; i < len; ++i) for (std::size_t i = 0; i < len; ++i)
{ {
@@ -2310,6 +2319,16 @@ class binary_reader
case 'Z': // null case 'Z': // null
return sax->null(); return sax->null();
case 'B': // byte
{
if (input_format != input_format_t::bjdata)
{
break;
}
std::uint8_t number{};
return get_number(input_format, number) && sax->number_unsigned(number);
}
case 'U': case 'U':
{ {
std::uint8_t number{}; std::uint8_t number{};
@@ -2510,7 +2529,7 @@ class binary_reader
return false; return false;
} }
if (size_and_type.second == 'C') if (size_and_type.second == 'C' || size_and_type.second == 'B')
{ {
size_and_type.second = 'U'; size_and_type.second = 'U';
} }
@@ -2532,6 +2551,13 @@ class binary_reader
return (sax->end_array() && sax->end_object()); return (sax->end_array() && sax->end_object());
} }
// If BJData type marker is 'B' decode as binary
if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
{
binary_t result;
return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
}
if (size_and_type.first != npos) if (size_and_type.first != npos)
{ {
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
@@ -2565,7 +2591,7 @@ class binary_reader
} }
else else
{ {
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -2643,7 +2669,7 @@ class binary_reader
} }
else else
{ {
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -2754,6 +2780,29 @@ class binary_reader
return current = ia.get_character(); return current = ia.get_character();
} }
/*!
@brief get_to read into a primitive type
This function provides the interface to the used input adapter. It does
not throw in case the input reached EOF, but returns false instead
@return bool, whether the read was successful
*/
template<class T>
bool get_to(T& dest, const input_format_t format, const char* context)
{
auto new_chars_read = ia.get_elements(&dest);
chars_read += new_chars_read;
if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
{
// in case of failure, advance position by 1 to report failing location
++chars_read;
sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
return false;
}
return true;
}
/*! /*!
@return character read from the input after ignoring all 'N' entries @return character read from the input after ignoring all 'N' entries
*/ */
@@ -2768,6 +2817,28 @@ class binary_reader
return current; return current;
} }
template<class NumberType>
static void byte_swap(NumberType& number)
{
constexpr std::size_t sz = sizeof(number);
#ifdef __cpp_lib_byteswap
if constexpr (sz == 1)
{
return;
}
if constexpr(std::is_integral_v<NumberType>)
{
number = std::byteswap(number);
return;
}
#endif
auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
for (std::size_t i = 0; i < sz / 2; ++i)
{
std::swap(ptr[i], ptr[sz - i - 1]);
}
}
/* /*
@brief read a number from the input @brief read a number from the input
@@ -2786,29 +2857,16 @@ class binary_reader
template<typename NumberType, bool InputIsLittleEndian = false> template<typename NumberType, bool InputIsLittleEndian = false>
bool get_number(const input_format_t format, NumberType& result) bool get_number(const input_format_t format, NumberType& result)
{ {
// step 1: read input into array with system's byte order // read in the original format
std::array<std::uint8_t, sizeof(NumberType)> vec{};
for (std::size_t i = 0; i < sizeof(NumberType); ++i) if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
{
get();
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
{ {
return false; return false;
} }
// reverse byte order prior to conversion if necessary
if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
{ {
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current); byte_swap(result);
} }
else
{
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
}
}
// step 2: convert array into number of type T and return
std::memcpy(&result, vec.data(), sizeof(NumberType));
return true; return true;
} }
@@ -2947,7 +3005,7 @@ class binary_reader
} }
private: private:
static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1); static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
/// input adapter /// input adapter
InputAdapterType ia; InputAdapterType ia;
@@ -2973,6 +3031,7 @@ class binary_reader
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
make_array<bjd_type>( \ make_array<bjd_type>( \
bjd_type{'B', "byte"}, \
bjd_type{'C', "char"}, \ bjd_type{'C', "char"}, \
bjd_type{'D', "double"}, \ bjd_type{'D', "double"}, \
bjd_type{'I', "int16"}, \ bjd_type{'I', "int16"}, \
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -23,6 +23,7 @@
#include <istream> // istream #include <istream> // istream
#endif // JSON_NO_IO #endif // JSON_NO_IO
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/iterators/iterator_traits.hpp> #include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
@@ -67,6 +68,13 @@ class file_input_adapter
return std::fgetc(m_file); return std::fgetc(m_file);
} }
// returns the number of characters successfully read
template<class T>
std::size_t get_elements(T* dest, std::size_t count = 1)
{
return fread(dest, 1, sizeof(T) * count, m_file);
}
private: private:
/// the file pointer to read from /// the file pointer to read from
std::FILE* m_file; std::FILE* m_file;
@@ -126,6 +134,17 @@ class input_stream_adapter
return res; return res;
} }
template<class T>
std::size_t get_elements(T* dest, std::size_t count = 1)
{
auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
{
is->clear(is->rdstate() | std::ios::eofbit);
}
return res;
}
private: private:
/// the associated input stream /// the associated input stream
std::istream* is = nullptr; std::istream* is = nullptr;
@@ -157,6 +176,26 @@ class iterator_input_adapter
return char_traits<char_type>::eof(); return char_traits<char_type>::eof();
} }
// for general iterators, we cannot really do something better than falling back to processing the range one-by-one
template<class T>
std::size_t get_elements(T* dest, std::size_t count = 1)
{
auto* ptr = reinterpret_cast<char*>(dest);
for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
{
if (JSON_HEDLEY_LIKELY(current != end))
{
ptr[read_index] = static_cast<char>(*current);
std::advance(current, 1);
}
else
{
return read_index;
}
}
return count * sizeof(T);
}
private: private:
IteratorType current; IteratorType current;
IteratorType end; IteratorType end;
@@ -320,6 +359,13 @@ class wide_string_input_adapter
return utf8_bytes[utf8_bytes_index++]; return utf8_bytes[utf8_bytes_index++];
} }
// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
template<class T>
std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
{
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
}
private: private:
BaseInputAdapter base_adapter; BaseInputAdapter base_adapter;
@@ -416,10 +462,17 @@ typename container_input_adapter_factory_impl::container_input_adapter_factory<C
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
} }
// specialization for std::string
using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
#ifndef JSON_NO_IO #ifndef JSON_NO_IO
// Special cases with fast paths // Special cases with fast paths
inline file_input_adapter input_adapter(std::FILE* file) inline file_input_adapter input_adapter(std::FILE* file)
{ {
if (file == nullptr)
{
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
}
return file_input_adapter(file); return file_input_adapter(file);
} }
@@ -446,9 +499,13 @@ template < typename CharT,
int >::type = 0 > int >::type = 0 >
contiguous_bytes_input_adapter input_adapter(CharT b) contiguous_bytes_input_adapter input_adapter(CharT b)
{ {
if (b == nullptr)
{
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
}
auto length = std::strlen(reinterpret_cast<const char*>(b)); auto length = std::strlen(reinterpret_cast<const char*>(b));
const auto* ptr = reinterpret_cast<const char*>(b); const auto* ptr = reinterpret_cast<const char*>(b);
return input_adapter(ptr, ptr + length); return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
@@ -1,22 +1,23 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <string> // string #include <string> // string
#include <type_traits> // enable_if_t
#include <utility> // move #include <utility> // move
#include <vector> // vector #include <vector> // vector
#include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/string_concat.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
/*! /*!
@@ -144,6 +145,11 @@ struct json_sax
namespace detail namespace detail
{ {
constexpr std::size_t unknown_size()
{
return (std::numeric_limits<std::size_t>::max)();
}
/*! /*!
@brief SAX implementation to create a JSON value from SAX events @brief SAX implementation to create a JSON value from SAX events
@@ -157,7 +163,7 @@ constructor contains the parsed value.
@tparam BasicJsonType the JSON type @tparam BasicJsonType the JSON type
*/ */
template<typename BasicJsonType> template<typename BasicJsonType, typename InputAdapterType>
class json_sax_dom_parser class json_sax_dom_parser
{ {
public: public:
@@ -166,14 +172,15 @@ class json_sax_dom_parser
using number_float_t = typename BasicJsonType::number_float_t; using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t; using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t; using binary_t = typename BasicJsonType::binary_t;
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
/*! /*!
@param[in,out] r reference to a JSON value that is manipulated while @param[in,out] r reference to a JSON value that is manipulated while
parsing parsing
@param[in] allow_exceptions_ whether parse errors yield exceptions @param[in] allow_exceptions_ whether parse errors yield exceptions
*/ */
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
: root(r), allow_exceptions(allow_exceptions_) : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
{} {}
// make class move-only // make class move-only
@@ -229,7 +236,18 @@ class json_sax_dom_parser
{ {
ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) #if JSON_DIAGNOSTIC_POSITIONS
// Manually set the start position of the object here.
// Ensure this is after the call to handle_value to ensure correct start position.
if (m_lexer_ref)
{
// Lexer has read the first character of the object, so
// subtract 1 from the position to get the correct start position.
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
}
#endif
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
} }
@@ -252,6 +270,14 @@ class json_sax_dom_parser
JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(!ref_stack.empty());
JSON_ASSERT(ref_stack.back()->is_object()); JSON_ASSERT(ref_stack.back()->is_object());
#if JSON_DIAGNOSTIC_POSITIONS
if (m_lexer_ref)
{
// Lexer's position is past the closing brace, so set that as the end position.
ref_stack.back()->end_position = m_lexer_ref->get_position();
}
#endif
ref_stack.back()->set_parents(); ref_stack.back()->set_parents();
ref_stack.pop_back(); ref_stack.pop_back();
return true; return true;
@@ -261,7 +287,16 @@ class json_sax_dom_parser
{ {
ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) #if JSON_DIAGNOSTIC_POSITIONS
// Manually set the start position of the array here.
// Ensure this is after the call to handle_value to ensure correct start position.
if (m_lexer_ref)
{
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
}
#endif
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
} }
@@ -274,6 +309,14 @@ class json_sax_dom_parser
JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(!ref_stack.empty());
JSON_ASSERT(ref_stack.back()->is_array()); JSON_ASSERT(ref_stack.back()->is_array());
#if JSON_DIAGNOSTIC_POSITIONS
if (m_lexer_ref)
{
// Lexer's position is past the closing bracket, so set that as the end position.
ref_stack.back()->end_position = m_lexer_ref->get_position();
}
#endif
ref_stack.back()->set_parents(); ref_stack.back()->set_parents();
ref_stack.pop_back(); ref_stack.pop_back();
return true; return true;
@@ -298,6 +341,75 @@ class json_sax_dom_parser
} }
private: private:
#if JSON_DIAGNOSTIC_POSITIONS
void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
{
if (m_lexer_ref)
{
// Lexer has read past the current field value, so set the end position to the current position.
// The start position will be set below based on the length of the string representation
// of the value.
v.end_position = m_lexer_ref->get_position();
switch (v.type())
{
case value_t::boolean:
{
// 4 and 5 are the string length of "true" and "false"
v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
break;
}
case value_t::null:
{
// 4 is the string length of "null"
v.start_position = v.end_position - 4;
break;
}
case value_t::string:
{
// include the length of the quotes, which is 2
v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
break;
}
// As we handle the start and end positions for values created during parsing,
// we do not expect the following value type to be called. Regardless, set the positions
// in case this is created manually or through a different constructor. Exclude from lcov
// since the exact condition of this switch is esoteric.
// LCOV_EXCL_START
case value_t::discarded:
{
v.end_position = std::string::npos;
v.start_position = v.end_position;
break;
}
// LCOV_EXCL_STOP
case value_t::binary:
case value_t::number_integer:
case value_t::number_unsigned:
case value_t::number_float:
{
v.start_position = v.end_position - m_lexer_ref->get_string().size();
break;
}
case value_t::object:
case value_t::array:
{
// object and array are handled in start_object() and start_array() handlers
// skip setting the values here.
break;
}
default: // LCOV_EXCL_LINE
// Handle all possible types discretely, default handler should never be reached.
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
}
}
}
#endif
/*! /*!
@invariant If the ref stack is empty, then the passed value will be the new @invariant If the ref stack is empty, then the passed value will be the new
root. root.
@@ -311,6 +423,11 @@ class json_sax_dom_parser
if (ref_stack.empty()) if (ref_stack.empty())
{ {
root = BasicJsonType(std::forward<Value>(v)); root = BasicJsonType(std::forward<Value>(v));
#if JSON_DIAGNOSTIC_POSITIONS
handle_diagnostic_positions_for_json_value(root);
#endif
return &root; return &root;
} }
@@ -319,12 +436,22 @@ class json_sax_dom_parser
if (ref_stack.back()->is_array()) if (ref_stack.back()->is_array())
{ {
ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v)); ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
#if JSON_DIAGNOSTIC_POSITIONS
handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
#endif
return &(ref_stack.back()->m_data.m_value.array->back()); return &(ref_stack.back()->m_data.m_value.array->back());
} }
JSON_ASSERT(ref_stack.back()->is_object()); JSON_ASSERT(ref_stack.back()->is_object());
JSON_ASSERT(object_element); JSON_ASSERT(object_element);
*object_element = BasicJsonType(std::forward<Value>(v)); *object_element = BasicJsonType(std::forward<Value>(v));
#if JSON_DIAGNOSTIC_POSITIONS
handle_diagnostic_positions_for_json_value(*object_element);
#endif
return object_element; return object_element;
} }
@@ -338,9 +465,11 @@ class json_sax_dom_parser
bool errored = false; bool errored = false;
/// whether to throw exceptions in case of errors /// whether to throw exceptions in case of errors
const bool allow_exceptions = true; const bool allow_exceptions = true;
/// the lexer reference to obtain the current position
lexer_t* m_lexer_ref = nullptr;
}; };
template<typename BasicJsonType> template<typename BasicJsonType, typename InputAdapterType>
class json_sax_dom_callback_parser class json_sax_dom_callback_parser
{ {
public: public:
@@ -351,11 +480,13 @@ class json_sax_dom_callback_parser
using binary_t = typename BasicJsonType::binary_t; using binary_t = typename BasicJsonType::binary_t;
using parser_callback_t = typename BasicJsonType::parser_callback_t; using parser_callback_t = typename BasicJsonType::parser_callback_t;
using parse_event_t = typename BasicJsonType::parse_event_t; using parse_event_t = typename BasicJsonType::parse_event_t;
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
json_sax_dom_callback_parser(BasicJsonType& r, json_sax_dom_callback_parser(BasicJsonType& r,
const parser_callback_t cb, parser_callback_t cb,
const bool allow_exceptions_ = true) const bool allow_exceptions_ = true,
: root(r), callback(cb), allow_exceptions(allow_exceptions_) lexer_t* lexer_ = nullptr)
: root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
{ {
keep_stack.push_back(true); keep_stack.push_back(true);
} }
@@ -418,12 +549,26 @@ class json_sax_dom_callback_parser
auto val = handle_value(BasicJsonType::value_t::object, true); auto val = handle_value(BasicJsonType::value_t::object, true);
ref_stack.push_back(val.second); ref_stack.push_back(val.second);
if (ref_stack.back())
{
#if JSON_DIAGNOSTIC_POSITIONS
// Manually set the start position of the object here.
// Ensure this is after the call to handle_value to ensure correct start position.
if (m_lexer_ref)
{
// Lexer has read the first character of the object, so
// subtract 1 from the position to get the correct start position.
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
}
#endif
// check object limit // check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
} }
}
return true; return true;
} }
@@ -452,9 +597,23 @@ class json_sax_dom_callback_parser
{ {
// discard object // discard object
*ref_stack.back() = discarded; *ref_stack.back() = discarded;
#if JSON_DIAGNOSTIC_POSITIONS
// Set start/end positions for discarded object.
handle_diagnostic_positions_for_json_value(*ref_stack.back());
#endif
} }
else else
{ {
#if JSON_DIAGNOSTIC_POSITIONS
if (m_lexer_ref)
{
// Lexer's position is past the closing brace, so set that as the end position.
ref_stack.back()->end_position = m_lexer_ref->get_position();
}
#endif
ref_stack.back()->set_parents(); ref_stack.back()->set_parents();
} }
} }
@@ -488,11 +647,26 @@ class json_sax_dom_callback_parser
auto val = handle_value(BasicJsonType::value_t::array, true); auto val = handle_value(BasicJsonType::value_t::array, true);
ref_stack.push_back(val.second); ref_stack.push_back(val.second);
if (ref_stack.back())
{
#if JSON_DIAGNOSTIC_POSITIONS
// Manually set the start position of the array here.
// Ensure this is after the call to handle_value to ensure correct start position.
if (m_lexer_ref)
{
// Lexer has read the first character of the array, so
// subtract 1 from the position to get the correct start position.
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
}
#endif
// check array limit // check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
} }
}
return true; return true;
} }
@@ -506,12 +680,26 @@ class json_sax_dom_callback_parser
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
if (keep) if (keep)
{ {
#if JSON_DIAGNOSTIC_POSITIONS
if (m_lexer_ref)
{
// Lexer's position is past the closing bracket, so set that as the end position.
ref_stack.back()->end_position = m_lexer_ref->get_position();
}
#endif
ref_stack.back()->set_parents(); ref_stack.back()->set_parents();
} }
else else
{ {
// discard array // discard array
*ref_stack.back() = discarded; *ref_stack.back() = discarded;
#if JSON_DIAGNOSTIC_POSITIONS
// Set start/end positions for discarded array.
handle_diagnostic_positions_for_json_value(*ref_stack.back());
#endif
} }
} }
@@ -548,6 +736,71 @@ class json_sax_dom_callback_parser
} }
private: private:
#if JSON_DIAGNOSTIC_POSITIONS
void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
{
if (m_lexer_ref)
{
// Lexer has read past the current field value, so set the end position to the current position.
// The start position will be set below based on the length of the string representation
// of the value.
v.end_position = m_lexer_ref->get_position();
switch (v.type())
{
case value_t::boolean:
{
// 4 and 5 are the string length of "true" and "false"
v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
break;
}
case value_t::null:
{
// 4 is the string length of "null"
v.start_position = v.end_position - 4;
break;
}
case value_t::string:
{
// include the length of the quotes, which is 2
v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
break;
}
case value_t::discarded:
{
v.end_position = std::string::npos;
v.start_position = v.end_position;
break;
}
case value_t::binary:
case value_t::number_integer:
case value_t::number_unsigned:
case value_t::number_float:
{
v.start_position = v.end_position - m_lexer_ref->get_string().size();
break;
}
case value_t::object:
case value_t::array:
{
// object and array are handled in start_object() and start_array() handlers
// skip setting the values here.
break;
}
default: // LCOV_EXCL_LINE
// Handle all possible types discretely, default handler should never be reached.
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
}
}
}
#endif
/*! /*!
@param[in] v value to add to the JSON value we build during parsing @param[in] v value to add to the JSON value we build during parsing
@param[in] skip_callback whether we should skip calling the callback @param[in] skip_callback whether we should skip calling the callback
@@ -578,6 +831,10 @@ class json_sax_dom_callback_parser
// create value // create value
auto value = BasicJsonType(std::forward<Value>(v)); auto value = BasicJsonType(std::forward<Value>(v));
#if JSON_DIAGNOSTIC_POSITIONS
handle_diagnostic_positions_for_json_value(value);
#endif
// check callback // check callback
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
@@ -632,9 +889,9 @@ class json_sax_dom_callback_parser
/// stack to model hierarchy of values /// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack {}; std::vector<BasicJsonType*> ref_stack {};
/// stack to manage which values to keep /// stack to manage which values to keep
std::vector<bool> keep_stack {}; std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
/// stack to manage which object keys to keep /// stack to manage which object keys to keep
std::vector<bool> key_keep_stack {}; std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
/// helper to hold the reference for the next object element /// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr; BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred /// whether a syntax error occurred
@@ -645,6 +902,8 @@ class json_sax_dom_callback_parser
const bool allow_exceptions = true; const bool allow_exceptions = true;
/// a discarded value for the callback /// a discarded value for the callback
BasicJsonType discarded = BasicJsonType::value_t::discarded; BasicJsonType discarded = BasicJsonType::value_t::discarded;
/// the lexer reference to obtain the current position
lexer_t* m_lexer_ref = nullptr;
}; };
template<typename BasicJsonType> template<typename BasicJsonType>
@@ -692,7 +951,7 @@ class json_sax_acceptor
return true; return true;
} }
bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) bool start_object(std::size_t /*unused*/ = detail::unknown_size())
{ {
return true; return true;
} }
@@ -707,7 +966,7 @@ class json_sax_acceptor
return true; return true;
} }
bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) bool start_array(std::size_t /*unused*/ = detail::unknown_size())
{ {
return true; return true;
} }
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -967,7 +967,7 @@ class lexer : public lexer_base<BasicJsonType>
locale's decimal point is used instead of `.` to work with the locale's decimal point is used instead of `.` to work with the
locale-dependent converters. locale-dependent converters.
*/ */
token_type scan_number() // lgtm [cpp/use-of-goto] token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
{ {
// reset token_buffer to store the number's bytes // reset token_buffer to store the number's bytes
reset(); reset();
@@ -1049,6 +1049,7 @@ scan_number_zero:
case '.': case '.':
{ {
add(decimal_point_char); add(decimal_point_char);
decimal_point_position = token_buffer.size() - 1;
goto scan_number_decimal1; goto scan_number_decimal1;
} }
@@ -1085,6 +1086,7 @@ scan_number_any1:
case '.': case '.':
{ {
add(decimal_point_char); add(decimal_point_char);
decimal_point_position = token_buffer.size() - 1;
goto scan_number_decimal1; goto scan_number_decimal1;
} }
@@ -1245,7 +1247,7 @@ scan_number_done:
// we are done scanning a number) // we are done scanning a number)
unget(); unget();
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
errno = 0; errno = 0;
// try to parse integers first and fall back to floats // try to parse integers first and fall back to floats
@@ -1256,7 +1258,7 @@ scan_number_done:
// we checked the number format before // we checked the number format before
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
if (errno == 0) if (errno != ERANGE)
{ {
value_unsigned = static_cast<number_unsigned_t>(x); value_unsigned = static_cast<number_unsigned_t>(x);
if (value_unsigned == x) if (value_unsigned == x)
@@ -1272,7 +1274,7 @@ scan_number_done:
// we checked the number format before // we checked the number format before
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
if (errno == 0) if (errno != ERANGE)
{ {
value_integer = static_cast<number_integer_t>(x); value_integer = static_cast<number_integer_t>(x);
if (value_integer == x) if (value_integer == x)
@@ -1322,6 +1324,7 @@ scan_number_done:
{ {
token_buffer.clear(); token_buffer.clear();
token_string.clear(); token_string.clear();
decimal_point_position = std::string::npos;
token_string.push_back(char_traits<char_type>::to_char_type(current)); token_string.push_back(char_traits<char_type>::to_char_type(current));
} }
@@ -1430,6 +1433,11 @@ scan_number_done:
/// return current string value (implicitly resets the token; useful only once) /// return current string value (implicitly resets the token; useful only once)
string_t& get_string() string_t& get_string()
{ {
// translate decimal points from locale back to '.' (#4084)
if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
{
token_buffer[decimal_point_position] = '.';
}
return token_buffer; return token_buffer;
} }
@@ -1627,6 +1635,8 @@ scan_number_done:
/// the decimal point /// the decimal point
const char_int_type decimal_point_char = '.'; const char_int_type decimal_point_char = '.';
/// the position of the decimal point in the input
std::size_t decimal_point_position = std::string::npos;
}; };
} // namespace detail } // namespace detail
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -69,10 +69,10 @@ class parser
public: public:
/// a parser reading from an input adapter /// a parser reading from an input adapter
explicit parser(InputAdapterType&& adapter, explicit parser(InputAdapterType&& adapter,
const parser_callback_t<BasicJsonType> cb = nullptr, parser_callback_t<BasicJsonType> cb = nullptr,
const bool allow_exceptions_ = true, const bool allow_exceptions_ = true,
const bool skip_comments = false) const bool skip_comments = false)
: callback(cb) : callback(std::move(cb))
, m_lexer(std::move(adapter), skip_comments) , m_lexer(std::move(adapter), skip_comments)
, allow_exceptions(allow_exceptions_) , allow_exceptions(allow_exceptions_)
{ {
@@ -94,7 +94,7 @@ class parser
{ {
if (callback) if (callback)
{ {
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
sax_parse_internal(&sdp); sax_parse_internal(&sdp);
// in strict mode, input must be completely read // in strict mode, input must be completely read
@@ -122,7 +122,7 @@ class parser
} }
else else
{ {
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
sax_parse_internal(&sdp); sax_parse_internal(&sdp);
// in strict mode, input must be completely read // in strict mode, input must be completely read
@@ -194,7 +194,7 @@ class parser
{ {
case token_type::begin_object: case token_type::begin_object:
{ {
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -239,7 +239,7 @@ class parser
case token_type::begin_array: case token_type::begin_array:
{ {
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
{ {
return false; return false;
} }
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -463,7 +463,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: equal @brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
*/ */
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator==(const IterImpl& other) const bool operator==(const IterImpl& other) const
@@ -474,7 +474,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
} }
JSON_ASSERT(m_object != nullptr); // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
if (m_object == nullptr)
{
return true;
}
switch (m_object->m_data.m_type) switch (m_object->m_data.m_type)
{ {
@@ -499,7 +503,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: not equal @brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
*/ */
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator!=(const IterImpl& other) const bool operator!=(const IterImpl& other) const
@@ -509,7 +513,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: smaller @brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
*/ */
bool operator<(const iter_impl& other) const bool operator<(const iter_impl& other) const
{ {
@@ -519,7 +523,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
} }
JSON_ASSERT(m_object != nullptr); // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
if (m_object == nullptr)
{
// the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
return false;
}
switch (m_object->m_data.m_type) switch (m_object->m_data.m_type)
{ {
@@ -544,7 +553,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: less than or equal @brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
*/ */
bool operator<=(const iter_impl& other) const bool operator<=(const iter_impl& other) const
{ {
@@ -553,7 +562,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: greater than @brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
*/ */
bool operator>(const iter_impl& other) const bool operator>(const iter_impl& other) const
{ {
@@ -562,7 +571,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/*! /*!
@brief comparison: greater than or equal @brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized.
*/ */
bool operator>=(const iter_impl& other) const bool operator>=(const iter_impl& other) const
{ {
@@ -1,16 +1,15 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
#include <cstddef> // size_t #include <cstddef> // size_t
#include <iterator> // input_iterator_tag #include <iterator> // forward_iterator_tag
#include <string> // string, to_string
#include <tuple> // tuple_size, get, tuple_element #include <tuple> // tuple_size, get, tuple_element
#include <utility> // move #include <utility> // move
@@ -20,19 +19,13 @@
#include <nlohmann/detail/abi_macros.hpp> #include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_utils.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail namespace detail
{ {
template<typename string_type>
void int_to_string( string_type& target, std::size_t value )
{
// For ADL
using std::to_string;
target = to_string(value);
}
template<typename IteratorType> class iteration_proxy_value template<typename IteratorType> class iteration_proxy_value
{ {
public: public:
@@ -40,7 +33,7 @@ template<typename IteratorType> class iteration_proxy_value
using value_type = iteration_proxy_value; using value_type = iteration_proxy_value;
using pointer = value_type *; using pointer = value_type *;
using reference = value_type &; using reference = value_type &;
using iterator_category = std::input_iterator_tag; using iterator_category = std::forward_iterator_tag;
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
private: private:
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -228,7 +228,7 @@ class json_pointer
} }
const char* p = s.c_str(); const char* p = s.c_str();
char* p_end = nullptr; char* p_end = nullptr; // NOLINT(misc-const-correctness)
errno = 0; // strtoull doesn't reset errno errno = 0; // strtoull doesn't reset errno
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
if (p == p_end // invalid input or empty string if (p == p_end // invalid input or empty string
@@ -750,7 +750,7 @@ class json_pointer
// iterate array and use index as reference string // iterate array and use index as reference string
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
{ {
flatten(detail::concat(reference_string, '/', std::to_string(i)), flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
value.m_data.m_value.array->operator[](i), result); value.m_data.m_value.array->operator[](i), result);
} }
} }
@@ -769,7 +769,7 @@ class json_pointer
// iterate object and use keys as reference string // iterate object and use keys as reference string
for (const auto& element : *value.m_data.m_value.object) for (const auto& element : *value.m_data.m_value.object)
{ {
flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
} }
} }
break; break;
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -32,15 +32,20 @@
// C++ language standard detection // C++ language standard detection
// if the user manually specified the used c++ version this is skipped // 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(JSON_HAS_CPP_23) && !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) #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
#define JSON_HAS_CPP_23
#define JSON_HAS_CPP_20 #define JSON_HAS_CPP_20
#define JSON_HAS_CPP_17 #define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14 #define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
#define JSON_HAS_CPP_20
#define JSON_HAS_CPP_17 #define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14 #define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
#define JSON_HAS_CPP_14 #define JSON_HAS_CPP_14
#endif #endif
// the cpp 11 flag is always specified because it is the minimal required version // the cpp 11 flag is always specified because it is the minimal required version
@@ -216,7 +221,9 @@
template<typename BasicJsonType> \ template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \ { \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \ auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
@@ -228,7 +235,9 @@
template<typename BasicJsonType> \ template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \ { \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \ auto it = std::find_if(std::begin(m), std::end(m), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
@@ -391,42 +400,146 @@
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #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(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); #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1;
/*! /*!
@brief macro @brief macro
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
@since version 3.9.0 @since version 3.9.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
*/ */
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ #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__)) } \ template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
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__)) } friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
@since version 3.11.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ #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__)) } \ template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE
@since version 3.11.3
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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__)) } template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
/*! /*!
@brief macro @brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@since version 3.9.0 @since version 3.9.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
*/ */
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ #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__)) } \ template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
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__)) } void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
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__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
@since version 3.11.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ #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__)) } \ template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const 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_ONLY_SERIALIZE
@since version 3.11.3
@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
@since version 3.12.0
@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
*/
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
// inspired from https://stackoverflow.com/a/26745591 // inspired from https://stackoverflow.com/a/26745591
// allows to call any std function as if (e.g. with begin): // allows calling any std function as if (e.g., with begin):
// using std::begin; begin(x); // using std::begin; begin(x);
// //
// it allows using the detected idiom to retrieve the return type // it allows using the detected idiom to retrieve the return type
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -34,6 +34,7 @@
#undef JSON_HAS_CPP_14 #undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17 #undef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_20 #undef JSON_HAS_CPP_20
#undef JSON_HAS_CPP_23
#undef JSON_HAS_FILESYSTEM #undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef JSON_HAS_THREE_WAY_COMPARISON #undef JSON_HAS_THREE_WAY_COMPARISON
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-FileCopyrightText: 2018 The Abseil Authors // SPDX-FileCopyrightText: 2018 The Abseil Authors
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@@ -162,7 +162,7 @@ struct static_const
#endif #endif
template<typename T, typename... Args> template<typename T, typename... Args>
inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
{ {
return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
} }
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -19,7 +19,7 @@ namespace std_fs = std::experimental::filesystem;
} // namespace detail } // namespace detail
NLOHMANN_JSON_NAMESPACE_END NLOHMANN_JSON_NAMESPACE_END
#elif JSON_HAS_FILESYSTEM #elif JSON_HAS_FILESYSTEM
#include <filesystem> #include <filesystem> // NOLINT(build/c++17)
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail namespace detail
{ {
@@ -1,18 +1,18 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
#include <limits> // numeric_limits #include <limits> // numeric_limits
#include <string> // char_traits
#include <tuple> // tuple
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval #include <utility> // declval
#include <tuple> // tuple
#include <string> // char_traits
#include <nlohmann/detail/iterators/iterator_traits.hpp> #include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
@@ -211,7 +211,7 @@ struct char_traits<unsigned char> : std::char_traits<char>
static constexpr int_type eof() noexcept static constexpr int_type eof() noexcept
{ {
return static_cast<int_type>(EOF); return static_cast<int_type>(std::char_traits<char>::eof());
} }
}; };
@@ -235,7 +235,7 @@ struct char_traits<signed char> : std::char_traits<char>
static constexpr int_type eof() noexcept static constexpr int_type eof() noexcept
{ {
return static_cast<int_type>(EOF); return static_cast<int_type>(std::char_traits<char>::eof());
} }
}; };
@@ -471,8 +471,8 @@ is_detected<range_value_t, ConstructibleArrayType>::value&&
// special case for types like std::filesystem::path whose iterator's value_type are themselves // special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073 // c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
is_complete_type < is_complete_type <
detected_t<range_value_t, ConstructibleArrayType >>::value >> detected_t<range_value_t, ConstructibleArrayType >>::value >>
{ {
using value_type = range_value_t<ConstructibleArrayType>; using value_type = range_value_t<ConstructibleArrayType>;
@@ -734,7 +734,7 @@ struct value_in_range_of_impl1<OfType, T, true>
}; };
template<typename OfType, typename T> template<typename OfType, typename T>
inline constexpr bool value_in_range_of(T val) constexpr bool value_in_range_of(T val)
{ {
return value_in_range_of_impl1<OfType, T>::test(val); return value_in_range_of_impl1<OfType, T>::test(val);
} }
@@ -750,7 +750,7 @@ namespace impl
{ {
template<typename T> template<typename T>
inline constexpr bool is_c_string() constexpr bool is_c_string()
{ {
using TUnExt = typename std::remove_extent<T>::type; using TUnExt = typename std::remove_extent<T>::type;
using TUnCVExt = typename std::remove_cv<TUnExt>::type; using TUnCVExt = typename std::remove_cv<TUnExt>::type;
@@ -778,7 +778,7 @@ namespace impl
{ {
template<typename T> template<typename T>
inline constexpr bool is_transparent() constexpr bool is_transparent()
{ {
return is_detected<detect_is_transparent, T>::value; return is_detected<detect_is_transparent, T>::value;
} }
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -28,6 +28,13 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail namespace detail
{ {
/// how to encode BJData
enum class bjdata_version_t
{
draft2,
draft3,
};
/////////////////// ///////////////////
// binary writer // // binary writer //
/////////////////// ///////////////////
@@ -612,7 +619,7 @@ class binary_writer
case value_t::binary: case value_t::binary:
{ {
// step 0: determine if the binary type has a set subtype to // step 0: determine if the binary type has a set subtype to
// determine whether or not to use the ext or fixext types // determine whether to use the ext or fixext types
const bool use_ext = j.m_data.m_value.binary->has_subtype(); const bool use_ext = j.m_data.m_value.binary->has_subtype();
// step 1: write control byte and the byte string length // step 1: write control byte and the byte string length
@@ -735,11 +742,14 @@ class binary_writer
@param[in] use_type whether to use '$' prefixes (optimized format) @param[in] use_type whether to use '$' prefixes (optimized format)
@param[in] add_prefix whether prefixes need to be used for this value @param[in] add_prefix whether prefixes need to be used for this value
@param[in] use_bjdata whether write in BJData format, default is false @param[in] use_bjdata whether write in BJData format, default is false
@param[in] bjdata_version which BJData version to use, default is draft2
*/ */
void write_ubjson(const BasicJsonType& j, const bool use_count, void write_ubjson(const BasicJsonType& j, const bool use_count,
const bool use_type, const bool add_prefix = true, const bool use_type, const bool add_prefix = true,
const bool use_bjdata = false) const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
{ {
const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
switch (j.type()) switch (j.type())
{ {
case value_t::null: case value_t::null:
@@ -829,7 +839,7 @@ class binary_writer
for (const auto& el : *j.m_data.m_value.array) for (const auto& el : *j.m_data.m_value.array)
{ {
write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
} }
if (!use_count) if (!use_count)
@@ -847,11 +857,11 @@ class binary_writer
oa->write_character(to_char_type('[')); oa->write_character(to_char_type('['));
} }
if (use_type && !j.m_data.m_value.binary->empty()) if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
{ {
JSON_ASSERT(use_count); JSON_ASSERT(use_count);
oa->write_character(to_char_type('$')); oa->write_character(to_char_type('$'));
oa->write_character('U'); oa->write_character(bjdata_draft3 ? 'B' : 'U');
} }
if (use_count) if (use_count)
@@ -870,7 +880,7 @@ class binary_writer
{ {
for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
{ {
oa->write_character(to_char_type('U')); oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
oa->write_character(j.m_data.m_value.binary->data()[i]); oa->write_character(j.m_data.m_value.binary->data()[i]);
} }
} }
@@ -887,7 +897,7 @@ class binary_writer
{ {
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
{ {
if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
{ {
break; break;
} }
@@ -931,7 +941,7 @@ class binary_writer
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(el.first.c_str()), reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size()); el.first.size());
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata); write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
} }
if (!use_count) if (!use_count)
@@ -1087,7 +1097,8 @@ class binary_writer
} }
else else
{ {
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); write_bson_entry_header(name, 0x11 /* uint64 */);
write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
} }
} }
@@ -1615,10 +1626,11 @@ class binary_writer
/*! /*!
@return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
*/ */
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type) bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
{ {
std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'}, std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'} {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
{"char", 'C'}, {"byte", 'B'}
}; };
string_t key = "_ArrayType_"; string_t key = "_ArrayType_";
@@ -1648,10 +1660,10 @@ class binary_writer
oa->write_character('#'); oa->write_character('#');
key = "_ArraySize_"; key = "_ArraySize_";
write_ubjson(value.at(key), use_count, use_type, true, true); write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
key = "_ArrayData_"; key = "_ArrayData_";
if (dtype == 'U' || dtype == 'C') if (dtype == 'U' || dtype == 'C' || dtype == 'B')
{ {
for (const auto& el : value.at(key)) for (const auto& el : value.at(key))
{ {
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,10 +1,10 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> // SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -643,7 +643,7 @@ class serializer
@param[in] x unsigned integer number to count its digits @param[in] x unsigned integer number to count its digits
@return number of decimal digits @return number of decimal digits
*/ */
inline unsigned int count_digits(number_unsigned_t x) noexcept unsigned int count_digits(number_unsigned_t x) noexcept
{ {
unsigned int n_digits = 1; unsigned int n_digits = 1;
for (;;) for (;;)
@@ -926,7 +926,7 @@ class serializer
? (byte & 0x3fu) | (codep << 6u) ? (byte & 0x3fu) | (codep << 6u)
: (0xFFu >> type) & (byte); : (0xFFu >> type) & (byte);
const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
JSON_ASSERT(index < utf8d.size()); JSON_ASSERT(index < utf8d.size());
state = utf8d[index]; state = utf8d[index];
return state; return state;
@@ -952,7 +952,7 @@ class serializer
* absolute values of INT_MIN and INT_MAX are usually not the same. See * absolute values of INT_MIN and INT_MAX are usually not the same. See
* #1708 for details. * #1708 for details.
*/ */
inline number_unsigned_t remove_sign(number_integer_t x) noexcept number_unsigned_t remove_sign(number_integer_t x) noexcept
{ {
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
return static_cast<number_unsigned_t>(-(x + 1)) + 1; return static_cast<number_unsigned_t>(-(x + 1)) + 1;
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -0,0 +1,37 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef> // size_t
#include <string> // string, to_string
#include <nlohmann/detail/abi_macros.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename StringType>
void int_to_string(StringType& target, std::size_t value)
{
// For ADL
using std::to_string;
target = to_string(value);
}
template<typename StringType>
StringType to_string(std::size_t value)
{
StringType result;
int_to_string(result, value);
return result;
}
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
+129 -81
View File
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/****************************************************************************\ /****************************************************************************\
@@ -52,6 +52,7 @@
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/string_escape.hpp> #include <nlohmann/detail/string_escape.hpp>
#include <nlohmann/detail/string_utils.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/output/binary_writer.hpp> #include <nlohmann/detail/output/binary_writer.hpp>
@@ -114,9 +115,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
friend class ::nlohmann::detail::binary_writer; friend class ::nlohmann::detail::binary_writer;
template<typename BasicJsonType, typename InputType, typename SAX> template<typename BasicJsonType, typename InputType, typename SAX>
friend class ::nlohmann::detail::binary_reader; friend class ::nlohmann::detail::binary_reader;
template<typename BasicJsonType> template<typename BasicJsonType, typename InputAdapterType>
friend class ::nlohmann::detail::json_sax_dom_parser; friend class ::nlohmann::detail::json_sax_dom_parser;
template<typename BasicJsonType> template<typename BasicJsonType, typename InputAdapterType>
friend class ::nlohmann::detail::json_sax_dom_callback_parser; friend class ::nlohmann::detail::json_sax_dom_callback_parser;
friend class ::nlohmann::detail::exception; friend class ::nlohmann::detail::exception;
@@ -170,6 +171,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
using error_handler_t = detail::error_handler_t; using error_handler_t = detail::error_handler_t;
/// how to treat CBOR tags /// how to treat CBOR tags
using cbor_tag_handler_t = detail::cbor_tag_handler_t; using cbor_tag_handler_t = detail::cbor_tag_handler_t;
/// how to encode BJData
using bjdata_version_t = detail::bjdata_version_t;
/// helper type for initializer lists of basic_json values /// helper type for initializer lists of basic_json values
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
@@ -249,7 +252,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
basic_json result; basic_json result;
result["copyright"] = "(C) 2013-2023 Niels Lohmann"; result["copyright"] = "(C) 2013-2025 Niels Lohmann";
result["name"] = "JSON for Modern C++"; result["name"] = "JSON for Modern C++";
result["url"] = "https://github.com/nlohmann/json"; result["url"] = "https://github.com/nlohmann/json";
result["version"]["string"] = result["version"]["string"] =
@@ -514,7 +517,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
object = nullptr; // silence warning, see #821 object = nullptr; // silence warning, see #821
if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
{ {
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
} }
break; break;
} }
@@ -750,10 +753,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return it; return it;
} }
reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
{ {
#if JSON_DIAGNOSTICS #if JSON_DIAGNOSTICS
if (old_capacity != static_cast<std::size_t>(-1)) if (old_capacity != detail::unknown_size())
{ {
// see https://github.com/nlohmann/json/issues/2838 // see https://github.com/nlohmann/json/issues/2838
JSON_ASSERT(type() == value_t::array); JSON_ASSERT(type() == value_t::array);
@@ -847,6 +850,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::enable_if_t < detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
basic_json(const BasicJsonType& val) basic_json(const BasicJsonType& val)
#if JSON_DIAGNOSTIC_POSITIONS
: start_position(val.start_pos()),
end_position(val.end_pos())
#endif
{ {
using other_boolean_t = typename BasicJsonType::boolean_t; using other_boolean_t = typename BasicJsonType::boolean_t;
using other_number_float_t = typename BasicJsonType::number_float_t; using other_number_float_t = typename BasicJsonType::number_float_t;
@@ -893,6 +900,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
} }
JSON_ASSERT(m_data.m_type == val.type()); JSON_ASSERT(m_data.m_type == val.type());
set_parents(); set_parents();
assert_invariant(); assert_invariant();
} }
@@ -1029,7 +1037,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < class InputIT, typename std::enable_if < template < class InputIT, typename std::enable_if <
std::is_same<InputIT, typename basic_json_t::iterator>::value || std::is_same<InputIT, typename basic_json_t::iterator>::value ||
std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
basic_json(InputIT first, InputIT last) basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
{ {
JSON_ASSERT(first.m_object != nullptr); JSON_ASSERT(first.m_object != nullptr);
JSON_ASSERT(last.m_object != nullptr); JSON_ASSERT(last.m_object != nullptr);
@@ -1144,6 +1152,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(const basic_json& other) basic_json(const basic_json& other)
: json_base_class_t(other) : json_base_class_t(other)
#if JSON_DIAGNOSTIC_POSITIONS
, start_position(other.start_position)
, end_position(other.end_position)
#endif
{ {
m_data.m_type = other.m_data.m_type; m_data.m_type = other.m_data.m_type;
// check of passed value is valid // check of passed value is valid
@@ -1213,15 +1225,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(basic_json&& other) noexcept basic_json(basic_json&& other) noexcept
: json_base_class_t(std::forward<json_base_class_t>(other)), : json_base_class_t(std::forward<json_base_class_t>(other)),
m_data(std::move(other.m_data)) m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
#if JSON_DIAGNOSTIC_POSITIONS
, start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
, end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
#endif
{ {
// check that passed value is valid // check that passed value is valid
other.assert_invariant(false); other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
// invalidate payload // invalidate payload
other.m_data.m_type = value_t::null; other.m_data.m_type = value_t::null;
other.m_data.m_value = {}; other.m_data.m_value = {};
#if JSON_DIAGNOSTIC_POSITIONS
other.start_position = std::string::npos;
other.end_position = std::string::npos;
#endif
set_parents(); set_parents();
assert_invariant(); assert_invariant();
} }
@@ -1242,6 +1263,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
using std::swap; using std::swap;
swap(m_data.m_type, other.m_data.m_type); swap(m_data.m_type, other.m_data.m_type);
swap(m_data.m_value, other.m_data.m_value); swap(m_data.m_value, other.m_data.m_value);
#if JSON_DIAGNOSTIC_POSITIONS
swap(start_position, other.start_position);
swap(end_position, other.end_position);
#endif
json_base_class_t::operator=(std::move(other)); json_base_class_t::operator=(std::move(other));
set_parents(); set_parents();
@@ -1463,13 +1490,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// get a pointer to the value (integer number) /// get a pointer to the value (integer number)
number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
{ {
return is_number_integer() ? &m_data.m_value.number_integer : nullptr; return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
} }
/// get a pointer to the value (integer number) /// get a pointer to the value (integer number)
constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
{ {
return is_number_integer() ? &m_data.m_value.number_integer : nullptr; return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
} }
/// get a pointer to the value (unsigned number) /// get a pointer to the value (unsigned number)
@@ -1948,7 +1975,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
// create better exception explanation // create better exception explanation
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
} } // cppcheck-suppress[missingReturn]
} }
else else
{ {
@@ -1971,7 +1998,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
// create better exception explanation // create better exception explanation
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
} } // cppcheck-suppress[missingReturn]
} }
else else
{ {
@@ -2116,7 +2143,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief access specified object element /// @brief access specified object element
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
reference operator[](typename object_t::key_type key) reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
{ {
// implicitly convert null value to an empty object // implicitly convert null value to an empty object
if (is_null()) if (is_null())
@@ -2426,7 +2453,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < class IteratorType, detail::enable_if_t < template < class IteratorType, detail::enable_if_t <
std::is_same<IteratorType, typename basic_json_t::iterator>::value || std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
IteratorType erase(IteratorType pos) IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
@@ -2496,7 +2523,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < class IteratorType, detail::enable_if_t < template < class IteratorType, detail::enable_if_t <
std::is_same<IteratorType, typename basic_json_t::iterator>::value || std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
IteratorType erase(IteratorType first, IteratorType last) IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
@@ -3263,7 +3290,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @note: This uses std::distance to support GCC 4.8, /// @note: This uses std::distance to support GCC 4.8,
/// see https://github.com/nlohmann/json/pull/1257 /// see https://github.com/nlohmann/json/pull/1257
template<typename... Args> template<typename... Args>
iterator insert_iterator(const_iterator pos, Args&& ... args) iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
{ {
iterator result(this); iterator result(this);
JSON_ASSERT(m_data.m_value.array != nullptr); JSON_ASSERT(m_data.m_value.array != nullptr);
@@ -3282,7 +3309,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief inserts element into array /// @brief inserts element into array
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, const basic_json& val) iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
@@ -3302,14 +3329,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief inserts element into array /// @brief inserts element into array
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, basic_json&& val) iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{ {
return insert(pos, val); return insert(pos, val);
} }
/// @brief inserts copies of element into array /// @brief inserts copies of element into array
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, size_type cnt, const basic_json& val) iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
@@ -3329,7 +3356,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief inserts range of elements into array /// @brief inserts range of elements into array
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, const_iterator first, const_iterator last) iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_UNLIKELY(!is_array()))
@@ -3360,7 +3387,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief inserts elements from initializer list into array /// @brief inserts elements from initializer list into array
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, initializer_list_t ilist) iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_UNLIKELY(!is_array()))
@@ -3380,7 +3407,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief inserts range of elements into object /// @brief inserts range of elements into object
/// @sa https://json.nlohmann.me/api/basic_json/insert/ /// @sa https://json.nlohmann.me/api/basic_json/insert/
void insert(const_iterator first, const_iterator last) void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for objects // insert only works for objects
if (JSON_HEDLEY_UNLIKELY(!is_object())) if (JSON_HEDLEY_UNLIKELY(!is_object()))
@@ -3401,6 +3428,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
set_parents();
} }
/// @brief updates a JSON object from another object, overwriting existing keys /// @brief updates a JSON object from another object, overwriting existing keys
@@ -3412,7 +3440,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief updates a JSON object from another object, overwriting existing keys /// @brief updates a JSON object from another object, overwriting existing keys
/// @sa https://json.nlohmann.me/api/basic_json/update/ /// @sa https://json.nlohmann.me/api/basic_json/update/
void update(const_iterator first, const_iterator last, bool merge_objects = false) void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
{ {
// implicitly convert null value to an empty object // implicitly convert null value to an empty object
if (is_null()) if (is_null())
@@ -4013,12 +4041,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename InputType> template<typename InputType>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json parse(InputType&& i, static basic_json parse(InputType&& i,
const parser_callback_t cb = nullptr, parser_callback_t cb = nullptr,
const bool allow_exceptions = true, const bool allow_exceptions = true,
const bool ignore_comments = false) const bool ignore_comments = false)
{ {
basic_json result; basic_json result;
parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result); parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
return result; return result;
} }
@@ -4028,24 +4056,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json parse(IteratorType first, static basic_json parse(IteratorType first,
IteratorType last, IteratorType last,
const parser_callback_t cb = nullptr, parser_callback_t cb = nullptr,
const bool allow_exceptions = true, const bool allow_exceptions = true,
const bool ignore_comments = false) const bool ignore_comments = false)
{ {
basic_json result; basic_json result;
parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
return result; return result;
} }
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
static basic_json parse(detail::span_input_adapter&& i, static basic_json parse(detail::span_input_adapter&& i,
const parser_callback_t cb = nullptr, parser_callback_t cb = nullptr,
const bool allow_exceptions = true, const bool allow_exceptions = true,
const bool ignore_comments = false) const bool ignore_comments = false)
{ {
basic_json result; basic_json result;
parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
return result; return result;
} }
@@ -4224,6 +4252,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json* m_parent = nullptr; basic_json* m_parent = nullptr;
#endif #endif
#if JSON_DIAGNOSTIC_POSITIONS
/// the start position of the value
std::size_t start_position = std::string::npos;
/// the end position of the value
std::size_t end_position = std::string::npos;
public:
constexpr std::size_t start_pos() const noexcept
{
return start_position;
}
constexpr std::size_t end_pos() const noexcept
{
return end_position;
}
#endif
////////////////////////////////////////// //////////////////////////////////////////
// binary serialization/deserialization // // binary serialization/deserialization //
////////////////////////////////////////// //////////////////////////////////////////
@@ -4309,27 +4354,30 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
static std::vector<std::uint8_t> to_bjdata(const basic_json& j, static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
const bool use_size = false, const bool use_size = false,
const bool use_type = false) const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
{ {
std::vector<std::uint8_t> result; std::vector<std::uint8_t> result;
to_bjdata(j, result, use_size, use_type); to_bjdata(j, result, use_size, use_type, version);
return result; return result;
} }
/// @brief create a BJData serialization of a given JSON value /// @brief create a BJData serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
{ {
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
} }
/// @brief create a BJData serialization of a given JSON value /// @brief create a BJData serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
{ {
binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
} }
/// @brief create a BSON serialization of a given JSON value /// @brief create a BSON serialization of a given JSON value
@@ -4365,9 +4413,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4381,9 +4429,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4406,10 +4454,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4422,9 +4470,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4437,9 +4485,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4460,10 +4508,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4476,9 +4524,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4491,9 +4539,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4514,10 +4562,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4530,9 +4578,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4545,9 +4593,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4560,9 +4608,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4575,9 +4623,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@@ -4598,10 +4646,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true) const bool allow_exceptions = true)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
/// @} /// @}
@@ -4702,7 +4750,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// the valid JSON Patch operations // the valid JSON Patch operations
enum class patch_operations {add, remove, replace, move, copy, test, invalid}; enum class patch_operations {add, remove, replace, move, copy, test, invalid};
const auto get_op = [](const std::string & op) const auto get_op = [](const string_t& op)
{ {
if (op == "add") if (op == "add")
{ {
@@ -4733,7 +4781,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}; };
// wrapper for "add" operation; add value at ptr // wrapper for "add" operation; add value at ptr
const auto operation_add = [&result](json_pointer & ptr, basic_json val) const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
{ {
// adding to the root of the target document means replacing it // adding to the root of the target document means replacing it
if (ptr.empty()) if (ptr.empty())
@@ -4839,15 +4887,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
for (const auto& val : json_patch) for (const auto& val : json_patch)
{ {
// wrapper to get a value for an operation // wrapper to get a value for an operation
const auto get_value = [&val](const std::string & op, const auto get_value = [&val](const string_t& op,
const std::string & member, const string_t& member,
bool string_type) -> basic_json & bool string_type) -> basic_json &
{ {
// find value // find value
auto it = val.m_data.m_value.object->find(member); auto it = val.m_data.m_value.object->find(member);
// context-sensitive error message // context-sensitive error message
const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
// check if desired value is present // check if desired value is present
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
@@ -4874,8 +4922,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
// collect mandatory members // collect mandatory members
const auto op = get_value("op", "op", true).template get<std::string>(); const auto op = get_value("op", "op", true).template get<string_t>();
const auto path = get_value(op, "path", true).template get<std::string>(); const auto path = get_value(op, "path", true).template get<string_t>();
json_pointer ptr(path); json_pointer ptr(path);
switch (get_op(op)) switch (get_op(op))
@@ -4901,7 +4949,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case patch_operations::move: case patch_operations::move:
{ {
const auto from_path = get_value("move", "from", true).template get<std::string>(); const auto from_path = get_value("move", "from", true).template get<string_t>();
json_pointer from_ptr(from_path); json_pointer from_ptr(from_path);
// the "from" location must exist - use at() // the "from" location must exist - use at()
@@ -4918,7 +4966,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case patch_operations::copy: case patch_operations::copy:
{ {
const auto from_path = get_value("copy", "from", true).template get<std::string>(); const auto from_path = get_value("copy", "from", true).template get<string_t>();
const json_pointer from_ptr(from_path); const json_pointer from_ptr(from_path);
// the "from" location must exist - use at() // the "from" location must exist - use at()
@@ -4978,7 +5026,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/diff/ /// @sa https://json.nlohmann.me/api/basic_json/diff/
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json diff(const basic_json& source, const basic_json& target, static basic_json diff(const basic_json& source, const basic_json& target,
const std::string& path = "") const string_t& path = "")
{ {
// the patch // the patch
basic_json result(value_t::array); basic_json result(value_t::array);
@@ -5008,7 +5056,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
while (i < source.size() && i < target.size()) while (i < source.size() && i < target.size())
{ {
// recursive call to compare array values at index i // recursive call to compare array values at index i
auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
result.insert(result.end(), temp_diff.begin(), temp_diff.end()); result.insert(result.end(), temp_diff.begin(), temp_diff.end());
++i; ++i;
} }
@@ -5025,7 +5073,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result.insert(result.begin() + end_index, object( result.insert(result.begin() + end_index, object(
{ {
{"op", "remove"}, {"op", "remove"},
{"path", detail::concat(path, '/', std::to_string(i))} {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
})); }));
++i; ++i;
} }
@@ -5036,7 +5084,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result.push_back( result.push_back(
{ {
{"op", "add"}, {"op", "add"},
{"path", detail::concat(path, "/-")}, {"path", detail::concat<string_t>(path, "/-")},
{"value", target[i]} {"value", target[i]}
}); });
++i; ++i;
@@ -5051,7 +5099,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
for (auto it = source.cbegin(); it != source.cend(); ++it) for (auto it = source.cbegin(); it != source.cend(); ++it)
{ {
// escape the key name to be used in a JSON patch // escape the key name to be used in a JSON patch
const auto path_key = detail::concat(path, '/', detail::escape(it.key())); const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
if (target.find(it.key()) != target.end()) if (target.find(it.key()) != target.end())
{ {
@@ -5075,7 +5123,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (source.find(it.key()) == source.end()) if (source.find(it.key()) == source.end())
{ {
// found a key that is not in this -> add it // found a key that is not in this -> add it
const auto path_key = detail::concat(path, '/', detail::escape(it.key())); const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
result.push_back( result.push_back(
{ {
{"op", "add"}, {"path", path_key}, {"op", "add"}, {"path", path_key},
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
@@ -2,11 +2,11 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com> // SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* Hedley - https://nemequ.github.io/hedley /* Hedley - https://nemequ.github.io/hedley
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
File diff suppressed because it is too large Load Diff
@@ -1,9 +1,9 @@
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
@@ -18,10 +18,10 @@
// #include <nlohmann/detail/abi_macros.hpp> // #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____ // __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ // __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3 // | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json // |_____|_____|_____|_|___| https://github.com/nlohmann/json
// //
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@@ -30,20 +30,24 @@
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) #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 != 3 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
#warning "Already included a different version of the library!" #warning "Already included a different version of the library!"
#endif #endif
#endif #endif
#endif #endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) #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_MINOR 12 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) #define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS #ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0 #define JSON_DIAGNOSTICS 0
#endif #endif
#ifndef JSON_DIAGNOSTIC_POSITIONS
#define JSON_DIAGNOSTIC_POSITIONS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif #endif
@@ -54,6 +58,12 @@
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif #endif
#if JSON_DIAGNOSTIC_POSITIONS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else #else
@@ -65,14 +75,15 @@
#endif #endif
// Construct the namespace ABI tags component // 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_EX(a, b, c) json_abi ## a ## b ## c
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
#define NLOHMANN_JSON_ABI_TAGS \ #define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
// Construct the namespace version component // Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
+2 -1
View File
@@ -1,3 +1,4 @@
set(JOLT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/JoltPhysics") set(JOLT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/JoltPhysics")
set(JOLT_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/JoltPhysics/lib/libJolt.a") set(JOLT_LIBRARIES_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/JoltPhysics/lib/Release/libJolt.a")
set(JOLT_LIBRARIES_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/JoltPhysics/lib/Debug/libJolt.a")
+1
View File
@@ -0,0 +1 @@
set(DRLIBS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/dr_libs/")
+19 -28
View File
@@ -2,12 +2,12 @@
"$schema": "https://json-schema.org/draft-07/schema#", "$schema": "https://json-schema.org/draft-07/schema#",
"title": "SceneDescription", "title": "SceneDescription",
"type": "object", "type": "object",
"ID": 100,
"properties": { "properties": {
"name": { "type": "string", "ID": 101}, "name": { "type": "string", "ID": 101},
"description": { "type": "string", "ID": 102}, "description": { "type": "string", "ID": 102},
"entities": { "entities": {
"type": "array", "type": "array",
"ID": 103,
"items": { "$ref": "#/definitions/Entity" } "items": { "$ref": "#/definitions/Entity" }
} }
}, },
@@ -16,7 +16,6 @@
"Entity": { "Entity": {
"type": "object", "type": "object",
"ID": 200,
"properties": { "properties": {
"entityref": { "type": "integer", "ID": 201 }, "entityref": { "type": "integer", "ID": 201 },
"parent": { "type": ["integer", "null"] , "ID": 202}, "parent": { "type": ["integer", "null"] , "ID": 202},
@@ -27,26 +26,24 @@
"ID": 205, "ID": 205,
"items": { "type": "integer" } "items": { "type": "integer" }
}, },
"components": { "$ref": "#/definitions/Components" } "components": { "ID": 206, "$ref": "#/definitions/Components" }
}, },
"required": ["entityref", "name", "components"] "required": ["entityref", "name", "components"]
}, },
"Components": { "Components": {
"type": "object", "type": "object",
"ID": 300,
"properties": { "properties": {
"transform": { "$ref": "#/definitions/Transform" }, "transform": { "ID": 2061, "$ref": "#/definitions/Transform" },
"renderer": { "$ref": "#/definitions/Renderer" }, "renderer": { "ID": 2062, "$ref": "#/definitions/Renderer" },
"camera": { "$ref": "#/definitions/Camera" }, "camera": { "ID": 2063, "$ref": "#/definitions/Camera" },
"collider": { "$ref": "#/definitions/Collider" }, "collider": { "ID": 2064, "$ref": "#/definitions/Collider" },
"rigidbody": { "$ref": "#/definitions/RigidBody" } "rigidbody": { "ID": 2065, "$ref": "#/definitions/RigidBody" }
} }
}, },
"Vec3": { "Vec3": {
"type": "array", "type": "array",
"ID": 401,
"items": { "type": "number" }, "items": { "type": "number" },
"minItems": 3, "minItems": 3,
"maxItems": 3 "maxItems": 3
@@ -54,7 +51,6 @@
"Vec4": { "Vec4": {
"type": "array", "type": "array",
"ID": 402,
"items": { "type": "number" }, "items": { "type": "number" },
"minItems": 4, "minItems": 4,
"maxItems": 4 "maxItems": 4
@@ -62,29 +58,26 @@
"Transform": { "Transform": {
"type": "object", "type": "object",
"ID": 301,
"properties": { "properties": {
"position": { "$ref": "#/definitions/Vec3" }, "position": { "ID": 3011, "$ref": "#/definitions/Vec3" },
"rotation": { "$ref": "#/definitions/Vec3" }, "rotation": { "ID": 3012, "$ref": "#/definitions/Vec3" },
"scale": { "$ref": "#/definitions/Vec3" } "scale": { "ID": 3013, "$ref": "#/definitions/Vec3" }
}, },
"required": ["position", "rotation", "scale"] "required": ["position", "rotation", "scale"]
}, },
"Renderer": { "Renderer": {
"type": "object", "type": ["object", "null"],
"ID": 302,
"properties": { "properties": {
"model": { "type": "string", "ID": 3021 }, "model": { "type": ["string", "null"], "ID": 3021 },
"shader": { "type": "string", "ID": 3022 }, "shader": { "type": "string", "ID": 3022 },
"albedo": { "type": "string", "ID": 3023 } "albedo": { "type": ["string", "null"], "ID": 3023 }
}, },
"required": ["model", "shader"] "required": ["model", "shader"]
}, },
"Camera": { "Camera": {
"type": "object", "type": ["object", "null"],
"ID": 303,
"properties": { "properties": {
"fov": { "type": "number", "minimum": 1, "maximum": 179, "ID": 3031 }, "fov": { "type": "number", "minimum": 1, "maximum": 179, "ID": 3031 },
"near": { "type": "number", "minimum": 0.001, "ID": 3032 }, "near": { "type": "number", "minimum": 0.001, "ID": 3032 },
@@ -94,17 +87,16 @@
}, },
"Collider": { "Collider": {
"type": "object", "type": ["object", "null"],
"ID": 304,
"properties": { "properties": {
"type": { "type": {
"type": "string", "type": "string",
"ID": 3041, "ID": 3041,
"enum": ["Box", "Sphere", "Capsule", "ConvexHull", "Mesh", "Compound"] "enum": ["Box", "Sphere", "Capsule", "ConvexHull", "Mesh", "Compound"]
}, },
"size": { "$ref": "#/definitions/Vec3" }, "size": { "$ref": "#/definitions/Vec3", "ID": 3042 },
"radius": { "type": "number", "minimum": 0, "ID": 3042 }, "radius": { "type": "number", "minimum": 0, "ID": 3043 },
"halfHeight": { "type": "number", "minimum": 0, "ID": 3043 } "halfHeight": { "type": "number", "minimum": 0, "ID": 3044 }
}, },
"required": ["type"], "required": ["type"],
"allOf": [ "allOf": [
@@ -124,8 +116,7 @@
}, },
"RigidBody": { "RigidBody": {
"type": "object", "type": ["object", "null"],
"ID": 305,
"properties": { "properties": {
"type": { "type": {
"type": "string", "type": "string",
@@ -1,7 +1,7 @@
#ifndef CABSTRACT_COMPONENT_HPP #ifndef CABSTRACT_COMPONENT_HPP
#define CABSTRACT_COMPONENT_HPP #define CABSTRACT_COMPONENT_HPP
#include "../Utils/CSerializable.hpp" #include "../../Utils/JsonParser/CSerializable.hpp"
#include "../Entity/CEntity.hpp" #include "../Entity/CEntity.hpp"
namespace CosmicCore { namespace CosmicCore {
@@ -25,9 +25,16 @@ namespace CosmicCore {
class CAbstractComponent : public CSerializable{ class CAbstractComponent : public CSerializable{
public: public:
CAbstractComponent(CEntity& entity): m_owningEntity(entity){}; CAbstractComponent(CEntity& entity): m_owningEntity(entity){};
CAbstractComponent(CAbstractComponent&& other) = default;
CAbstractComponent& operator=(CAbstractComponent&&) = default;
virtual ~CAbstractComponent() = default; virtual ~CAbstractComponent() = default;
CEntity getEntity() const { CEntity& getEntity() {
return m_owningEntity;
}
const CEntity& getEntity() const {
return m_owningEntity; return m_owningEntity;
} }
+8 -6
View File
@@ -6,7 +6,7 @@
#define GLM_FORCE_DEPTH_ZERO_TO_ONE #define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include "../../Graphics/API/VulkanImpl.hpp" #include "../../Systems/Graphics/API/VulkanImplementation/VulkanImpl.hpp"
#include "../Geometry/CTransform.hpp" #include "../Geometry/CTransform.hpp"
namespace CosmicCore { namespace CosmicCore {
@@ -65,14 +65,15 @@ public:
// getters // getters
glm::mat4 getView(const CTransform& transform) const { glm::mat4 getView(const CTransform& transform) const {
glm::quat q = transform.getOrientation(); /*glm::quat q = transform.getOrientation();
glm::vec3 position = transform.getCenter(); glm::vec3 position = transform.getCenter();
// rotation inverse (conjugué du quaternion) + translation inverse // rotation inverse (conjugué du quaternion) + translation inverse
glm::mat4 rotInverse = glm::toMat4(glm::conjugate(q)); glm::mat4 rotInverse = glm::toMat4(glm::conjugate(q));
glm::mat4 transInverse = glm::translate(glm::mat4(1.0f), -position); glm::mat4 transInverse = glm::translate(glm::mat4(1.0f), -position);*/
return rotInverse * transInverse; //return rotInverse * transInverse;
return glm::inverse(transform.getInheritedTransformation());
} }
glm::mat4 getProjection() const { return m_projection; } glm::mat4 getProjection() const { return m_projection; }
@@ -145,8 +146,9 @@ public:
} }
} }
nlohmann::json to_json(){
nlohmann::json to_json(){}; return nlohmann::json();
};
}; };
} // namespace CosmicCore } // namespace CosmicCore
@@ -3,7 +3,7 @@
#include "CAbstractCollider.hpp" #include "CAbstractCollider.hpp"
#include <Jolt/Jolt.h> #include <Jolt/Jolt.h>
#include <Jolt/Physics/Collision/Shape/Shape.h> #include <Jolt/Physics/Collision/Shape/Shape.h>
#include "../../Graphics/Data/Mesh/CMesh.hpp" #include "../../Systems/Graphics/Data/Mesh/CMesh.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
namespace CosmicCore { namespace CosmicCore {
@@ -1,5 +1,5 @@
#include "CTransform.hpp" #include "CTransform.hpp"
#include "../../Graphics/API/VulkanImpl.hpp" #include "../../Systems/Graphics/API/VulkanImplementation/VulkanImpl.hpp"
#include "../Relationships/CRelationship.hpp" #include "../Relationships/CRelationship.hpp"
namespace CosmicCore namespace CosmicCore
{ {
@@ -71,10 +71,10 @@ namespace CosmicCore
auto& rel = registry().get<CRelationship>(*getEntity()); auto& rel = registry().get<CRelationship>(*getEntity());
if (rel.getParent() == entt::null) if (!rel.getParent().has_value())
return m_transformation; return m_transformation;
auto& parentTransform = registry().get<CTransform>(rel.getParent()); auto& parentTransform = registry().get<CTransform>(rel.getParent().value());
return parentTransform.getInheritedTransformation() * m_transformation; return parentTransform.getInheritedTransformation() * m_transformation;
} }
@@ -10,9 +10,8 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include "../../Systems/Graphics/API/VulkanImplementation/VMABuffer.hpp"
#include "../../Graphics/API/VMABuffer.hpp" #include "../../Systems/Graphics/API/VulkanImplementation/ManagedDescriptorSet.hpp"
#include "../../Graphics/API/ManagedDescriptorSet.hpp"
namespace CosmicCore namespace CosmicCore
{ {
@@ -1,7 +1,7 @@
#ifndef CTESTRENDERER_HPP #ifndef CTESTRENDERER_HPP
#define CTESTRENDERER_HPP #define CTESTRENDERER_HPP
#include "CAbstractRenderer.hpp" #include "CAbstractRenderer.hpp"
#include "../../Graphics/Data/CModel.hpp" #include "../../Systems/Graphics/Data/Model/CModel.hpp"
namespace CosmicCore { namespace CosmicCore {
class CRenderer: public CAbstractRenderer class CRenderer: public CAbstractRenderer
{ {
@@ -3,24 +3,26 @@
#include "../CAbstractComponent.hpp" #include "../CAbstractComponent.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
#include <string> #include <optional>
#include <vector> #include <vector>
namespace CosmicCore { namespace CosmicCore {
class CRelationship : public CAbstractComponent{ class CRelationship : public CAbstractComponent{
private: private:
EntityId parent = entt::null; std::optional<EntityId> parent;
std::vector<EntityId> children; std::vector<EntityId> children;
public: public:
CRelationship(CEntity& entity): CAbstractComponent(entity){} CRelationship(CEntity& entity): CAbstractComponent(entity){}
CRelationship(CEntity& entity, EntityId p): CAbstractComponent(entity), parent(p){} CRelationship(CEntity& entity, std::optional<EntityId> p): CAbstractComponent(entity), parent(p){}
CRelationship(CEntity& entity, std::vector<EntityId> childs): CAbstractComponent(entity), children(childs){} CRelationship(CEntity& entity, std::vector<EntityId> childs): CAbstractComponent(entity), children(childs){}
CRelationship(CEntity& entity, EntityId p, std::vector<EntityId> childs): CAbstractComponent(entity), parent(p), children(childs){} CRelationship(CEntity& entity, std::optional<EntityId> p, std::vector<EntityId> childs): CAbstractComponent(entity), parent(p), children(childs){}
nlohmann::json to_json(){return nlohmann::json();} nlohmann::json to_json(){return nlohmann::json();}
void setParent(EntityId par){parent = par;} void setParent(EntityId par){parent = par;}
void addChild(EntityId child){children.emplace_back(child);} void addChild(EntityId child){children.emplace_back(child);}
EntityId getParent(){return parent;} std::optional<EntityId> getParent(){return parent;}
const std::optional<EntityId> getParent() const {return parent;}
std::vector<EntityId>& getChildren(){return children;} std::vector<EntityId>& getChildren(){return children;}
}; };
@@ -1,10 +1,9 @@
#include "CRigidBody.hpp" #include "CRigidBody.hpp"
#include "../../Physics/PhysicsLayers.hpp" #include "../../Systems/Physics/PhysicsLayers.hpp"
#include "../../Scene/CScene.hpp" #include "../../Scene/CScene.hpp"
#include "../Geometry/CTransform.hpp" #include "../Geometry/CTransform.hpp"
#include "../Collider/CCollider.hpp" #include "../Collider/CCollider.hpp"
#include "Jolt/Physics/EActivation.h" #include "Jolt/Physics/EActivation.h"
#include <iostream>
namespace CosmicCore { namespace CosmicCore {
CRigidBody::CRigidBody(CEntity& entity, EBodyType type): CAbstractRigidBody(entity), m_bodyType(type) CRigidBody::CRigidBody(CEntity& entity, EBodyType type): CAbstractRigidBody(entity), m_bodyType(type)
@@ -1,31 +1,9 @@
#include "CAbstractScript.hpp" #include "CAbstractScript.hpp"
//#include "../../../Controller/CKernel.hpp"
namespace CosmicCore { namespace CosmicCore {
//CPlugin<CAbstractScript>* CAbstractScript::m_scriptPLugin = nullptr;
CAbstractScript::CAbstractScript(CEntity& entity) : CAbstractComponent(entity) CAbstractScript::CAbstractScript(CEntity& entity, const std::string& name) : CAbstractComponent(entity), m_scriptName(name)
{ {
//m_kernelPTR = CKernel::m_kernel;
}
nlohmann::json CAbstractScript::to_json()
{
nlohmann::json absScript;
absScript["scriptName"] = m_scriptName;
absScript["ComponentType"] = EComponentType::COMPONENT_SCRIPT;
return absScript;
}
CAbstractScript* CAbstractScript::from_json(CEntity& entity, nlohmann::json& j)
{
/*std::string name = j["scriptName"];
CAbstractScript* script = CAbstractScript::m_scriptPLugin->useCreator("instantiate"+name);
script->setEntity(entity);
script->setKernel(CKernel::m_kernel);
script->start();
return script;*/
return nullptr;
} }
} }
@@ -3,31 +3,27 @@
#include "../CAbstractComponent.hpp" #include "../CAbstractComponent.hpp"
#include "../../Entity/CEntity.hpp" #include "../../Entity/CEntity.hpp"
#include <memory>
//#include "../../../Modules/CPlugin.hpp"
//#include "../../../Controller/CKernel.fwd.hpp"
namespace CosmicCore { namespace CosmicCore {
//TODO
class CAbstractScript : public CAbstractComponent class CAbstractScript : public CAbstractComponent
{ {
private: private:
std::string m_scriptName; std::string m_scriptName;
//CKernel* m_kernelPTR;
public: public:
//static CPlugin<CAbstractScript>* m_scriptPLugin; CAbstractScript(CEntity& entity, const std::string& name);
CAbstractScript(CEntity& entity); CAbstractScript(CAbstractScript&& other) = default;
CAbstractScript& operator=(CAbstractScript&&) = default;
virtual void start() = 0; virtual void start() = 0;
virtual void update() = 0; virtual void update() = 0;
nlohmann::json to_json(); virtual void destroy() = 0;
static CAbstractScript* from_json(CEntity& entity, nlohmann::json& j); virtual nlohmann::json to_json() = 0;
virtual ~CAbstractScript(){}; virtual ~CAbstractScript() = default;
std::string getName() { return m_scriptName; }; std::string getName() { return m_scriptName; };
//CKernel* getKernel() { return m_kernelPTR; }; void setName(const std::string& name) { m_scriptName = name; };
//void setKernel(CKernel* kernel) { m_kernelPTR = kernel; };
void setName(std::string name) { m_scriptName = name; };
}; };
} }
#endif #endif
@@ -0,0 +1,38 @@
#include "CScript.hpp"
#include "Core/Component/Script/CAbstractScript.hpp"
#include "Core/Systems/Scripts/API/CScriptAPI.hpp"
namespace CosmicCore {
CScript::CScript(CEntity& entity, const std::string& name, std::unique_ptr<CAbstractScript>&& innerScript) : CAbstractScript(entity, name), m_innerScript(std::move(innerScript))
{
}
CScript::CScript(CEntity& entity, const std::string& name) : CAbstractScript(entity, name)
{
m_innerScript = CScriptAPI::scripts().create(name, entity, name);
}
void CScript::start()
{
m_innerScript->start();
}
void CScript::update()
{
m_innerScript->update();
}
void CScript::destroy()
{
m_innerScript->destroy();
}
nlohmann::json CScript::to_json()
{
return m_innerScript->to_json();
}
}
@@ -0,0 +1,30 @@
#ifndef CSCRIPT_HPP
#define CSCRIPT_HPP
#include "CAbstractScript.hpp"
#include "Core/Entity/CEntity.hpp"
#include <memory>
namespace CosmicCore {
class CScript : public CAbstractScript
{
private:
std::unique_ptr<CAbstractScript> m_innerScript;
public:
CScript(CEntity& entity, const std::string& name, std::unique_ptr<CAbstractScript>&& innerScript);
CScript(CEntity& entity, const std::string& name);
CScript(CScript&& mov) = default;
CScript& operator=(CScript&&) = default;
void start() override;
void update() override;
void destroy() override;
nlohmann::json to_json() override;
virtual ~CScript() = default;
};
}
#endif
@@ -0,0 +1,23 @@
#include "CScriptManager.hpp"
#include "Core/Component/Script/CScript.hpp"
#include "nlohmann/json_fwd.hpp"
namespace CosmicCore {
void CScriptManager::emplace(const std::string& name)
{
m_scripts.emplace_back(getEntity(), name);
}
nlohmann::json CScriptManager::to_json(){
return nlohmann::json();
}
void CScriptManager::updateAll()
{
for(auto& sc : m_scripts)
{
sc.update();
}
}
}
@@ -0,0 +1,27 @@
#ifndef CSCRIPTMANAGER_HPP
#define CSCRIPTMANAGER_HPP
#include "Core/Component/CAbstractComponent.hpp"
#include "Core/Component/Script/CScript.hpp"
#include "Core/Entity/CEntity.hpp"
#include <vector>
namespace CosmicCore {
class CScriptManager: public CAbstractComponent
{
private:
std::vector<CScript> m_scripts;
public:
CScriptManager(CEntity& entity) : CAbstractComponent(entity) {};
CScriptManager(CScriptManager&& mov) = default;
~CScriptManager() = default;
CScriptManager& operator=(CScriptManager&&) = default;
void emplace(const std::string& name);
void updateAll();
nlohmann::json to_json();
};
}
#endif
@@ -0,0 +1,121 @@
#include "CSpeaker.hpp"
#include "../../Systems/Resources/API/CResourceAPI.hpp"
namespace CosmicCore {
CSpeaker::CSpeaker(CEntity& entity): CAbstractComponent(entity)
{
}
void CSpeaker::addClip(const std::string& name, const std::string& path, float gain, float pitch, bool loop, bool spatial) {
auto* clip = CResourceAPI::resources().sounds().loadClip(path);
SoundInstance instance;
instance.clip = clip;
instance.gain = gain;
instance.pitch = pitch;
instance.spatial = spatial;
instance.loop = loop;
alGenSources(1, &instance.source);
alSourcei(instance.source, AL_SOURCE_RELATIVE, AL_FALSE);
//TODO
// à passer dans la config
alSourcef(instance.source, AL_ROLLOFF_FACTOR, 1.3f);
alSourcef(instance.source, AL_REFERENCE_DISTANCE, 0.2f); // distance à partir de laquelle le son diminue
alSourcef(instance.source, AL_MAX_DISTANCE, 100.0f); // distance max
alSourcei(instance.source, AL_BUFFER, clip->buffer);
alSourcef(instance.source, AL_GAIN, m_masterGain*instance.gain);
alSourcei(instance.source, AL_LOOPING, instance.loop);
alSource3f(instance.source, AL_POSITION, 0, 0, 0);
m_clips[name] = instance;
}
void CSpeaker::addClip(const std::string& name, CAudioClip* clip, float gain, float pitch, bool loop, bool spatial) {
SoundInstance instance;
instance.clip = clip;
instance.gain = gain;
instance.pitch = pitch;
instance.spatial = spatial;
instance.loop = loop;
alGenSources(1, &instance.source);
alSourcei(instance.source, AL_SOURCE_RELATIVE, AL_FALSE);
//TODO
// à passer dans la config
alSourcef(instance.source, AL_ROLLOFF_FACTOR, 1.3f);
alSourcef(instance.source, AL_REFERENCE_DISTANCE, 0.2f); // distance à partir de laquelle le son diminue
alSourcef(instance.source, AL_MAX_DISTANCE, 100.0f); // distance max
alSourcei(instance.source, AL_BUFFER, clip->buffer);
alSourcef(instance.source, AL_GAIN, m_masterGain*instance.gain);
alSourcei(instance.source, AL_LOOPING, instance.loop);
alSource3f(instance.source, AL_POSITION, 0, 0, 0);
m_clips[name] = instance;
}
void CSpeaker::play(const std::string& name) {
auto it = m_clips.find(name);
if (it == m_clips.end()) return;
alSourcePlay(it->second.source);
}
void CSpeaker::stop(const std::string& name) {
auto it = m_clips.find(name);
if (it == m_clips.end()) return;
alSourceStop(it->second.source);
}
void CSpeaker::pause(const std::string& name) {
auto it = m_clips.find(name);
if (it == m_clips.end()) return;
alSourcePause(it->second.source);
}
void CSpeaker::stopAll() {
for (auto& [name, instance] : m_clips)
alSourceStop(instance.source);
}
void CSpeaker::setLoop(const std::string& name, bool loop) {
auto it = m_clips.find(name);
if (it == m_clips.end()) return;
it->second.loop = loop;
alSourcei(it->second.source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
}
void CSpeaker::setGain(const std::string& name, float gain) {
auto it = m_clips.find(name);
if (it == m_clips.end()) return;
it->second.gain = gain;
alSourcef(it->second.source, AL_GAIN, gain * m_masterGain);
}
void CSpeaker::updatePosition(const CTransform& transform, glm::vec3 velocity) {
for (auto& [name, instance] : m_clips) {
auto center = transform.getCenter();
if (!instance.spatial) continue;
alSource3f(instance.source, AL_POSITION,
center.x, center.y, center.z);
alSource3f(instance.source, AL_VELOCITY,
velocity.x, velocity.y, velocity.z);
}
}
bool CSpeaker::isPlaying(const std::string& name) const {
auto it = m_clips.find(name);
if (it == m_clips.end()) return false;
ALint state;
alGetSourcei(it->second.source, AL_SOURCE_STATE, &state);
return state == AL_PLAYING;
}
CSpeaker::~CSpeaker() {
for (auto& [name, instance] : m_clips)
alDeleteSources(1, &instance.source);
}
}
@@ -0,0 +1,58 @@
#ifndef CSPEAKER_HPP
#define CSPEAKER_HPP
#include <AL/al.h>
#include <string>
#include "../CAbstractComponent.hpp"
#include "../Geometry/CTransform.hpp"
#include "../../Systems/Audio/Sound/CAudioClip.hpp"
#include "nlohmann/json_fwd.hpp"
namespace CosmicCore {
struct SoundInstance {
CAudioClip* clip = nullptr;
ALuint source = 0;
float gain = 1.0f;
float pitch = 1.0f;
bool loop = false;
bool spatial = true;
};
class CSpeaker : public CAbstractComponent {
std::unordered_map<std::string, SoundInstance> m_clips;
bool m_muted = false;
float m_masterGain = 1.0f;
public:
CSpeaker(CEntity& entity);
// charge et enregistre un son
void addClip(const std::string& name, const std::string& path, float gain = 1.0f, float pitch = 1.0f, bool loop = false, bool spatial = true);
void addClip(const std::string& name, CAudioClip* clip, float gain = 1.0f, float pitch = 1.0f, bool loop = false, bool spatial = true);
void play(const std::string& name);
void stop(const std::string& name);
void pause(const std::string& name);
void stopAll();
void setLoop(const std::string& name, bool loop);
void setGain(const std::string& name, float gain);
bool isPlaying(const std::string& name) const;
~CSpeaker();
// paramètres globaux du speaker
void setMuted(bool muted);
void setMasterGain(float gain);
void updatePosition(const CTransform& transform, glm::vec3 velocity = {0,0,0});
nlohmann::json to_json(){return nlohmann::json();};
};
}
#endif
+12 -4
View File
@@ -1,12 +1,12 @@
#include "CEntity.hpp" #include "CEntity.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
#include <memory> #include <functional>
namespace CosmicCore namespace CosmicCore
{ {
CEntity::CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene) : CSerializable(), m_scene(scene), m_registryReference(registry), m_handle(handle) CEntity::CEntity(std::reference_wrapper<EntityComponentManager> registry, EntityId handle, CScene* scene) : CSerializable(), m_scene(scene), m_registryReference(registry), m_handle(handle)
{ {
} }
@@ -14,6 +14,14 @@ namespace CosmicCore
} }
CEntity& CEntity::operator=(const CEntity& ent)
{
m_handle = ent.m_handle;
m_registryReference = ent.m_registryReference;
m_scene = ent.m_scene;
return *this;
}
CScene* CEntity::getScene() CScene* CEntity::getScene()
{ {
return m_scene; return m_scene;
@@ -24,9 +32,9 @@ namespace CosmicCore
m_scene = s; m_scene = s;
} }
CEntity CEntity::getParent() { /*CEntity CEntity::getParent() {
//to implement //to implement
} }*/
nlohmann::json CEntity::to_json(){return nlohmann::json();}; nlohmann::json CEntity::to_json(){return nlohmann::json();};
} }
+14 -6
View File
@@ -2,9 +2,9 @@
#define CENTITY_HPP #define CENTITY_HPP
#include <forward_list> #include <forward_list>
#include <memory> #include <functional>
#include "../Utils/CSerializable.hpp" #include "../../Utils/JsonParser/CSerializable.hpp"
#include "../Systems/EntityComponentManager.hpp" #include "EntityComponentManager.hpp"
namespace CosmicCore namespace CosmicCore
{ {
@@ -19,7 +19,7 @@ namespace CosmicCore
*/ */
CScene* m_scene; CScene* m_scene;
EntityComponentManager& m_registryReference; std::reference_wrapper<EntityComponentManager> m_registryReference;
EntityId m_handle; EntityId m_handle;
@@ -30,9 +30,11 @@ namespace CosmicCore
*/ */
CEntity() = delete; CEntity() = delete;
CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene); CEntity(std::reference_wrapper<EntityComponentManager> registry, EntityId handle, CScene* scene);
CEntity(const CEntity& cop); CEntity(const CEntity& cop);
CEntity& operator=(const CEntity& ent);
/** /**
* @brief CEntity's destructor. * @brief CEntity's destructor.
*/ */
@@ -42,7 +44,7 @@ namespace CosmicCore
* @brief Getter to the parent entity. * @brief Getter to the parent entity.
* @return a pointer to the parent entity m_parent. nullptr if there is not. * @return a pointer to the parent entity m_parent. nullptr if there is not.
*/ */
CEntity getParent(); //CEntity getParent();
template<typename compType, typename... Args> template<typename compType, typename... Args>
void addComponent(std::forward_list<Args...> args) void addComponent(std::forward_list<Args...> args)
@@ -57,6 +59,9 @@ namespace CosmicCore
} }
EntityComponentManager& getRegistry(){return m_registryReference;}; EntityComponentManager& getRegistry(){return m_registryReference;};
const EntityComponentManager& getRegistry() const {return m_registryReference;};
EntityId getHandle(){return m_handle;};
/** /**
* @brief Getter to the entity's scene. * @brief Getter to the entity's scene.
@@ -74,6 +79,9 @@ namespace CosmicCore
return m_handle; return m_handle;
} }
const EntityId operator*() const {
return m_handle;
}
//TODO GET COMPONENT VECTOR OF SPECIFIC TYPE ? si utile //TODO GET COMPONENT VECTOR OF SPECIFIC TYPE ? si utile
nlohmann::json to_json(); nlohmann::json to_json();
-34
View File
@@ -1,34 +0,0 @@
#ifndef CMODEL_HPP
#define CMODEL_HPP
#include "Mesh/CMesh.hpp"
#include <glm/glm.hpp>
class CModel {
private:
std::vector<CMesh*> m_meshes;
bool m_loaded;
public:
CModel(void) = delete;
CModel(std::vector<CMesh*> meshes);
~CModel(void);
void load(void);
//void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
std::vector<CMesh*>& getMeshes(void);
void setMeshes(std::vector<CMesh*> meshes);
bool isLoaded(void);
};
#endif
@@ -1,152 +0,0 @@
#include "CModelLoader.hpp"
#include "../API/GraphicsAPI.hpp"
#include <memory>
CModel* CModelLoader::loadModel(std::string fileName, CResourceManager& rm)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(fileName.c_str(),
aiProcess_Triangulate |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace |
aiProcess_GenNormals
);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
throw std::runtime_error("Assimp: " + std::string(importer.GetErrorString()));
// dossier de base pour les textures relatives
std::vector<CMesh*> meshes;
processNode(scene->mRootNode, scene, fileName, rm, meshes);
// crée et enregistre le model
auto model = std::make_unique<CModel>(meshes);
auto* ptr = model.get();
rm.getModelManager().addModel(fileName,std::move(model));
return ptr;
}
void CModelLoader::processNode(aiNode* node, const aiScene* scene, const std::string& directory, CResourceManager& rm, std::vector<CMesh*>& meshes)
{
// process all the node's meshes (if any)
for (uint32_t i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene, directory, rm));
}
// then do the same for each of its children
for (uint32_t i = 0; i < node->mNumChildren; i++) {
processNode(node->mChildren[i], scene, directory, rm, meshes);
}
}
CMesh* CModelLoader::processMesh(aiMesh* mesh, const aiScene* scene, const std::string& directory, CResourceManager& rm)
{
std::vector<SVertex> vertices;
std::vector<uint32_t> indices;
// vertices
for (uint32_t i = 0; i < mesh->mNumVertices; i++) {
SVertex vertex{};
vertex.m_position = {
mesh->mVertices[i].x,
mesh->mVertices[i].y,
mesh->mVertices[i].z
};
vertex.m_normal = mesh->HasNormals() ?
glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z) :
glm::vec3(0.0f);
vertex.m_texCoords = mesh->mTextureCoords[0] ?
glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y) :
glm::vec2(0.0f);
vertex.m_tangent = mesh->HasTangentsAndBitangents() ?
glm::vec3(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z) :
glm::vec3(0.0f);
vertex.m_bitangent = mesh->HasTangentsAndBitangents() ?
glm::vec3(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z) :
glm::vec3(0.0f);
vertices.push_back(vertex);
}
// indices
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
for (uint32_t j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
// material
CMaterial* material = nullptr;
if (mesh->mMaterialIndex >= 0) {
material = processMaterial(
scene->mMaterials[mesh->mMaterialIndex],
directory,
rm
);
}
// crée et enregistre le mesh
auto newMesh = std::make_unique<CMesh>();
newMesh->setVertices(vertices);
newMesh->setIndexes(indices);
if (material) newMesh->setMaterial(material);
newMesh->load();
auto* ptr = newMesh.get();
rm.getMeshManager().addMesh(directory, std::move(newMesh));
return ptr;
}
CMaterial* CModelLoader::processMaterial(aiMaterial* mat, const std::string& directory, CResourceManager& rm)
{
auto newMat = std::make_unique<CMaterial>();
// albedo
if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString path;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &path);
newMat->textureAlbedo = loadTexture(
directory + "/" + path.C_Str(), rm
);
}
// normal
if (mat->GetTextureCount(aiTextureType_NORMALS) > 0) {
aiString path;
mat->GetTexture(aiTextureType_NORMALS, 0, &path);
newMat->textureNormal = loadTexture(
directory + "/" + path.C_Str(), rm
);
}
auto shader = GraphicsAPI::getAPI()->getShaderManager().get("triangle");
newMat->shader = static_cast<CShaderImplVulkan*>(shader);
newMat->build();
auto* ptr = newMat.get();
rm.getMaterialManager().addMaterial(directory, std::move(newMat));
return ptr;
}
CTexture* CModelLoader::loadTexture(const std::string& directory, CResourceManager& rm)
{
auto text = rm.getTextureManager().get(directory);
if(rm.getTextureManager().get(directory))
{
return text.value();
}
else {
auto tex = std::make_unique<CTexture>(directory);
tex->init();
auto* ptr = tex.get();
rm.getTextureManager().addTexture(directory, std::move(tex));
return ptr;
}
}
@@ -1,32 +0,0 @@
#ifndef CMODELMANAGER_HPP
#define CMODELMANAGER_HPP
#include "CModel.hpp"
#include <list>
#include <memory>
class CModelManager
{
public:
std::list<std::unique_ptr<CModel>> loadedModel;
std::unordered_map<std::string, CModel*> modelsMap;
void addModel(std::string name, std::unique_ptr<CModel>&& model)
{
loadedModel.push_back(std::move(model));
modelsMap[name] = loadedModel.back().get();
}
std::optional<CModel*> get(std::string name)
{
auto find = modelsMap.find(name);
if(find != modelsMap.end())
{
return find->second;
}
else {
return nullptr;
}
}
};
#endif
@@ -1,28 +0,0 @@
#ifndef CRESOURCEMANAGER_HPP
#define CRESOURCEMANAGER_HPP
#include "CModelManager.hpp"
#include "Mesh/CMeshManager.hpp"
#include "Material/CMaterialManager.hpp"
#include "Texture/CTextureManager.hpp"
class CResourceManager{
private:
CModelManager modelManager;
CMeshManager meshManager;
CMaterialManager materialManager;
CTextureManager textureManager;
public:
CModelManager& getModelManager() { return modelManager; }
CMeshManager& getMeshManager() { return meshManager; }
CMaterialManager& getMaterialManager() { return materialManager; }
CTextureManager& getTextureManager() {return textureManager;}
void cleanup(){
materialManager.loadedMaterials.clear();
meshManager.loadedMeshes.clear();
modelManager.loadedModel.clear();
textureManager.loadedTextures.clear();
};
};
#endif
@@ -1,31 +0,0 @@
#ifndef CMATERIALMANAGER_HPP
#define CMATERIALMANAGER_HPP
#include "CMaterial.hpp"
#include <list>
#include <memory>
#include <unordered_map>
class CMaterialManager
{
public:
std::list<std::unique_ptr<CMaterial>> loadedMaterials;
std::unordered_map<std::string, CMaterial*> materialsMap;
void addMaterial(std::string name, std::unique_ptr<CMaterial>&& mat)
{
loadedMaterials.push_back(std::move(mat));
materialsMap[name] = loadedMaterials.back().get();
}
std::optional<CMaterial*> get(std::string name)
{
auto find = materialsMap.find(name);
if(find != materialsMap.end())
{
return find->second;
}
else {
return nullptr;
}
}
};
#endif
@@ -1,31 +0,0 @@
#ifndef CMESHMANAGER_HPP
#define CMESHMANAGER_HPP
#include "CMesh.hpp"
#include <list>
#include <memory>
class CMeshManager
{
public:
std::list<std::unique_ptr<CMesh>> loadedMeshes;
std::unordered_map<std::string, CMesh*> meshesMap;
void addMesh(std::string name, std::unique_ptr<CMesh>&& mesh)
{
loadedMeshes.push_back(std::move(mesh));
meshesMap[name] = loadedMeshes.back().get();
}
std::optional<CMesh*> get(std::string name)
{
auto find = meshesMap.find(name);
if(find != meshesMap.end())
{
return find->second;
}
else {
return nullptr;
}
}
};
#endif
@@ -1,32 +0,0 @@
#ifndef CTEXTUREMANAGER_HPP
#define CTEXTUREMANAGER_HPP
#include "CTexture.hpp"
#include <list>
#include <memory>
#include <optional>
#include <unordered_map>
class CTextureManager
{
public:
std::list<std::unique_ptr<CTexture>> loadedTextures;
std::unordered_map<std::string, CTexture*> texturesMap;
void addTexture(std::string name, std::unique_ptr<CTexture>&& text)
{
loadedTextures.push_back(std::move(text));
texturesMap[name] = loadedTextures.back().get();
}
std::optional<CTexture*> get(std::string name)
{
auto find = texturesMap.find(name);
if(find != texturesMap.end())
{
return find->second;
}
else {
return nullptr;
}
}
};
#endif
@@ -1,45 +0,0 @@
#ifndef CSHADERSMANAGER_HPP
#define CSHADERSMANAGER_HPP
#include <list>
#include <string>
#include <map>
#include <nlohmann/json.hpp>
#include <unordered_map>
#include "CShader.hpp"
#define SHADERS_FOLDER "assets/shaders/slang/spv"
class CShadersManager {
private:
std::list<std::unique_ptr<CShader>> shaders;
std::unordered_map<std::string, CShader*> m_shadersMap;
public:
CShadersManager(void);
CShadersManager(const CShadersManager& param) = delete;
~CShadersManager(void);
CShadersManager& operator=(const CShadersManager& param) = delete;
CShader* get(std::string name) const;
std::list<std::unique_ptr<CShader>>::const_iterator beginShaders(){return shaders.cbegin();};
std::list<std::unique_ptr<CShader>>::const_iterator endShaders(){return shaders.cend();};
void compile(void);
void create(void);
void cleanup(){
shaders.clear();
}
};
#endif
+36 -33
View File
@@ -5,20 +5,26 @@
#include <SDL3/SDL_render.h> #include <SDL3/SDL_render.h>
#include <SDL3/SDL_timer.h> #include <SDL3/SDL_timer.h>
#include <SDL3/SDL_video.h> #include <SDL3/SDL_video.h>
#include <dlfcn.h>
#include <filesystem>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include "../Graphics/CContext.hpp" #include "../Systems/Graphics/CContext.hpp"
#include "../Graphics/API/GraphicsAPI.hpp" #include "../Systems/Graphics/API/GraphicsAPI.hpp"
#include "../Physics/CPhysicsAPI.hpp" #include "../Systems/Physics/API/CPhysicsAPI.hpp"
#include "../Scene/CScene.hpp" #include "../Scene/CScene.hpp"
#include "../Entity/CEntity.hpp" #include "../Entity/CEntity.hpp"
#include "../Component/Camera/CCamera.hpp" #include "../Component/Camera/CCamera.hpp"
#include "../../Utils/Factory/CEntityFactory.hpp" #include "../../Utils/Factory/CEntityFactory.hpp"
#include "../../Utils/Factory/ComponentFactory.hpp" #include "../../Utils/Factory/ComponentFactory.hpp"
#include "../../Utils/JsonParser/Identifier.hpp"
#include "../Component/Graphics/CRenderer.hpp" #include "../Component/Graphics/CRenderer.hpp"
#include "../Modules/Scripts/CScriptRegister.hpp"
#include "Core/Systems/Scripts/API/CScriptAPI.hpp"
#include "glm/ext/vector_float3.hpp" #include "glm/ext/vector_float3.hpp"
//CShader* CKernel::m_mainShader; //CShader* CKernel::m_mainShader;
@@ -38,8 +44,8 @@ namespace CosmicCore {
m_gameName(gameName), m_window(gameName, LOGO, 1270, 720, true, false) m_gameName(gameName), m_window(gameName, LOGO, 1270, 720, true, false)
{ {
m_kernel = this; m_kernel = this;
CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC); CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC);
CScriptAPI::init();
} }
CKernel::~CKernel() CKernel::~CKernel()
@@ -52,38 +58,20 @@ namespace CosmicCore {
} }
void CKernel::start(bool isPreview) { void CKernel::start(bool isPreview) {
//CScriptRegister::registerAllScripts();
JPH::RegisterDefaultAllocator();
//JPH::Trace = JoltTraceImpl;
JPH::Factory::sInstance = new JPH::Factory();
JPH::RegisterTypes();
std::filesystem::path pathToSchema("schema_json.json");
CosmicUtils::JsonValidator::init(pathToSchema);
if(!isPreview) if(!isPreview)
{ {
m_window.initialization(); m_window.initialization();
auto scene = CScene::load("scenes/scene1.json");
m_sceneMap["TestScene"] = std::make_unique<CScene>("Scene1"); m_activeScene = scene.get();
m_activeScene = m_sceneMap["TestScene"].get(); m_sceneMap[scene->getName()] = std::move(scene);
CEntityFactory::EntityConfig configCamera;
CEntityFactory::EntityConfig configSol;
CEntityFactory::EntityConfig configCube;
configCamera = {"camera", "une caméra", {0.0f,0.0f,6.0f}, {1.0f,1.0f,1.0f}, glm::vec3(), "", "triangle", EColliderType::Box, EBodyType::Static, false};
configSol = {"sol", "le sol, ne bouge pas", {0.0f,-2.0f,0.0f}, {100.0f,1.0f,100.0f}, glm::vec3(), "assets/models/cube.glb", "triangle", EColliderType::Box, EBodyType::Static, true};
configCube = {"cube", "le cube, shrek", {0.0f,60.0f,0.0f}, {1.0f,1.0f,1.0f}, glm::vec3(), "assets/models/cube.glb", "triangle", EColliderType::Box, EBodyType::Dynamic, true};
auto cam = CEntityFactory::create(m_activeScene, configCamera);
ComponentFactory::addCamera(cam);
CEntityFactory::create(m_activeScene, configSol);
auto e = CEntityFactory::create(m_activeScene, configCube);
auto& renderer = m_activeScene->getECManager().registry.get<CRenderer>(*e);
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
api->getResourceManager().getTextureManager().loadedTextures.push_back(std::make_unique<CTexture>("assets/shrekt.png"));
auto texture = api->getResourceManager().getTextureManager().loadedTextures.back().get();
texture->init();
for(auto& mesh : renderer.getModel()->getMeshes())
{
mesh->getMaterial()->textureAlbedo = texture;
mesh->getMaterial()->build();
}
} }
} }
@@ -120,7 +108,11 @@ namespace CosmicCore {
// Handle key press // Handle key press
SDL_Keycode keyPressed = event.key.key; SDL_Keycode keyPressed = event.key.key;
auto entities = m_activeScene->getECManager().registry.view<CCamera, CTransform>(); auto entities = m_activeScene->getECManager().registry.view<CCamera, CTransform>();
auto shrek = m_activeScene->getECManager().registry.view<CTransform, CSpeaker>();
auto& ent = m_activeScene->getECManager().registry.get<CTransform>(entities.front()); auto& ent = m_activeScene->getECManager().registry.get<CTransform>(entities.front());
auto& speaker = m_activeScene->getECManager().registry.get<CSpeaker>(shrek.front());
switch (keyPressed) { switch (keyPressed) {
case SDLK_Z: case SDLK_Z:
ent.forward({0.0f, 0.0f, -0.08f}); ent.forward({0.0f, 0.0f, -0.08f});
@@ -140,6 +132,9 @@ namespace CosmicCore {
case SDLK_A: case SDLK_A:
ent.forward({0.0f, 0.08f, 0.0f}); ent.forward({0.0f, 0.08f, 0.0f});
break; break;
case SDLK_P:
speaker.play("assets/GiveAlittleBit.flac");
break;
default: default:
break; break;
} }
@@ -162,6 +157,10 @@ namespace CosmicCore {
if(m_activeScene) if(m_activeScene)
{ {
m_activeScene->getTangibleWorld().updateWorld(1.0f/60.0f); m_activeScene->getTangibleWorld().updateWorld(1.0f/60.0f);
m_activeScene->getAudioWorld().updateWorld(1.0f/60.0f);
m_activeScene->getScriptWorld().updateWorld(1.0f/60.0f);
//TODO scne update -> physics + audio + scripts ?
GraphicsAPI::getAPI()->drawFrame(); GraphicsAPI::getAPI()->drawFrame();
} }
@@ -182,6 +181,10 @@ namespace CosmicCore {
void CKernel::quit() { void CKernel::quit() {
m_finished = true; m_finished = true;
JPH::UnregisterTypes();
// Destroy the factory
delete JPH::Factory::sInstance;
JPH::Factory::sInstance = nullptr;
} }
+1 -1
View File
@@ -7,7 +7,7 @@
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "../Graphics/Window/CGameWindow.hpp" #include "../Systems/Graphics/Window/CGameWindow.hpp"
#include "../Scene/CScene.hpp" #include "../Scene/CScene.hpp"
+171 -9
View File
@@ -4,15 +4,28 @@
#include "../Component/Meta/CMetaData.hpp" #include "../Component/Meta/CMetaData.hpp"
#include "../Component/Geometry/CTransform.hpp" #include "../Component/Geometry/CTransform.hpp"
#include "../Component/Camera/CCamera.hpp" #include "../Component/Camera/CCamera.hpp"
#include "../Graphics/API/GraphicsAPI.hpp" #include "../Systems/Graphics/API/GraphicsAPI.hpp"
#include "../../Utils/JsonParser/Identifier.hpp"
#include "../../Utils/Factory/CEntityFactory.hpp"
#include "../../Utils/Factory/ComponentFactory.hpp"
#include "glm/ext/vector_float3.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "nlohmann/json_fwd.hpp"
#include <fstream>
#include <memory> #include <memory>
#include <optional>
#include <unordered_map>
#include <vector>
namespace CosmicCore { namespace CosmicCore {
CScene::CScene(std::string name) : CSerializable(), CScene::CScene(std::string name) : CSerializable(),
m_name(std::move(name)), m_tangibleWorld(this) m_name(std::move(name)), m_tangibleWorld(this), m_audioWorld(this), m_scriptWorld(this)
{ {
m_tangibleWorld.initWorld(); m_tangibleWorld.initWorld();
m_audioWorld.initWorld();
m_scriptWorld.initWorld();
} }
@@ -23,6 +36,8 @@ namespace CosmicCore {
CScene::~CScene() CScene::~CScene()
{ {
m_tangibleWorld.destroy(); m_tangibleWorld.destroy();
m_audioWorld.destroy();
m_scriptWorld.destroy();
} }
CEntity CScene::createEntity(){ CEntity CScene::createEntity(){
@@ -73,22 +88,22 @@ namespace CosmicCore {
{} {}
); );
for (auto& mesh : model->getMeshes()) { for (auto& mm : model->getMeshMaterials()) {
// ne rebind le pipeline que si le material change // ne rebind le pipeline que si le material change
//if (mesh.getMaterial() != boundMaterial) { //if (mesh.getMaterial() != boundMaterial) {
//boundMaterial = mesh.getMaterial(); //boundMaterial = mesh.getMaterial();
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, cmd.bindPipeline(vk::PipelineBindPoint::eGraphics,
*mesh->getMaterial()->getPipeline()); *mm.material->getPipeline());
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
*mesh->getMaterial()->getPipelineLayout(), *mm.material->getPipelineLayout(),
2, 2,
*mesh->getMaterial()->getDescriptorSet(frameIndex), *mm.material->getDescriptorSet(frameIndex),
{}); {});
//} //}
cmd.bindVertexBuffers(0, vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getVertexOffset()); cmd.bindVertexBuffers(0, vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getVertexOffset());
cmd.bindIndexBuffer(vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getIndexOffset(), vk::IndexType::eUint32); cmd.bindIndexBuffer(vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getIndexOffset(), vk::IndexType::eUint32);
cmd.drawIndexed(mesh->getIndexCount(), 1, 0, 0, 0); cmd.drawIndexed(mm.mesh->getIndexCount(), 1, 0, 0, 0);
} }
} }
} }
@@ -97,4 +112,151 @@ namespace CosmicCore {
{ {
return nlohmann::json(); return nlohmann::json();
} }
std::unique_ptr<CScene> CScene::load(const std::string &path)
{
std::ifstream file(path);
nlohmann::json sceneJson = nlohmann::json::parse(file);
if(CosmicUtils::JsonValidator::validate(sceneJson))
{
std::string sceneName = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Name)];
std::unordered_map<unsigned int, CEntity> idToHandle;
std::unordered_map<unsigned int, unsigned int> idToParent;
std::unordered_map<unsigned int, std::vector<unsigned int>> idToChildren;
//TODO add descritpion to members
std::string sceneDescription = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Description)];
auto scene = std::make_unique<CScene>(sceneName);
nlohmann::json& entities = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Entities)];
for(auto& entity : entities.items())
{
nlohmann::json& entityObj = entity.value();
auto ref = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Ref)].get<unsigned int>();
std::optional<unsigned int> parent = !entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Parent)].is_null() ? std::optional<unsigned int>(entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Parent)].get<unsigned int>()) : std::nullopt;
auto children = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Children)].get<std::vector<unsigned int>>();
nlohmann::json& components = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Components)];
nlohmann::json& transform = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Transform)];
nlohmann::json& camera = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Camera)];
nlohmann::json& collider = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Collider)];
nlohmann::json& rigidbody = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Rigidbody)];
nlohmann::json& renderer = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Renderer)];
nlohmann::json& speaker = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Speaker)];
nlohmann::json& script = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Script)];
auto trConfig(!transform.is_null() ? std::optional<CosmicUtils::ComponentFactory::TransformConfig>({
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Position)].get<std::vector<float>>().data()),
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Rotation)].get<std::vector<float>>().data()),
glm::make_vec3(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Scale)].get<std::vector<float>>().data())
}) : std::nullopt);
auto camConfig(!camera.is_null() ? std::optional<CosmicUtils::ComponentFactory::CameraConfig>({
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Fov)].get<float>(),
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Near)].get<float>(),
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Far)].get<float>()
}) : std::nullopt);
auto colliderConfig(!collider.is_null() ? std::optional<CosmicUtils::ComponentFactory::ColliderConfig>({
static_cast<EColliderType>(collider[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Collider_Type)].get<int>()),
glm::vec3(),
0,
0,
}) : std::nullopt);
auto rigidbodyConfig(!rigidbody.is_null() ? std::optional<CosmicUtils::ComponentFactory::RigidBodyConfig>({
static_cast<EBodyType>(rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Type)].get<int>()),
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Mass)].get<float>(),
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Friction)].get<float>(),
rigidbody[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::RigidBody_Restitution)].get<float>()
}) : std::nullopt);
auto rendererConfig(!renderer.is_null() ? std::optional<CosmicUtils::ComponentFactory::RendererConfig>({
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Model)].get<std::string>(),
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Shader)].get<std::string>(),
!renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Albedo)].is_null() ? std::optional<std::string>(renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Albedo)].get<std::string>()) : std::nullopt,
}) : std::nullopt);
auto scriptConfig(!script.is_null() ? std::optional<CosmicUtils::ComponentFactory::ScriptConfig>({
script.get<std::vector<std::string>>()
}): std::nullopt);
std::optional<CosmicUtils::ComponentFactory::SpeakerConfig> speakerConfig = std::nullopt;
if(!speaker.is_null())
{
if(!speaker[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Clips)].empty())
{
speakerConfig = std::optional<CosmicUtils::ComponentFactory::SpeakerConfig>(CosmicUtils::ComponentFactory::SpeakerConfig());
for(auto clipConf : speaker[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Clips)])
{
CosmicUtils::ComponentFactory::SpeakerConfig::SoundClipConfig conf
{
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Path)].get<std::string>(),
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Gain)].get<float>(),
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Pitch)].get<float>(),
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Loop)].get<bool>(),
clipConf[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Speaker_Spatial)].get<bool>()
};
speakerConfig->clips.push_back(conf);
}
}
}
CosmicUtils::CEntityFactory::EntityConfig config = {
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Name)],
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity_Description)],
trConfig,
camConfig,
rendererConfig,
colliderConfig,
rigidbodyConfig,
speakerConfig,
scriptConfig
};
auto entityHandle = CosmicUtils::CEntityFactory::create(scene.get(), config);
idToHandle.emplace(std::make_pair(ref, entityHandle));
if(parent.has_value())
idToParent[ref] = parent.value();
for(auto i : children)
{
idToChildren[ref].push_back(i);
}
}
//Connect entities to relationships
for(auto& [entityNb, handle]: idToHandle)
{
CosmicUtils::ComponentFactory::RelationshipConfig cnf;
if(idToParent.find(entityNb) != idToParent.end())
{
cnf.parent = std::optional<EntityId>(idToHandle.at(idToParent.at(entityNb)).getHandle());
}
else
{
cnf.parent = std::nullopt;
}
for(auto& child : idToChildren[entityNb])
{
cnf.children.push_back(idToHandle.at(child).getHandle());
}
CosmicUtils::ComponentFactory::addRelationship(handle, cnf);
}
return scene;
}
return nullptr;
}
void CScene::save(CScene *scene, const std::string &path)
{
}
void CScene::save(const std::string& path)
{
save(this, path);
}
} }
+24 -4
View File
@@ -1,11 +1,14 @@
#ifndef CSCENE_HPP #ifndef CSCENE_HPP
#define CSCENE_HPP #define CSCENE_HPP
#include "../Systems/EntityComponentManager.hpp" #include "../Entity/EntityComponentManager.hpp"
#include "../Utils/CSerializable.hpp" #include "../../Utils/JsonParser/CSerializable.hpp"
#include <string> #include <string>
#include <vulkan/vulkan_raii.hpp> #include <vulkan/vulkan_raii.hpp>
#include "../Physics/CTangibleWorld.hpp" #include "../Systems/Physics/CTangibleWorld.hpp"
#include "../Systems/Audio/CAudioWorld.hpp"
#include "Core/Systems/Scripts/CScriptWorld.hpp"
namespace CosmicCore { namespace CosmicCore {
class CEntity; class CEntity;
class CScene : public CSerializable { class CScene : public CSerializable {
@@ -14,10 +17,16 @@ namespace CosmicCore {
std::string m_name; std::string m_name;
EntityComponentManager m_ecManager; EntityComponentManager m_ecManager;
CTangibleWorld m_tangibleWorld; CTangibleWorld m_tangibleWorld;
CAudioWorld m_audioWorld;
CScriptWorld m_scriptWorld;
public: public:
CScene() = delete; CScene() = delete;
CScene(std::string name); CScene(std::string name);
CScene(CScene&&) = delete;
CScene& operator=(CScene&&) = delete;
CScene(const CScene&) = delete;
CScene& operator=(const CScene&) = delete;
virtual ~CScene(); virtual ~CScene();
unsigned int getNumEntity() const; unsigned int getNumEntity() const;
@@ -31,6 +40,11 @@ namespace CosmicCore {
void removeEntity(unsigned int index, bool destroy = true); void removeEntity(unsigned int index, bool destroy = true);
CTangibleWorld& getTangibleWorld() {return m_tangibleWorld;}; CTangibleWorld& getTangibleWorld() {return m_tangibleWorld;};
CAudioWorld& getAudioWorld() {return m_audioWorld;};
CScriptWorld& getScriptWorld() {return m_scriptWorld;};
//CEntity* getActiveCamera(); //CEntity* getActiveCamera();
//void setActiveCamera(CEntity* newCamera); //void setActiveCamera(CEntity* newCamera);
@@ -85,6 +99,12 @@ namespace CosmicCore {
} }
return s; return s;
};*/ };*/
static std::unique_ptr<CScene> load(const std::string& path);
static void save(CScene* scene, const std::string& path);
void save(const std::string& path);
}; };
} }
#endif #endif
@@ -0,0 +1,8 @@
#include "CAudioAPI.hpp"
namespace CosmicCore {
CAudioAPI::~CAudioAPI()
{
}
}
@@ -0,0 +1,25 @@
#ifndef CAUDIOAPI_HPP
#define CAUDIOAPI_HPP
namespace CosmicCore {
class CScene;
/**
* @brief Class representing any audio world - abstract.
*/
class CAudioAPI {
private:
CScene* m_scene;
public:
CAudioAPI(CScene* scene): m_scene(scene){};
virtual ~CAudioAPI();
virtual void updateWorld(float delta) = 0;
virtual void initWorld() = 0;
virtual void destroy() = 0;
CScene* getScene(){return m_scene;};
};
}
#endif
@@ -0,0 +1,61 @@
#include "CAudioWorld.hpp"
#include "../../Scene/CScene.hpp"
#include "../../Component/Camera/CCamera.hpp"
#include "../../Component/Speaker/CSpeaker.hpp"
#include <al.h>
namespace CosmicCore {
CAudioWorld::~CAudioWorld()
{
}
void CAudioWorld::initWorld() {
m_device = alcOpenDevice(nullptr);
m_context = alcCreateContext(m_device, nullptr);
alcMakeContextCurrent(m_context);
// active le distance model
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
alListenerf(AL_GAIN, 1.0f);
}
void CAudioWorld::updateWorld(float delta) {
auto& registry = getScene()->getECManager().registry;
// met à jour la position de l'écouteur depuis la caméra
auto camView = registry.view<CCamera, CTransform>();
if (camView.begin() != camView.end()) {
auto& camTransform = registry.get<CTransform>(camView.front());
glm::vec3 pos = camTransform.getCenter();
glm::vec3 forward = camTransform.getOrientation() * glm::vec3(0,0,-1);
glm::vec3 up = camTransform.getOrientation() * glm::vec3(0,1,0);
alListener3f(AL_POSITION, pos.x, pos.y, pos.z);
float orientation[6] = {
forward.x, forward.y, forward.z,
up.x, up.y, up.z
};
alListenerfv(AL_ORIENTATION, orientation);
}
// met à jour la position de chaque speaker
auto view = registry.view<CSpeaker, CTransform>();
for (auto entity : view) {
auto& speaker = registry.get<CSpeaker>(entity);
auto& transform = registry.get<CTransform>(entity);
speaker.updatePosition(
transform,
{0.0f,0.0f,0.0f} // si tu as une vélocité dans CTransform
);
}
}
void CAudioWorld::destroy() {
alcMakeContextCurrent(nullptr);
alcDestroyContext(m_context);
alcCloseDevice(m_device);
}
}
@@ -0,0 +1,26 @@
#ifndef CAUDIOWORLD_HPP
#define CAUDIOWORLD_HPP
#include <alc.h>
#include "API/CAudioAPI.hpp"
namespace CosmicCore {
class CAudioWorld : public CAudioAPI{
ALCdevice* m_device = nullptr;
ALCcontext* m_context = nullptr;
public:
CAudioWorld(CScene* scene) : CAudioAPI(scene) {}
~CAudioWorld();
void initWorld();
void updateWorld(float delta);
void destroy();
};
}
#endif
@@ -0,0 +1,20 @@
#ifndef CAUDIOCLIP_HPP
#define CAUDIOCLIP_HPP
#include <AL/al.h>
#include <string>
class CAudioClip {
private:
public:
ALuint buffer = 0;
std::string path;
float duration = 0.0f;
~CAudioClip() {
if (buffer) alDeleteBuffers(1, &buffer);
}
};
#endif
@@ -1,5 +1,5 @@
#include "GraphicsAPI.hpp" #include "GraphicsAPI.hpp"
#include "VulkanImpl.hpp" #include "VulkanImplementation/VulkanImpl.hpp"
#include <memory> #include <memory>
std::unique_ptr<GraphicsAPI> GraphicsAPI::impl = nullptr; std::unique_ptr<GraphicsAPI> GraphicsAPI::impl = nullptr;
@@ -3,8 +3,6 @@
#include <SDL3/SDL_video.h> #include <SDL3/SDL_video.h>
#include <memory> #include <memory>
#include "../Shader/CShadersManager.hpp"
#include "../Data/CResourceManager.hpp"
enum class GraphicsBackend{ enum class GraphicsBackend{
Vulkan, Vulkan,
@@ -14,9 +12,6 @@ enum class GraphicsBackend{
class GraphicsAPI{ class GraphicsAPI{
static std::unique_ptr<GraphicsAPI> impl; static std::unique_ptr<GraphicsAPI> impl;
protected:
CShadersManager shadermanager;
CResourceManager resourceManager;
public: public:
static void initAPI(); static void initAPI();
static std::unique_ptr<GraphicsAPI>& getAPI(){return impl;}; static std::unique_ptr<GraphicsAPI>& getAPI(){return impl;};
@@ -25,8 +20,6 @@ class GraphicsAPI{
virtual ~GraphicsAPI(){}; virtual ~GraphicsAPI(){};
virtual void* getDevice() = 0; virtual void* getDevice() = 0;
virtual void drawFrame() = 0; virtual void drawFrame() = 0;
CShadersManager& getShaderManager(){return shadermanager;};
CResourceManager& getResourceManager(){return resourceManager;};
}; };

Some files were not shown because too many files have changed in this diff Show More