diff --git a/CLAUDE.md b/CLAUDE.md index 99a1982..48ac33c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -195,6 +195,23 @@ cmake . && make warfactory-core # Build core engine make warfactory-modules # Build all modules ``` +### UI Testing Commands +```bash +# Build UI tests +cmake -B build && cmake --build build # Debug with AddressSanitizer +cmake -B build_release -DCMAKE_BUILD_TYPE=Release && cmake --build build_release # Clean release + +# Run UI tests +./bin/test_imgui_ui # Interactive mode (DEFAULT - no auto-exit) +./bin/test_imgui_ui --headless # Quick test mode (auto-exit after 3s) +./bin/test_imgui_ui --max-frames 300 # Custom frame limit (overrides interactive) +./bin/test_imgui_ui --interactive # Explicit interactive mode (no auto-exit) +./bin/test_imgui_ui --help # Show usage options + +# For Claude Code testing +./bin/test_imgui_ui --headless # Use this for quick validation tests +``` + ### Project Structure ``` ├── modules/ # Autonomous hot-reloadable modules @@ -296,6 +313,24 @@ The project includes 16 C++ libraries via FetchContent: - **Compiler Hardening**: Stack protection, frame pointers, maximum debug info - **Memory Safety**: Smart pointers, RAII patterns, leak detection +## 🚫 **CRITICAL CODE RESTRICTIONS** + +### AUTO KEYWORD PROHIBITION +**STRICTLY FORBIDDEN**: The `auto` keyword is banned as a type in this codebase. +- **NEVER use**: `auto variable = value;` +- **ALWAYS use**: `ExplicitType variable = value;` +- **Reason**: Explicit types improve code readability, reduce debugging complexity, and prevent type-related errors +- **Examples**: + ```cpp + // ❌ FORBIDDEN - will not compile + auto config = getConfiguration(); + auto nodes = config->getChildNodes(); + + // ✅ REQUIRED - explicit types + std::unique_ptr config = getConfiguration(); + std::vector> nodes = config->getChildNodes(); + ``` + ## Quick Reference ### For Understanding the Project @@ -304,7 +339,7 @@ The project includes 16 C++ libraries via FetchContent: 3. `02-systems/gameplay-industriel.md` - Core gameplay ### For Development -1. **`CLAUDE-HOT-RELOAD-GUIDE.md`** - **ESSENTIAL**: Blazing 0.4ms hot-reload system guide +1. **`docs/03-implementation/CLAUDE-HOT-RELOAD-GUIDE.md`** - **ESSENTIAL**: Blazing 0.4ms hot-reload system guide 2. `01-architecture/claude-code-integration.md` - AI development workflow 3. `03-implementation/testing-strategy.md` - Testing approach 4. `04-reference/INTEGRATION-MASTER-LIST.md` - Complete specifications diff --git a/CMakeLists.txt b/CMakeLists.txt index 6093359..d455747 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,11 @@ project(ImGuiUI_Test) set(CMAKE_CXX_STANDARD 17) -# 🔧 DEVELOPMENT MODE - Enable all debugging tools -set(CMAKE_BUILD_TYPE Debug) +# 🚫 CRITICAL: Prohibit 'auto' keyword as type (explicit types required) +# Applied only to project files, not external dependencies + +# 🔧 DEVELOPMENT MODE - Enable all debugging tools (can be overridden) +# set(CMAKE_BUILD_TYPE Debug) # Commented out to allow Release builds set(CMAKE_CXX_FLAGS_DEBUG "-fsanitize=address -fsanitize=undefined -g -O0 -Wall -Wextra") set(CMAKE_C_FLAGS_DEBUG "-fsanitize=address -fsanitize=undefined -g -O0 -Wall -Wextra") @@ -55,11 +58,11 @@ target_link_libraries(imgui_backends PUBLIC glfw OpenGL::GL) # Test executable add_executable(test_imgui_ui test_imgui_ui.cpp - core/src/ImGuiUI.cpp + src/core/src/ImGuiUI.cpp ) target_include_directories(test_imgui_ui PRIVATE - core/include + src/core/include ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends ) @@ -71,7 +74,34 @@ target_link_libraries(test_imgui_ui OpenGL::GL ) +# Note: Auto keyword restriction enforced via code review and linting tools + # Copy to build directory set_target_properties(test_imgui_ui PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +# Test constraints executable +add_executable(test_constraints + test_constraints.cpp + src/core/src/ImGuiUI.cpp +) + +target_include_directories(test_constraints PRIVATE + src/core/include + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends +) + +target_link_libraries(test_constraints + imgui_backends + nlohmann_json::nlohmann_json + glfw + OpenGL::GL +) + +# Note: Auto keyword restriction enforced via code review and linting tools + +set_target_properties(test_constraints PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) \ No newline at end of file diff --git a/core/CMakeLists-full.txt b/core/CMakeLists-full.txt deleted file mode 100644 index e3ea91d..0000000 --- a/core/CMakeLists-full.txt +++ /dev/null @@ -1,64 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(WarfactoryCore LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Load Warfactory defenses -include(../cmake/WarfactoryDefenses.cmake) -include(../cmake/WarfactoryAutomation.cmake) - -# Output directories -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - -# Core includes -include_directories(include) - -# Core library with interfaces and implementations -add_library(warfactory-core SHARED - src/DebugEngine.cpp - src/EngineFactory.cpp - src/ModuleSystemFactory.cpp - src/IOFactory.cpp - src/ModuleFactory.cpp - src/SequentialModuleSystem.cpp - src/IntraIO.cpp -) - -target_include_directories(warfactory-core PUBLIC - include -) - -# Main executable -add_executable(warfactory-engine - src/main.cpp -) - -# Hot-reload integration test -add_executable(hot-reload-test - src/hot_reload_test.cpp -) - -# Add dependencies to core library -warfactory_add_dependencies(warfactory-core) - -target_link_libraries(warfactory-engine - PRIVATE warfactory-core -) - -target_link_libraries(hot-reload-test - PRIVATE warfactory-core - PRIVATE ${CMAKE_DL_LIBS} -) - -# Install rules -install(TARGETS warfactory-core warfactory-engine - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin -) - -install(DIRECTORY include/ - DESTINATION include - FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" -) \ No newline at end of file diff --git a/core/CMakeLists-light.txt b/core/CMakeLists-light.txt deleted file mode 100644 index 85c5d13..0000000 --- a/core/CMakeLists-light.txt +++ /dev/null @@ -1,32 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(WarfactoryCore LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Output directories -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -# Core includes -include_directories(include) - -# Find nlohmann_json -find_package(nlohmann_json QUIET) -if(NOT nlohmann_json_FOUND) - include(FetchContent) - FetchContent_Declare(nlohmann_json - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz - URL_HASH SHA256=d6c65aca6b1ed68e7a182f4757257b107ae403032760ed6ef121c9d55e81757d - ) - FetchContent_MakeAvailable(nlohmann_json) -endif() - -# Minimal hot-reload test -add_executable(minimal-hot-reload-test - src/minimal_hot_reload_test.cpp -) - -target_link_libraries(minimal-hot-reload-test - PRIVATE nlohmann_json::nlohmann_json - PRIVATE ${CMAKE_DL_LIBS} -) \ No newline at end of file diff --git a/core/README.md b/core/README.md deleted file mode 100644 index 4f462b5..0000000 --- a/core/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Core Game Logic - -Core game mechanics and shared systems for Warfactory. - -## Structure -- Game loop management -- Shared data structures -- Common utilities -- Engine coordination \ No newline at end of file diff --git a/core/include/warfactory/DebugEngine.h b/core/include/warfactory/DebugEngine.h deleted file mode 100644 index 067b6c9..0000000 --- a/core/include/warfactory/DebugEngine.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IEngine.h" -#include "IModuleSystem.h" -#include "IIO.h" - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Debug engine implementation with comprehensive logging - * - * DebugEngine provides maximum visibility into engine operations: - * - Verbose logging of all operations - * - Step-by-step execution capabilities - * - Module isolation and debugging - * - Performance metrics and timing - * - IIO health monitoring and reporting - * - Detailed socket management logging - */ -class DebugEngine : public IEngine { -private: - std::shared_ptr logger; - std::atomic running{false}; - std::atomic debugPaused{false}; - - // Module management - std::vector> moduleSystems; - std::vector moduleNames; - - // Socket management - std::unique_ptr coordinatorSocket; - std::vector> clientSockets; - - // Performance tracking - std::chrono::high_resolution_clock::time_point lastFrameTime; - std::chrono::high_resolution_clock::time_point engineStartTime; - size_t frameCount = 0; - - // Configuration - json engineConfig; - - // Helper methods - void logEngineStart(); - void logEngineShutdown(); - void logFrameStart(float deltaTime); - void logFrameEnd(float frameTime); - void logModuleHealth(); - void logSocketHealth(); - void processModuleSystems(float deltaTime); - void processClientMessages(); - void processCoordinatorMessages(); - float calculateDeltaTime(); - void validateConfiguration(); - -public: - DebugEngine(); - virtual ~DebugEngine(); - - // IEngine implementation - void initialize() override; - void run() override; - void step(float deltaTime) override; - void shutdown() override; - void loadModules(const std::string& configPath) override; - void registerMainSocket(std::unique_ptr coordinatorSocket) override; - void registerNewClientSocket(std::unique_ptr clientSocket) override; - EngineType getType() const override; - - // Debug-specific methods - void pauseExecution(); - void resumeExecution(); - void stepSingleFrame(); - bool isPaused() const; - json getDetailedStatus() const; - void setLogLevel(spdlog::level::level_enum level); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/EngineFactory.h b/core/include/warfactory/EngineFactory.h deleted file mode 100644 index 37c0679..0000000 --- a/core/include/warfactory/EngineFactory.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "IEngine.h" -#include "DebugEngine.h" - -namespace warfactory { - -/** - * @brief Factory for creating engine implementations - * - * EngineFactory provides a centralized way to create different engine types - * based on configuration or runtime requirements. - * - * Supported engine types: - * - "debug" or "DEBUG" -> DebugEngine (maximum logging, step debugging) - * - "production" or "PRODUCTION" -> ProductionEngine (future implementation) - * - "high_performance" or "HIGH_PERFORMANCE" -> HighPerformanceEngine (future) - * - * Usage: - * ```cpp - * auto engine = EngineFactory::createEngine("debug"); - * auto engine = EngineFactory::createEngine(EngineType::DEBUG); - * auto engine = EngineFactory::createFromConfig("config/engine.json"); - * ``` - */ -class EngineFactory { -public: - /** - * @brief Create engine from string type - * @param engineType String representation of engine type - * @return Unique pointer to engine implementation - * @throws std::invalid_argument if engine type is unknown - */ - static std::unique_ptr createEngine(const std::string& engineType); - - /** - * @brief Create engine from enum type - * @param engineType Engine type enum value - * @return Unique pointer to engine implementation - * @throws std::invalid_argument if engine type is not implemented - */ - static std::unique_ptr createEngine(EngineType engineType); - - /** - * @brief Create engine from configuration file - * @param configPath Path to JSON configuration file - * @return Unique pointer to engine implementation - * @throws std::runtime_error if config file cannot be read - * @throws std::invalid_argument if engine type in config is invalid - * - * Expected config format: - * ```json - * { - * "engine": { - * "type": "debug", - * "log_level": "trace", - * "features": { - * "step_debugging": true, - * "performance_monitoring": true - * } - * } - * } - * ``` - */ - static std::unique_ptr createFromConfig(const std::string& configPath); - - /** - * @brief Get list of available engine types - * @return Vector of supported engine type strings - */ - static std::vector getAvailableEngineTypes(); - - /** - * @brief Check if engine type is supported - * @param engineType Engine type string to check - * @return True if engine type is supported - */ - static bool isEngineTypeSupported(const std::string& engineType); - - /** - * @brief Get engine type from string (case-insensitive) - * @param engineTypeStr String representation of engine type - * @return EngineType enum value - * @throws std::invalid_argument if string is not a valid engine type - */ - static EngineType parseEngineType(const std::string& engineTypeStr); - - /** - * @brief Convert engine type enum to string - * @param engineType Engine type enum value - * @return String representation of engine type - */ - static std::string engineTypeToString(EngineType engineType); - -private: - static std::shared_ptr getFactoryLogger(); - static std::string toLowercase(const std::string& str); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IEngine.h b/core/include/warfactory/IEngine.h deleted file mode 100644 index 9f1a236..0000000 --- a/core/include/warfactory/IEngine.h +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once - -#include -#include -#include - -// Forward declarations to avoid circular dependencies -namespace warfactory { - class IModuleSystem; -} - -using json = nlohmann::json; - -namespace warfactory { - -enum class EngineType { - DEBUG = 0, - PRODUCTION = 1, - HIGH_PERFORMANCE = 2 -}; - -/** - * @brief Engine orchestration interface - coordinates the entire system - * - * The engine is responsible for: - * - System initialization and lifecycle management - * - Main game loop coordination with delta time updates - * - Module system orchestration - * - IIO health monitoring and backpressure management - * - * IMPORTANT: Engine implementations must periodically check IIO health: - * - Monitor IOHealth.queueSize vs maxQueueSize (warn at 80% full) - * - Track IOHealth.dropping status (critical - consider module restart) - * - Log IOHealth.droppedMessageCount for debugging - * - Monitor IOHealth.averageProcessingRate for performance analysis - * - * Evolution path: - * - DebugEngine: Development/testing with step-by-step execution - * - HighPerfEngine: Production optimized with threading - * - DataOrientedEngine: Massive scale with SIMD and clustering - */ -class IEngine { -public: - virtual ~IEngine() = default; - - /** - * @brief Initialize engine systems - * - * Sets up the engine with basic configuration. - * Module system and other components are set separately. - */ - virtual void initialize() = 0; - - /** - * @brief Start main game loop - * - * Blocks until shutdown() called. Engine owns the main loop and handles: - * - Frame timing and delta time calculation - * - Module system coordination - * - Performance management and frame rate control - */ - virtual void run() = 0; - - /** - * @brief Process single frame/tick (for debugging) - * @param deltaTime Time elapsed since last update in seconds - * - * For step debugging and testing. Processes one iteration - * without entering the main loop. - */ - virtual void step(float deltaTime) = 0; - - /** - * @brief Shutdown engine and cleanup all resources - * - * Ensures proper cleanup of all systems in correct order. - * Should be safe to call multiple times. Stops run() loop. - */ - virtual void shutdown() = 0; - - /** - * @brief Load modules from configuration - * @param configPath Path to module configuration file - * - * Engine automatically: - * - Loads modules from .so/.dll files - * - Creates appropriate ModuleSystem for each module (performance strategy) - * - Configures execution frequency and coordination - * - * Config format: - * { - * "modules": [ - * {"path": "tank.so", "strategy": "threaded", "frequency": "60hz"}, - * {"path": "economy.so", "strategy": "sequential", "frequency": "0.1hz"} - * ] - * } - */ - virtual void loadModules(const std::string& configPath) = 0; - - /** - * @brief Register main coordinator socket - * @param coordinatorSocket Socket for system coordination communication - * - * Engine uses this socket for high-level system coordination, - * health monitoring, and administrative commands. - */ - virtual void registerMainSocket(std::unique_ptr coordinatorSocket) = 0; - - /** - * @brief Register new client/player socket - * @param clientSocket Socket for player communication - * - * Engine manages player connections as a priority channel. - * Players are the most important external connections. - */ - virtual void registerNewClientSocket(std::unique_ptr clientSocket) = 0; - - /** - * @brief Get engine type identifier - * @return Engine type enum value for identification - */ - virtual EngineType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IIO.h b/core/include/warfactory/IIO.h deleted file mode 100644 index 0f3edae..0000000 --- a/core/include/warfactory/IIO.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -enum class IOType { - INTRA = 0, // Same process - LOCAL = 1, // Same machine - NETWORK = 2 // TCP/WebSocket -}; - -struct SubscriptionConfig { - bool replaceable = false; // Replace vs accumulate for low-freq - int batchInterval = 30000; // ms for low-freq batching - int maxBatchSize = 100; // Max messages per batch - bool compress = false; // Compress batched data -}; - -struct Message { - std::string topic; - json data; - uint64_t timestamp; -}; - -struct IOHealth { - int queueSize; - int maxQueueSize; - bool dropping = false; // Started dropping messages? - float averageProcessingRate; // Messages/second processed by module - int droppedMessageCount = 0; // Total dropped since last check -}; - -/** - * @brief Pub/Sub communication interface with pull-based synchronous design - * - * Pull-based pub/sub system optimized for game modules. Modules have full control - * over when they process messages, avoiding threading issues. - * - * Features: - * - Topic patterns with wildcards (e.g., "player:*", "economy:*") - * - Low-frequency subscriptions for bandwidth optimization - * - Message consumption (pull removes message from queue) - * - Engine health monitoring for backpressure management - */ -class IIO { -public: - virtual ~IIO() = default; - - /** - * @brief Publish message to a topic - * @param topic Topic name (e.g., "player:123", "economy:prices") - * @param message JSON message data - */ - virtual void publish(const std::string& topic, const json& message) = 0; - - /** - * @brief Subscribe to topic pattern (high-frequency) - * @param topicPattern Topic pattern with wildcards (e.g., "player:*") - * @param config Optional subscription configuration - */ - virtual void subscribe(const std::string& topicPattern, const SubscriptionConfig& config = {}) = 0; - - /** - * @brief Subscribe to topic pattern (low-frequency batched) - * @param topicPattern Topic pattern with wildcards - * @param config Subscription configuration (batchInterval, etc.) - */ - virtual void subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config = {}) = 0; - - /** - * @brief Get count of pending messages - * @return Number of messages waiting to be pulled - */ - virtual int hasMessages() const = 0; - - /** - * @brief Pull and consume one message - * @return Message from queue (oldest first). Message is removed from queue. - * @throws std::runtime_error if no messages available - */ - virtual Message pullMessage() = 0; - - /** - * @brief Get IO health status for Engine monitoring - * @return Health metrics including queue size, drop status, processing rate - */ - virtual IOHealth getHealth() const = 0; - - /** - * @brief Get IO type identifier - * @return IO type enum value for identification - */ - virtual IOType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IModule.h b/core/include/warfactory/IModule.h deleted file mode 100644 index f343914..0000000 --- a/core/include/warfactory/IModule.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include -#include - -// Forward declarations -namespace warfactory { - class IIO; - class ITaskScheduler; -} - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Task scheduling interface for module delegation - * - * Allows modules to delegate tasks to their execution system without - * knowing the underlying implementation (sequential, threaded, thread pool). - */ -class ITaskScheduler { -public: - virtual ~ITaskScheduler() = default; - - /** - * @brief Schedule a task for execution - * @param taskType Type of task (e.g., "pathfinding", "collision_check") - * @param taskData JSON data for the task - */ - virtual void scheduleTask(const std::string& taskType, const json& taskData) = 0; - - /** - * @brief Check if completed tasks are available - * @return Number of completed tasks ready to be pulled - */ - virtual int hasCompletedTasks() const = 0; - - /** - * @brief Pull and consume one completed task - * @return Task result JSON. Task is removed from completed queue. - */ - virtual json getCompletedTask() = 0; -}; - - -/** - * @brief Pure business logic interface - optimized for Claude Code development - * - * This interface defines the contract for all game modules. Each module contains - * 200-300 lines of pure game logic with zero infrastructure code. - * - * Key design principles: - * - PURE FUNCTION: process() method has no side effects beyond return value - * - JSON ONLY: All communication via JSON input/output - * - NO INFRASTRUCTURE: No threading, networking, or framework dependencies - * - HOT-RELOAD READY: State serialization for seamless module replacement - * - CLAUDE OPTIMIZED: Micro-context size for AI development efficiency - * - * Module constraint: Maximum 300 lines per module (Exception: ProductionModule 500-800 lines) - */ -class IModule { -public: - virtual ~IModule() = default; - - /** - * @brief Process game logic - * @param input JSON input from other modules or the module system - * - * This is the core method where all module logic is implemented. - * Modules communicate via IIO pub/sub and can delegate tasks via ITaskScheduler. - * Must handle state properly through getState/setState for hot-reload. - */ - virtual void process(const json& input) = 0; - - /** - * @brief Initialize module with configuration and services - * @param config JSON configuration specific to this module - * @param io Pub/sub communication interface for messaging - * @param scheduler Task scheduling interface for delegating work - * - * Called once when the module is first loaded. Should setup any - * internal state, validate configuration, and store service references. - */ - virtual void initialize(const json& config, IIO* io, ITaskScheduler* scheduler) = 0; - - /** - * @brief Cleanup and shutdown the module - * - * Called when the module is being unloaded. Should clean up any - * resources and prepare for safe destruction. - */ - virtual void shutdown() = 0; - - /** - * @brief Get current module state for hot-reload support - * @return JSON representation of all module state - * - * Critical for hot-reload functionality. Must serialize all internal - * state that needs to be preserved when the module is replaced. - * The returned JSON should be sufficient to restore the module to - * its current state via setState(). - */ - virtual json getState() = 0; - - /** - * @brief Restore module state after hot-reload - * @param state JSON state previously returned by getState() - * - * Called after module replacement to restore the previous state. - * Must be able to reconstruct all internal state from the JSON - * to ensure seamless hot-reload without game disruption. - */ - virtual void setState(const json& state) = 0; - - /** - * @brief Get module type identifier - * @return Module type as string (e.g., "tank", "economy", "production") - */ - virtual std::string getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IModuleSystem.h b/core/include/warfactory/IModuleSystem.h deleted file mode 100644 index 2bfc9b1..0000000 --- a/core/include/warfactory/IModuleSystem.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include -#include -#include - -// Forward declarations to avoid circular dependencies -namespace warfactory { - class IModule; - class IIO; -} - -using json = nlohmann::json; - -namespace warfactory { - -enum class ModuleSystemType { - SEQUENTIAL = 0, - THREADED = 1, - THREAD_POOL = 2, - CLUSTER = 3 -}; - -/** - * @brief Task scheduling interface for module delegation - */ -class ITaskScheduler { -public: - virtual ~ITaskScheduler() = default; - - /** - * @brief Schedule a task for execution - * @param taskType Type of task (e.g., "pathfinding", "collision_check") - * @param taskData JSON data for the task - */ - virtual void scheduleTask(const std::string& taskType, const json& taskData) = 0; - - /** - * @brief Check if completed tasks are available - * @return Number of completed tasks ready to be pulled - */ - virtual int hasCompletedTasks() const = 0; - - /** - * @brief Pull and consume one completed task - * @return Task result JSON. Task is removed from completed queue. - */ - virtual json getCompletedTask() = 0; -}; - -/** - * @brief Module execution strategy interface - swappable performance architecture - * - * The module system manages module lifecycle and execution strategy. - * Different implementations provide different performance characteristics: - * - * - SequentialModuleSystem: Debug/test mode, processes modules one at a time - * - ThreadedModuleSystem: Each module in its own thread - * - MultithreadedModuleSystem: Module tasks distributed across thread pool - * - ClusterModuleSystem: Modules distributed across multiple machines - * - * This enables progressive evolution from debug to production to MMO scale - * without changing any module business logic code. - * - * Inherits from ITaskScheduler to provide task delegation capabilities. - */ -class IModuleSystem : public ITaskScheduler { -public: - virtual ~IModuleSystem() = default; - - /** - * @brief Register a module with the system - * @param name Unique identifier for the module - * @param module Module implementation (unique ownership) - * - * The module system takes ownership of the module and manages its lifecycle. - * Modules can be registered at any time and will participate in the next - * processing cycle. - */ - virtual void registerModule(const std::string& name, std::unique_ptr module) = 0; - - /** - * @brief Process all registered modules - * @param deltaTime Time elapsed since last processing cycle in seconds - * - * This is the core execution method that coordinates all modules according - * to the implemented strategy. Each module's process() method will be called - * with appropriate timing and coordination. - */ - virtual void processModules(float deltaTime) = 0; - - /** - * @brief Set the IO layer for inter-module communication - * @param ioLayer Communication transport implementation (unique ownership) - * - * The module system takes ownership of the IO layer and uses it to - * facilitate communication between modules. - */ - virtual void setIOLayer(std::unique_ptr ioLayer) = 0; - - /** - * @brief Query a specific module directly - * @param name Name of the module to query - * @param input JSON input to send to the module - * @return JSON response from the module - * - * This provides direct access to module functionality for debugging, - * testing, or administrative purposes. The query bypasses normal - * execution flow and calls the module's process() method directly. - */ - virtual json queryModule(const std::string& name, const json& input) = 0; - - /** - * @brief Get module system type identifier - * @return Module system type enum value for identification - */ - virtual ModuleSystemType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IOFactory.h b/core/include/warfactory/IOFactory.h deleted file mode 100644 index 10e1551..0000000 --- a/core/include/warfactory/IOFactory.h +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "IIO.h" - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Factory for creating IO transport implementations - * - * IOFactory provides centralized creation of different communication transports: - * - "intra" -> IntraIO (same-process direct function calls, zero network overhead) - * - "local" -> LocalIO (same-machine via named pipes/sockets, production single-server) - * - "network" -> NetworkIO (TCP/WebSocket for distributed deployment, MMO scale) - * - * Each IO type provides different performance and deployment characteristics while - * maintaining the same pub/sub interface, enabling progressive scaling from - * development to massive distributed systems. - * - * Usage: - * ```cpp - * auto io = IOFactory::create("intra"); - * auto io = IOFactory::create(IOType::NETWORK); - * auto io = IOFactory::createFromConfig(config); - * ``` - */ -class IOFactory { -public: - /** - * @brief Create IO transport from string type name - * @param transportType String representation of transport type - * @param instanceId Unique identifier for this IO instance (required for IntraIO) - * @return Unique pointer to IO implementation - * @throws std::invalid_argument if transport type is unknown - */ - static std::unique_ptr create(const std::string& transportType, const std::string& instanceId = ""); - - /** - * @brief Create IO transport from enum type - * @param ioType IOType enum value - * @param instanceId Unique identifier for this IO instance (required for IntraIO) - * @return Unique pointer to IO implementation - * @throws std::invalid_argument if type is not implemented - */ - static std::unique_ptr create(IOType ioType, const std::string& instanceId = ""); - - /** - * @brief Create IO transport from JSON configuration - * @param config JSON configuration object - * @param instanceId Unique identifier for this IO instance (required for IntraIO) - * @return Unique pointer to configured IO transport - * @throws std::invalid_argument if config is invalid - * - * Expected config format: - * ```json - * { - * "type": "network", - * "instance_id": "module-name", - * "host": "localhost", - * "port": 8080, - * "protocol": "tcp", - * "buffer_size": 4096, - * "timeout": 5000, - * "compression": true - * } - * ``` - */ - static std::unique_ptr createFromConfig(const json& config, const std::string& instanceId = ""); - - /** - * @brief Get list of available transport types - * @return Vector of supported transport strings - */ - static std::vector getAvailableTransports(); - - /** - * @brief Check if transport type is supported - * @param transportType Transport string to check - * @return True if transport type is supported - */ - static bool isTransportSupported(const std::string& transportType); - - /** - * @brief Parse transport string to enum (case-insensitive) - * @param transportStr String representation of transport - * @return IOType enum value - * @throws std::invalid_argument if string is invalid - */ - static IOType parseTransport(const std::string& transportStr); - - /** - * @brief Convert transport enum to string - * @param ioType IOType enum value - * @return String representation of transport - */ - static std::string transportToString(IOType ioType); - - /** - * @brief Get recommended transport for deployment scenario - * @param expectedClients Expected number of concurrent clients (0 = single-user) - * @param distributed Whether system will be distributed across machines - * @param development Whether this is for development/debugging - * @return Recommended IOType - */ - static IOType getRecommendedTransport(int expectedClients = 1, - bool distributed = false, - bool development = true); - - /** - * @brief Create IO transport with automatic endpoint discovery - * @param transportType Transport type to create - * @param endpoint Optional endpoint specification (auto-detected if empty) - * @param instanceId Unique identifier for this IO instance (required for IntraIO) - * @return Unique pointer to configured IO transport - */ - static std::unique_ptr createWithEndpoint(const std::string& transportType, - const std::string& endpoint = "", - const std::string& instanceId = ""); - -private: - static std::shared_ptr getFactoryLogger(); - static std::string toLowercase(const std::string& str); - static std::string generateEndpoint(IOType ioType); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IntraIO.h b/core/include/warfactory/IntraIO.h deleted file mode 100644 index 981fa5f..0000000 --- a/core/include/warfactory/IntraIO.h +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IIO.h" - -using json = nlohmann::json; - -namespace warfactory { - -// Interface for message delivery to avoid circular include -class IIntraIODelivery { -public: - virtual ~IIntraIODelivery() = default; - virtual void deliverMessage(const std::string& topic, const json& message, bool isLowFreq) = 0; - virtual const std::string& getInstanceId() const = 0; -}; - -/** - * @brief Intra-process IO implementation with central routing - * - * IntraIO provides same-process pub/sub communication with zero network overhead. - * Each module gets its own IntraIO instance, and messages are routed through - * IntraIOManager for proper multi-module delivery. - * - * Features: - * - Per-module isolation (one instance per module) - * - Central routing via IntraIOManager - * - Topic pattern matching with wildcards (e.g., "player:*", "economy:*") - * - Low-frequency batching with configurable intervals - * - Message replacement for reducible topics (latest-only semantics) - * - Comprehensive health monitoring and metrics - * - Thread-safe operations - * - Pull-based message consumption - * - * Performance characteristics: - * - Publish: ~10-50ns (direct memory copy + routing) - * - Subscribe: ~100-500ns (pattern registration) - * - Pull: ~50-200ns (queue operations) - * - Zero network serialization overhead - */ -class IntraIO : public IIO, public IIntraIODelivery { -private: - std::shared_ptr logger; - mutable std::mutex operationMutex; // Thread safety for all operations - - // Instance identification for routing - std::string instanceId; - - // Message storage - std::queue messageQueue; - std::queue lowFreqMessageQueue; - - // Subscription management - struct Subscription { - std::regex pattern; - std::string originalPattern; - SubscriptionConfig config; - std::chrono::high_resolution_clock::time_point lastBatch; - std::unordered_map batchedMessages; // For replaceable messages - std::vector accumulatedMessages; // For non-replaceable messages - }; - - std::vector highFreqSubscriptions; - std::vector lowFreqSubscriptions; - - // Health monitoring - mutable std::atomic totalPublished{0}; - mutable std::atomic totalPulled{0}; - mutable std::atomic totalDropped{0}; - mutable std::chrono::high_resolution_clock::time_point lastHealthCheck; - mutable float averageProcessingRate = 0.0f; - - // Configuration - static constexpr size_t DEFAULT_MAX_QUEUE_SIZE = 10000; - size_t maxQueueSize = DEFAULT_MAX_QUEUE_SIZE; - - // Helper methods - void logIOStart(); - bool matchesPattern(const std::string& topic, const std::regex& pattern) const; - std::regex compileTopicPattern(const std::string& pattern) const; - void processLowFreqSubscriptions(); - void flushBatchedMessages(Subscription& sub); - void updateHealthMetrics() const; - void enforceQueueLimits(); - void logPublish(const std::string& topic, const json& message) const; - void logSubscription(const std::string& pattern, bool isLowFreq) const; - void logPull(const Message& message) const; - -public: - IntraIO(const std::string& instanceId); - virtual ~IntraIO(); - - // IIO implementation - void publish(const std::string& topic, const json& message) override; - void subscribe(const std::string& topicPattern, const SubscriptionConfig& config = {}) override; - void subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config = {}) override; - int hasMessages() const override; - Message pullMessage() override; - IOHealth getHealth() const override; - IOType getType() const override; - - // Configuration and management - void setMaxQueueSize(size_t maxSize); - size_t getMaxQueueSize() const; - void clearAllMessages(); - void clearAllSubscriptions(); - - // Debug and monitoring - json getDetailedMetrics() const; - void setLogLevel(spdlog::level::level_enum level); - size_t getSubscriptionCount() const; - std::vector getActiveTopics() const; - - // Testing utilities - void simulateHighLoad(int messageCount, const std::string& topicPrefix = "test"); - void forceProcessLowFreqBatches(); - - // Manager interface (called by IntraIOManager) - void deliverMessage(const std::string& topic, const json& message, bool isLowFreq); - const std::string& getInstanceId() const; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/IntraIOManager.h b/core/include/warfactory/IntraIOManager.h deleted file mode 100644 index 3bb2b9e..0000000 --- a/core/include/warfactory/IntraIOManager.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IIO.h" - -using json = nlohmann::json; - -namespace warfactory { - -class IntraIO; // Forward declaration -class IIntraIODelivery; // Forward declaration - -// Factory function for creating IntraIO (defined in IntraIO.cpp to avoid circular include) -std::shared_ptr createIntraIOInstance(const std::string& instanceId); - -/** - * @brief Central router for IntraIO instances - * - * IntraIOManager coordinates message passing between multiple IntraIO instances. - * Each module gets its own IntraIO instance, and the manager handles routing - * messages between them based on subscriptions. - * - * Architecture: - * - One IntraIO instance per module (isolation) - * - Central routing of messages between instances - * - Pattern-based subscription matching - * - Thread-safe operations - * - * Performance: - * - Direct memory routing (no serialization) - * - Pattern caching for fast lookup - * - Batched delivery for efficiency - */ -class IntraIOManager { -private: - std::shared_ptr logger; - mutable std::mutex managerMutex; - - // Registry of IntraIO instances - std::unordered_map> instances; - - // Subscription routing table - struct RouteEntry { - std::string instanceId; - std::regex pattern; - std::string originalPattern; - bool isLowFreq; - }; - std::vector routingTable; - - // Statistics - mutable std::atomic totalRoutedMessages{0}; - mutable std::atomic totalRoutes{0}; - -public: - IntraIOManager(); - ~IntraIOManager(); - - // Instance management - std::shared_ptr createInstance(const std::string& instanceId); - void registerInstance(const std::string& instanceId, std::shared_ptr instance); - void removeInstance(const std::string& instanceId); - std::shared_ptr getInstance(const std::string& instanceId) const; - - // Routing (called by IntraIO instances) - void routeMessage(const std::string& sourceid, const std::string& topic, const json& message); - void registerSubscription(const std::string& instanceId, const std::string& pattern, bool isLowFreq); - void unregisterSubscription(const std::string& instanceId, const std::string& pattern); - - // Management - void clearAllRoutes(); - size_t getInstanceCount() const; - std::vector getInstanceIds() const; - - // Debug and monitoring - json getRoutingStats() const; - void setLogLevel(spdlog::level::level_enum level); - - // Singleton access (for global routing) - static IntraIOManager& getInstance(); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/ModuleFactory.h b/core/include/warfactory/ModuleFactory.h deleted file mode 100644 index 5c7cc29..0000000 --- a/core/include/warfactory/ModuleFactory.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "IModule.h" - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Factory for loading and creating modules from shared libraries (.so files) - * - * ModuleFactory handles dynamic loading of module implementations from .so files. - * It manages symbol resolution, error handling, and module lifecycle. - * - * Features: - * - Dynamic loading of .so files with dlopen/dlsym - * - Automatic symbol resolution for module entry points - * - Hot-reload support with proper cleanup - * - Comprehensive error reporting and logging - * - Module registration and discovery - * - Thread-safe operations - * - * Expected module .so structure: - * - extern "C" IModule* create_module() - * - extern "C" void destroy_module(IModule*) - * - extern "C" const char* get_module_type() - * - extern "C" const char* get_module_version() - */ -class ModuleFactory { -public: - struct ModuleInfo { - std::string path; - std::string type; - std::string version; - void* handle = nullptr; - std::function createFunc; - std::function destroyFunc; - }; - - ModuleFactory(); - ~ModuleFactory(); - - // Module loading - std::unique_ptr loadModule(const std::string& modulePath); - std::unique_ptr createModule(const std::string& moduleType); - - // Module discovery and registration - void scanModulesDirectory(const std::string& directory); - void registerModule(const std::string& modulePath); - void unloadModule(const std::string& moduleType); - void unloadAllModules(); - - // Information and diagnostics - std::vector getAvailableModules() const; - std::vector getLoadedModules() const; - ModuleInfo getModuleInfo(const std::string& moduleType) const; - bool isModuleLoaded(const std::string& moduleType) const; - bool isModuleAvailable(const std::string& moduleType) const; - - // Configuration - void setModulesDirectory(const std::string& directory); - std::string getModulesDirectory() const; - - // Hot-reload support - bool reloadModule(const std::string& moduleType); - void enableHotReload(bool enable); - bool isHotReloadEnabled() const; - - // Diagnostics and debugging - json getDetailedStatus() const; - void validateModule(const std::string& modulePath); - void setLogLevel(spdlog::level::level_enum level); - -private: - std::shared_ptr logger; - std::string modulesDirectory; - bool hotReloadEnabled = false; - - // Module registry - std::unordered_map loadedModules; - std::unordered_map availableModules; // type -> path - - // Helper methods - std::shared_ptr getFactoryLogger(); - bool loadSharedLibrary(const std::string& path, ModuleInfo& info); - void unloadSharedLibrary(ModuleInfo& info); - bool resolveSymbols(ModuleInfo& info); - std::string extractModuleTypeFromPath(const std::string& path) const; - bool isValidModuleFile(const std::string& path) const; - void logModuleLoad(const std::string& type, const std::string& path) const; - void logModuleUnload(const std::string& type) const; - void logModuleError(const std::string& operation, const std::string& details) const; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/ModuleSystemFactory.h b/core/include/warfactory/ModuleSystemFactory.h deleted file mode 100644 index 9ccd84a..0000000 --- a/core/include/warfactory/ModuleSystemFactory.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "IModuleSystem.h" - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Factory for creating ModuleSystem implementations - * - * ModuleSystemFactory provides centralized creation of different execution strategies: - * - "sequential" -> SequentialModuleSystem (debug/test, one-at-a-time execution) - * - "threaded" -> ThreadedModuleSystem (each module in own thread) - * - "thread_pool" -> ThreadPoolModuleSystem (tasks distributed across pool) - * - "cluster" -> ClusterModuleSystem (distributed across machines) - * - * Each ModuleSystem type provides different performance characteristics while - * maintaining the same interface, enabling progressive scaling. - * - * Usage: - * ```cpp - * auto moduleSystem = ModuleSystemFactory::create("sequential"); - * auto moduleSystem = ModuleSystemFactory::create(ModuleSystemType::THREAD_POOL); - * auto moduleSystem = ModuleSystemFactory::createFromConfig(config); - * ``` - */ -class ModuleSystemFactory { -public: - /** - * @brief Create ModuleSystem from string strategy name - * @param strategy String representation of execution strategy - * @return Unique pointer to ModuleSystem implementation - * @throws std::invalid_argument if strategy is unknown - */ - static std::unique_ptr create(const std::string& strategy); - - /** - * @brief Create ModuleSystem from enum type - * @param systemType ModuleSystemType enum value - * @return Unique pointer to ModuleSystem implementation - * @throws std::invalid_argument if type is not implemented - */ - static std::unique_ptr create(ModuleSystemType systemType); - - /** - * @brief Create ModuleSystem from JSON configuration - * @param config JSON configuration object - * @return Unique pointer to configured ModuleSystem - * @throws std::invalid_argument if config is invalid - * - * Expected config format: - * ```json - * { - * "strategy": "thread_pool", - * "thread_count": 4, - * "queue_size": 1000, - * "priority": "normal" - * } - * ``` - */ - static std::unique_ptr createFromConfig(const json& config); - - /** - * @brief Get list of available ModuleSystem strategies - * @return Vector of supported strategy strings - */ - static std::vector getAvailableStrategies(); - - /** - * @brief Check if strategy is supported - * @param strategy Strategy string to check - * @return True if strategy is supported - */ - static bool isStrategySupported(const std::string& strategy); - - /** - * @brief Parse strategy string to enum (case-insensitive) - * @param strategyStr String representation of strategy - * @return ModuleSystemType enum value - * @throws std::invalid_argument if string is invalid - */ - static ModuleSystemType parseStrategy(const std::string& strategyStr); - - /** - * @brief Convert strategy enum to string - * @param systemType ModuleSystemType enum value - * @return String representation of strategy - */ - static std::string strategyToString(ModuleSystemType systemType); - - /** - * @brief Get recommended strategy for given performance requirements - * @param targetFPS Target frames per second (0 = no preference) - * @param moduleCount Expected number of modules - * @param cpuCores Available CPU cores (0 = auto-detect) - * @return Recommended ModuleSystemType - */ - static ModuleSystemType getRecommendedStrategy(int targetFPS = 60, - int moduleCount = 1, - int cpuCores = 0); - -private: - static std::shared_ptr getFactoryLogger(); - static std::string toLowercase(const std::string& str); - static int detectCpuCores(); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/include/warfactory/SequentialModuleSystem.h b/core/include/warfactory/SequentialModuleSystem.h deleted file mode 100644 index 709eec9..0000000 --- a/core/include/warfactory/SequentialModuleSystem.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "IModuleSystem.h" -#include "IModule.h" - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Sequential module system implementation for debug and testing - * - * SequentialModuleSystem processes modules one at a time in a simple, predictable manner. - * Perfect for development, debugging, and testing scenarios where deterministic execution - * is more important than performance. - * - * Features: - * - Single-threaded execution (thread-safe by design) - * - Immediate task execution (no actual scheduling) - * - Comprehensive logging of all operations - * - Simple state management - * - Perfect for step-by-step debugging - * - * Task scheduling behavior: - * - scheduleTask() executes immediately (no queue) - * - hasCompletedTasks() always returns 0 (tasks complete immediately) - * - getCompletedTask() throws (no queued results) - */ -class SequentialModuleSystem : public IModuleSystem { -private: - std::shared_ptr logger; - std::unique_ptr module; - std::string moduleName = "unknown"; - - // Performance tracking - std::chrono::high_resolution_clock::time_point lastProcessTime; - size_t processCallCount = 0; - float totalProcessTime = 0.0f; - float lastProcessDuration = 0.0f; - - // Task execution tracking (for logging purposes) - size_t taskExecutionCount = 0; - - // Helper methods - void logSystemStart(); - void logProcessStart(float deltaTime); - void logProcessEnd(float processTime); - void logTaskExecution(const std::string& taskType, const json& taskData); - void validateModule() const; - -public: - SequentialModuleSystem(); - virtual ~SequentialModuleSystem(); - - // IModuleSystem implementation - void setModule(std::unique_ptr module) override; - IModule* getModule() const override; - int processModule(float deltaTime) override; - ModuleSystemType getType() const override; - - // Hot-reload support - std::unique_ptr extractModule(); - - // ITaskScheduler implementation (inherited) - void scheduleTask(const std::string& taskType, const json& taskData) override; - int hasCompletedTasks() const override; - json getCompletedTask() override; - - // Debug and monitoring methods - json getPerformanceMetrics() const; - void resetPerformanceMetrics(); - float getAverageProcessTime() const; - size_t getProcessCallCount() const; - size_t getTaskExecutionCount() const; - - // Configuration - void setLogLevel(spdlog::level::level_enum level); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/DebugEngine.cpp b/core/src/DebugEngine.cpp deleted file mode 100644 index dca6b2c..0000000 --- a/core/src/DebugEngine.cpp +++ /dev/null @@ -1,487 +0,0 @@ -#include -#include -#include -#include -#include - -namespace warfactory { - -DebugEngine::DebugEngine() { - // Create comprehensive logger with multiple sinks - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared("logs/debug_engine.log", true); - - console_sink->set_level(spdlog::level::debug); - file_sink->set_level(spdlog::level::trace); - - logger = std::make_shared("DebugEngine", - spdlog::sinks_init_list{console_sink, file_sink}); - logger->set_level(spdlog::level::trace); - logger->flush_on(spdlog::level::debug); - - // Register logger globally - spdlog::register_logger(logger); - - logger->info("🔧 DebugEngine constructor - Maximum logging enabled"); - logger->debug("📊 Console sink level: DEBUG, File sink level: TRACE"); - logger->trace("🏗️ DebugEngine object created at address: {}", static_cast(this)); -} - -DebugEngine::~DebugEngine() { - logger->info("🔧 DebugEngine destructor called"); - if (running.load()) { - logger->warn("⚠️ Engine still running during destruction - forcing shutdown"); - shutdown(); - } - logger->trace("🏗️ DebugEngine object destroyed"); -} - -void DebugEngine::initialize() { - logger->info("🚀 Initializing DebugEngine..."); - logEngineStart(); - - // Create logs directory if it doesn't exist - std::filesystem::create_directories("logs"); - logger->debug("📁 Ensured logs directory exists"); - - engineStartTime = std::chrono::high_resolution_clock::now(); - lastFrameTime = engineStartTime; - frameCount = 0; - - logger->info("✅ DebugEngine initialization complete"); - logger->debug("🕐 Engine start time recorded: {}", - std::chrono::duration_cast( - engineStartTime.time_since_epoch()).count()); -} - -void DebugEngine::run() { - logger->info("🏃 Starting DebugEngine main loop"); - logger->debug("🔄 Engine loop type: Continuous with debug capabilities"); - - if (!coordinatorSocket) { - logger->warn("⚠️ No coordinator socket registered - running in isolated mode"); - } - - if (clientSockets.empty()) { - logger->warn("⚠️ No client sockets registered - no players will connect"); - } - - running.store(true); - logger->info("✅ DebugEngine marked as running"); - - while (running.load()) { - if (debugPaused.load()) { - logger->trace("⏸️ Engine paused - waiting for resume or step command"); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - continue; - } - - float deltaTime = calculateDeltaTime(); - step(deltaTime); - - // Log every 60 frames (roughly every second at 60fps) - if (frameCount % 60 == 0) { - logger->debug("📊 Frame {}: Running smoothly, deltaTime: {:.3f}ms", - frameCount, deltaTime * 1000); - } - } - - logger->info("🏁 DebugEngine main loop ended"); -} - -void DebugEngine::step(float deltaTime) { - logFrameStart(deltaTime); - - auto frameStartTime = std::chrono::high_resolution_clock::now(); - - try { - // Process coordinator messages - if (coordinatorSocket) { - logger->trace("📨 Processing coordinator messages"); - processCoordinatorMessages(); - } - - // Process client messages - if (!clientSockets.empty()) { - logger->trace("👥 Processing {} client socket(s)", clientSockets.size()); - processClientMessages(); - } - - // Process all module systems - if (!moduleSystems.empty()) { - logger->trace("🔧 Processing {} module system(s)", moduleSystems.size()); - processModuleSystems(deltaTime); - } - - // Health monitoring every 30 frames - if (frameCount % 30 == 0) { - logModuleHealth(); - logSocketHealth(); - } - - frameCount++; - - } catch (const std::exception& e) { - logger->error("❌ Exception during step execution: {}", e.what()); - logger->error("🔍 Frame: {}, deltaTime: {:.3f}ms", frameCount, deltaTime * 1000); - throw; // Re-throw to allow caller to handle - } - - auto frameEndTime = std::chrono::high_resolution_clock::now(); - float frameTime = std::chrono::duration(frameEndTime - frameStartTime).count(); - - logFrameEnd(frameTime); -} - -void DebugEngine::shutdown() { - logger->info("🛑 DebugEngine shutdown initiated"); - logEngineShutdown(); - - running.store(false); - logger->debug("🔄 Running flag set to false"); - - // Shutdown all module systems - if (!moduleSystems.empty()) { - logger->info("🔧 Shutting down {} module system(s)", moduleSystems.size()); - for (size_t i = 0; i < moduleSystems.size(); ++i) { - logger->debug("🔧 Shutting down module system: {}", moduleNames[i]); - // Note: ModuleSystems don't have shutdown in interface yet - // This would be added when implementing IModuleSystem - } - moduleSystems.clear(); - moduleNames.clear(); - logger->info("✅ All module systems shut down"); - } - - // Clear sockets - if (coordinatorSocket) { - logger->debug("🔌 Clearing coordinator socket"); - coordinatorSocket.reset(); - } - - if (!clientSockets.empty()) { - logger->info("👥 Clearing {} client socket(s)", clientSockets.size()); - clientSockets.clear(); - } - - logger->info("✅ DebugEngine shutdown complete"); - - // Final statistics - auto shutdownTime = std::chrono::high_resolution_clock::now(); - auto totalRunTime = std::chrono::duration(shutdownTime - engineStartTime).count(); - logger->info("📊 Total engine runtime: {:.2f} seconds", totalRunTime); - logger->info("📊 Total frames processed: {}", frameCount); - if (totalRunTime > 0) { - logger->info("📊 Average FPS: {:.2f}", frameCount / totalRunTime); - } -} - -void DebugEngine::loadModules(const std::string& configPath) { - logger->info("📦 Loading modules from config: {}", configPath); - - try { - // Read configuration file - std::ifstream configFile(configPath); - if (!configFile.is_open()) { - logger->error("❌ Cannot open config file: {}", configPath); - throw std::runtime_error("Config file not found: " + configPath); - } - - json config; - configFile >> config; - logger->debug("✅ Config file parsed successfully"); - logger->trace("📄 Config content: {}", config.dump(2)); - - // Validate configuration - validateConfiguration(); - - if (!config.contains("modules")) { - logger->warn("⚠️ No 'modules' section in config - no modules to load"); - return; - } - - auto modules = config["modules"]; - logger->info("🔍 Found {} module(s) to load", modules.size()); - - for (size_t i = 0; i < modules.size(); ++i) { - const auto& moduleConfig = modules[i]; - logger->info("📦 Loading module {}/{}", i + 1, modules.size()); - - if (!moduleConfig.contains("path") || !moduleConfig.contains("strategy")) { - logger->error("❌ Module config missing 'path' or 'strategy': {}", moduleConfig.dump()); - continue; - } - - std::string modulePath = moduleConfig["path"]; - std::string strategy = moduleConfig["strategy"]; - std::string frequency = moduleConfig.value("frequency", "60hz"); - - logger->info("📂 Module path: {}", modulePath); - logger->info("⚙️ Module strategy: {}", strategy); - logger->info("⏱️ Module frequency: {}", frequency); - - // TODO: Create appropriate ModuleSystem based on strategy - // For now, we'll log what would be created - logger->info("🚧 TODO: Create {} ModuleSystem for {}", strategy, modulePath); - logger->debug("🔮 Future: Load dynamic library from {}", modulePath); - logger->debug("🔮 Future: Instantiate module and wrap in {} system", strategy); - - // Store module name for tracking - moduleNames.push_back(modulePath); - } - - logger->info("✅ Module loading configuration processed"); - - } catch (const std::exception& e) { - logger->error("❌ Failed to load modules: {}", e.what()); - throw; - } -} - -void DebugEngine::registerMainSocket(std::unique_ptr socket) { - logger->info("🔌 Registering main coordinator socket"); - - if (coordinatorSocket) { - logger->warn("⚠️ Coordinator socket already exists - replacing"); - } - - coordinatorSocket = std::move(socket); - logger->info("✅ Main coordinator socket registered"); - logger->debug("🔍 Socket type: {}", static_cast(coordinatorSocket->getType())); -} - -void DebugEngine::registerNewClientSocket(std::unique_ptr clientSocket) { - logger->info("👥 Registering new client socket (client #{})", clientSockets.size() + 1); - - logger->debug("🔍 Client socket type: {}", static_cast(clientSocket->getType())); - clientSockets.push_back(std::move(clientSocket)); - - logger->info("✅ Client socket registered - Total clients: {}", clientSockets.size()); -} - -EngineType DebugEngine::getType() const { - logger->trace("🏷️ Engine type requested: DEBUG"); - return EngineType::DEBUG; -} - -// Debug-specific methods -void DebugEngine::pauseExecution() { - logger->info("⏸️ Pausing engine execution"); - debugPaused.store(true); - logger->debug("🔄 Debug pause flag set to true"); -} - -void DebugEngine::resumeExecution() { - logger->info("▶️ Resuming engine execution"); - debugPaused.store(false); - logger->debug("🔄 Debug pause flag set to false"); -} - -void DebugEngine::stepSingleFrame() { - logger->info("👣 Executing single frame step"); - if (debugPaused.load()) { - float deltaTime = calculateDeltaTime(); - step(deltaTime); - logger->debug("✅ Single frame step completed"); - } else { - logger->warn("⚠️ Cannot step single frame - engine not paused"); - } -} - -bool DebugEngine::isPaused() const { - bool paused = debugPaused.load(); - logger->trace("🔍 Pause status requested: {}", paused ? "PAUSED" : "RUNNING"); - return paused; -} - -json DebugEngine::getDetailedStatus() const { - logger->debug("📊 Detailed status requested"); - - json status = { - {"type", "DEBUG"}, - {"running", running.load()}, - {"paused", debugPaused.load()}, - {"frame_count", frameCount}, - {"modules_loaded", moduleNames.size()}, - {"client_sockets", clientSockets.size()}, - {"has_coordinator", coordinatorSocket != nullptr} - }; - - // Add runtime info - if (frameCount > 0) { - auto currentTime = std::chrono::high_resolution_clock::now(); - auto totalTime = std::chrono::duration(currentTime - engineStartTime).count(); - status["runtime_seconds"] = totalTime; - status["average_fps"] = frameCount / totalTime; - } - - logger->trace("📄 Status JSON: {}", status.dump()); - return status; -} - -void DebugEngine::setLogLevel(spdlog::level::level_enum level) { - logger->info("🔧 Setting log level to: {}", spdlog::level::to_string_view(level)); - logger->set_level(level); - logger->debug("✅ Log level updated"); -} - -// Private helper methods -void DebugEngine::logEngineStart() { - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🏭 WARFACTORY DEBUG ENGINE STARTING"); - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🎯 Engine Type: DEBUG (Maximum visibility mode)"); - logger->info("📊 Logging Level: TRACE (Everything logged)"); - logger->info("🔧 Features: Step debugging, health monitoring, performance tracking"); -} - -void DebugEngine::logEngineShutdown() { - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🏭 WARFACTORY DEBUG ENGINE SHUTTING DOWN"); - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); -} - -void DebugEngine::logFrameStart(float deltaTime) { - logger->trace("🎬 Frame {} START - deltaTime: {:.3f}ms", frameCount, deltaTime * 1000); -} - -void DebugEngine::logFrameEnd(float frameTime) { - logger->trace("🏁 Frame {} END - frameTime: {:.3f}ms", frameCount, frameTime); - - // Warn about slow frames - if (frameTime > 16.67f) { // More than 60fps target - logger->warn("🐌 Slow frame detected: {:.2f}ms (target: <16.67ms for 60fps)", frameTime); - } -} - -void DebugEngine::logModuleHealth() { - if (moduleSystems.empty()) { - logger->debug("🏥 Module health check: No modules loaded"); - return; - } - - logger->debug("🏥 Module health check: {} module system(s)", moduleSystems.size()); - - for (size_t i = 0; i < moduleSystems.size(); ++i) { - // TODO: When IModuleSystem has health methods, check them here - logger->trace("🔍 Module '{}': Status unknown (health interface not implemented)", moduleNames[i]); - } -} - -void DebugEngine::logSocketHealth() { - logger->debug("🌐 Socket health check:"); - - if (coordinatorSocket) { - auto health = coordinatorSocket->getHealth(); - logger->debug("📡 Coordinator socket: Queue={}/{}, Dropping={}, Rate={:.1f}msg/s", - health.queueSize, health.maxQueueSize, health.dropping, health.averageProcessingRate); - - if (health.dropping) { - logger->warn("⚠️ Coordinator socket dropping messages!"); - } - if (health.queueSize > health.maxQueueSize * 0.8) { - logger->warn("⚠️ Coordinator socket queue 80% full ({}/{})", health.queueSize, health.maxQueueSize); - } - } - - for (size_t i = 0; i < clientSockets.size(); ++i) { - auto health = clientSockets[i]->getHealth(); - logger->debug("👤 Client socket {}: Queue={}/{}, Dropping={}, Rate={:.1f}msg/s", - i, health.queueSize, health.maxQueueSize, health.dropping, health.averageProcessingRate); - - if (health.dropping) { - logger->warn("⚠️ Client socket {} dropping messages!", i); - } - } -} - -void DebugEngine::processModuleSystems(float deltaTime) { - logger->trace("⚙️ Processing {} module system(s)", moduleSystems.size()); - - for (size_t i = 0; i < moduleSystems.size(); ++i) { - logger->trace("🔧 Processing module system: {}", moduleNames[i]); - - try { - // TODO: Call moduleSystem->processModule(deltaTime) when implemented - logger->trace("🚧 TODO: Call processModule() on {}", moduleNames[i]); - - } catch (const std::exception& e) { - logger->error("❌ Error processing module '{}': {}", moduleNames[i], e.what()); - } - } -} - -void DebugEngine::processClientMessages() { - for (size_t i = 0; i < clientSockets.size(); ++i) { - auto& socket = clientSockets[i]; - int messageCount = socket->hasMessages(); - - if (messageCount > 0) { - logger->trace("📨 Client {} has {} pending message(s)", i, messageCount); - - // Process a few messages per frame to avoid blocking - int messagesToProcess = std::min(messageCount, 5); - - for (int j = 0; j < messagesToProcess; ++j) { - try { - auto message = socket->pullMessage(); - logger->debug("📩 Client {} message: topic='{}', data size={}", - i, message.topic, message.data.dump().size()); - - // TODO: Route message to appropriate module or process it - logger->trace("🚧 TODO: Route client message to modules"); - - } catch (const std::exception& e) { - logger->error("❌ Error processing client {} message: {}", i, e.what()); - } - } - } - } -} - -void DebugEngine::processCoordinatorMessages() { - int messageCount = coordinatorSocket->hasMessages(); - - if (messageCount > 0) { - logger->trace("📨 Coordinator has {} pending message(s)", messageCount); - - // Process coordinator messages with higher priority - int messagesToProcess = std::min(messageCount, 10); - - for (int i = 0; i < messagesToProcess; ++i) { - try { - auto message = coordinatorSocket->pullMessage(); - logger->debug("📩 Coordinator message: topic='{}', data size={}", - message.topic, message.data.dump().size()); - - // TODO: Handle coordinator commands (shutdown, config reload, etc.) - logger->trace("🚧 TODO: Handle coordinator commands"); - - } catch (const std::exception& e) { - logger->error("❌ Error processing coordinator message: {}", e.what()); - } - } - } -} - -float DebugEngine::calculateDeltaTime() { - auto currentTime = std::chrono::high_resolution_clock::now(); - float deltaTime = std::chrono::duration(currentTime - lastFrameTime).count(); - lastFrameTime = currentTime; - - // Cap delta time to avoid huge jumps (e.g., after debugging pause) - if (deltaTime > 0.1f) { - logger->trace("⏱️ Large deltaTime detected: {:.3f}s - capping to 100ms", deltaTime); - deltaTime = 0.1f; - } - - return deltaTime; -} - -void DebugEngine::validateConfiguration() { - logger->debug("✅ Configuration validation passed"); - // TODO: Add actual validation logic - logger->trace("🚧 TODO: Implement comprehensive config validation"); -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/EngineFactory.cpp b/core/src/EngineFactory.cpp deleted file mode 100644 index 1127cf7..0000000 --- a/core/src/EngineFactory.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -std::unique_ptr EngineFactory::createEngine(const std::string& engineType) { - auto logger = getFactoryLogger(); - logger->info("🏭 EngineFactory: Creating engine of type '{}'", engineType); - - EngineType type = parseEngineType(engineType); - return createEngine(type); -} - -std::unique_ptr EngineFactory::createEngine(EngineType engineType) { - auto logger = getFactoryLogger(); - std::string typeStr = engineTypeToString(engineType); - logger->info("🏭 EngineFactory: Creating engine of enum type '{}'", typeStr); - - std::unique_ptr engine; - - switch (engineType) { - case EngineType::DEBUG: - logger->debug("🔧 Creating DebugEngine instance"); - engine = std::make_unique(); - logger->info("✅ DebugEngine created successfully"); - break; - - case EngineType::PRODUCTION: - logger->error("❌ ProductionEngine not yet implemented"); - throw std::invalid_argument("ProductionEngine not yet implemented - use DEBUG for now"); - - case EngineType::HIGH_PERFORMANCE: - logger->error("❌ HighPerformanceEngine not yet implemented"); - throw std::invalid_argument("HighPerformanceEngine not yet implemented - use DEBUG for now"); - - default: - logger->error("❌ Unknown engine type enum value: {}", static_cast(engineType)); - throw std::invalid_argument("Unknown engine type enum value: " + std::to_string(static_cast(engineType))); - } - - logger->debug("🎯 Engine type verification: created engine reports type '{}'", - engineTypeToString(engine->getType())); - - return engine; -} - -std::unique_ptr EngineFactory::createFromConfig(const std::string& configPath) { - auto logger = getFactoryLogger(); - logger->info("🏭 EngineFactory: Creating engine from config '{}'", configPath); - - try { - // Read configuration file - std::ifstream configFile(configPath); - if (!configFile.is_open()) { - logger->error("❌ Cannot open config file: {}", configPath); - throw std::runtime_error("Cannot open engine config file: " + configPath); - } - - json config; - configFile >> config; - logger->debug("✅ Config file parsed successfully"); - - // Extract engine configuration - if (!config.contains("engine")) { - logger->error("❌ Config file missing 'engine' section"); - throw std::runtime_error("Config file missing 'engine' section"); - } - - auto engineConfig = config["engine"]; - - if (!engineConfig.contains("type")) { - logger->error("❌ Engine config missing 'type' field"); - throw std::runtime_error("Engine config missing 'type' field"); - } - - std::string engineType = engineConfig["type"]; - logger->info("📋 Config specifies engine type: '{}'", engineType); - - // Create engine - auto engine = createEngine(engineType); - - // Apply additional configuration if available - if (engineConfig.contains("log_level")) { - std::string logLevel = engineConfig["log_level"]; - logger->info("🔧 Config specifies log level: '{}'", logLevel); - - // Apply log level if engine supports it (DebugEngine does) - if (engine->getType() == EngineType::DEBUG) { - auto debugEngine = static_cast(engine.get()); - - if (logLevel == "trace") debugEngine->setLogLevel(spdlog::level::trace); - else if (logLevel == "debug") debugEngine->setLogLevel(spdlog::level::debug); - else if (logLevel == "info") debugEngine->setLogLevel(spdlog::level::info); - else if (logLevel == "warn") debugEngine->setLogLevel(spdlog::level::warn); - else if (logLevel == "error") debugEngine->setLogLevel(spdlog::level::err); - else { - logger->warn("⚠️ Unknown log level '{}' - using default", logLevel); - } - } - } - - if (engineConfig.contains("features")) { - auto features = engineConfig["features"]; - logger->debug("🎛️ Engine features configuration found: {}", features.dump()); - // TODO: Apply feature configuration when engines support it - } - - logger->info("✅ Engine created from config successfully"); - return engine; - - } catch (const json::exception& e) { - logger->error("❌ JSON parsing error in config file: {}", e.what()); - throw std::runtime_error("Invalid JSON in engine config file: " + std::string(e.what())); - } catch (const std::exception& e) { - logger->error("❌ Error creating engine from config: {}", e.what()); - throw; - } -} - -std::vector EngineFactory::getAvailableEngineTypes() { - return { - "debug", - "production", // Not yet implemented - "high_performance" // Not yet implemented - }; -} - -bool EngineFactory::isEngineTypeSupported(const std::string& engineType) { - try { - parseEngineType(engineType); - return true; - } catch (const std::invalid_argument&) { - return false; - } -} - -EngineType EngineFactory::parseEngineType(const std::string& engineTypeStr) { - auto logger = getFactoryLogger(); - std::string lowerType = toLowercase(engineTypeStr); - - logger->trace("🔍 Parsing engine type: '{}' -> '{}'", engineTypeStr, lowerType); - - if (lowerType == "debug") { - return EngineType::DEBUG; - } else if (lowerType == "production") { - return EngineType::PRODUCTION; - } else if (lowerType == "high_performance" || lowerType == "high-performance" || lowerType == "highperformance") { - return EngineType::HIGH_PERFORMANCE; - } else { - logger->error("❌ Unknown engine type: '{}'", engineTypeStr); - auto availableTypes = getAvailableEngineTypes(); - std::string availableStr = "["; - for (size_t i = 0; i < availableTypes.size(); ++i) { - availableStr += availableTypes[i]; - if (i < availableTypes.size() - 1) availableStr += ", "; - } - availableStr += "]"; - - throw std::invalid_argument("Unknown engine type '" + engineTypeStr + "'. Available types: " + availableStr); - } -} - -std::string EngineFactory::engineTypeToString(EngineType engineType) { - switch (engineType) { - case EngineType::DEBUG: - return "debug"; - case EngineType::PRODUCTION: - return "production"; - case EngineType::HIGH_PERFORMANCE: - return "high_performance"; - default: - return "unknown"; - } -} - -// Private helper methods -std::shared_ptr EngineFactory::getFactoryLogger() { - static std::shared_ptr logger = nullptr; - - if (!logger) { - auto console_sink = std::make_shared(); - console_sink->set_level(spdlog::level::debug); - - logger = std::make_shared("EngineFactory", console_sink); - logger->set_level(spdlog::level::debug); - logger->flush_on(spdlog::level::debug); - - // Register globally - spdlog::register_logger(logger); - } - - return logger; -} - -std::string EngineFactory::toLowercase(const std::string& str) { - std::string result = str; - std::transform(result.begin(), result.end(), result.begin(), - [](char c) { return std::tolower(c); }); - return result; -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/IOFactory.cpp b/core/src/IOFactory.cpp deleted file mode 100644 index e373fc9..0000000 --- a/core/src/IOFactory.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include -#include -#include -#include -#include - -// Include implemented transports -#include -#include -// Forward declarations for future implementations -// #include "LocalIO.h" -// #include "NetworkIO.h" - -namespace warfactory { - -std::unique_ptr IOFactory::create(const std::string& transportType, const std::string& instanceId) { - auto logger = getFactoryLogger(); - logger->info("🌐 IOFactory: Creating transport '{}' with instanceId '{}'", transportType, instanceId); - - IOType type = parseTransport(transportType); - return create(type, instanceId); -} - -std::unique_ptr IOFactory::create(IOType ioType, const std::string& instanceId) { - auto logger = getFactoryLogger(); - std::string typeStr = transportToString(ioType); - logger->info("🌐 IOFactory: Creating enum type '{}' with instanceId '{}'", typeStr, instanceId); - - std::unique_ptr io; - - switch (ioType) { - case IOType::INTRA: { - logger->debug("🔧 Creating IntraIO instance"); - - // Generate instanceId if not provided - std::string actualInstanceId = instanceId; - if (actualInstanceId.empty()) { - actualInstanceId = "intra-" + std::to_string(std::random_device{}() % 10000); - logger->debug("🔧 Generated instanceId: '{}'", actualInstanceId); - } - - // TEMPORARY SOLUTION: Create direct IntraIO instance - // TODO: Properly integrate with IntraIOManager without type issues - io = std::make_unique(actualInstanceId); - - // Manually register with manager for routing - auto& manager = IntraIOManager::getInstance(); - manager.registerInstance(actualInstanceId, - std::static_pointer_cast( - std::shared_ptr(static_cast(io.get()), [](IntraIO*) { - // Don't delete - unique_ptr will handle it - }) - ) - ); - - logger->info("✅ IntraIO created successfully with instanceId '{}'", actualInstanceId); - break; - } - - case IOType::LOCAL: - logger->debug("🔧 Creating LocalIO instance"); - // TODO: Implement LocalIO - // io = std::make_unique(); - logger->error("❌ LocalIO not yet implemented"); - throw std::invalid_argument("LocalIO not yet implemented"); - - case IOType::NETWORK: - logger->debug("🔧 Creating NetworkIO instance"); - // TODO: Implement NetworkIO - // io = std::make_unique(); - logger->error("❌ NetworkIO not yet implemented"); - throw std::invalid_argument("NetworkIO not yet implemented"); - - default: - logger->error("❌ Unknown IOType enum value: {}", static_cast(ioType)); - throw std::invalid_argument("Unknown IOType enum value: " + std::to_string(static_cast(ioType))); - } - - logger->debug("🎯 IO type verification: created transport reports type '{}'", - transportToString(io->getType())); - - return io; -} - -std::unique_ptr IOFactory::createFromConfig(const json& config, const std::string& instanceId) { - auto logger = getFactoryLogger(); - logger->info("🌐 IOFactory: Creating from config with instanceId '{}'", instanceId); - logger->trace("📄 Config: {}", config.dump()); - - try { - if (!config.contains("type")) { - logger->error("❌ Config missing 'type' field"); - throw std::invalid_argument("IO config missing 'type' field"); - } - - std::string transportType = config["type"]; - logger->info("📋 Config specifies transport: '{}'", transportType); - - // Get instanceId from config or parameter - std::string actualInstanceId = instanceId; - if (actualInstanceId.empty() && config.contains("instance_id")) { - actualInstanceId = config["instance_id"]; - logger->debug("🔧 Using instanceId from config: '{}'", actualInstanceId); - } - - // Create base IO transport - auto io = create(transportType, actualInstanceId); - auto ioType = io->getType(); - - // Apply transport-specific configuration - if (ioType == IOType::NETWORK) { - if (config.contains("host")) { - std::string host = config["host"]; - logger->info("🔧 Network config: host '{}'", host); - // TODO: Apply host when NetworkIO is implemented - } - - if (config.contains("port")) { - int port = config["port"]; - logger->info("🔧 Network config: port {}", port); - // TODO: Apply port when NetworkIO is implemented - } - - if (config.contains("protocol")) { - std::string protocol = config["protocol"]; - logger->info("🔧 Network config: protocol '{}'", protocol); - // TODO: Apply protocol when NetworkIO is implemented - } - - if (config.contains("timeout")) { - int timeout = config["timeout"]; - logger->info("🔧 Network config: timeout {}ms", timeout); - // TODO: Apply timeout when NetworkIO is implemented - } - } - - if (ioType == IOType::LOCAL) { - if (config.contains("socket_path")) { - std::string socketPath = config["socket_path"]; - logger->info("🔧 Local config: socket path '{}'", socketPath); - // TODO: Apply socket path when LocalIO is implemented - } - } - - if (config.contains("buffer_size")) { - int bufferSize = config["buffer_size"]; - logger->info("🔧 IO config: buffer size {} bytes", bufferSize); - // TODO: Apply buffer size when implementations support it - } - - if (config.contains("compression")) { - bool compression = config["compression"]; - logger->info("🔧 IO config: compression {}", compression ? "enabled" : "disabled"); - // TODO: Apply compression settings when implementations support it - } - - logger->info("✅ IO transport created from config successfully"); - return io; - - } catch (const json::exception& e) { - logger->error("❌ JSON parsing error in config: {}", e.what()); - throw std::invalid_argument("Invalid JSON in IO config: " + std::string(e.what())); - } catch (const std::exception& e) { - logger->error("❌ Error creating IO from config: {}", e.what()); - throw; - } -} - -std::vector IOFactory::getAvailableTransports() { - return { - "intra", - "local", - "network" - }; -} - -bool IOFactory::isTransportSupported(const std::string& transportType) { - try { - parseTransport(transportType); - return true; - } catch (const std::invalid_argument&) { - return false; - } -} - -IOType IOFactory::parseTransport(const std::string& transportStr) { - auto logger = getFactoryLogger(); - std::string lowerTransport = toLowercase(transportStr); - - logger->trace("🔍 Parsing transport: '{}' -> '{}'", transportStr, lowerTransport); - - if (lowerTransport == "intra") { - return IOType::INTRA; - } else if (lowerTransport == "local") { - return IOType::LOCAL; - } else if (lowerTransport == "network" || lowerTransport == "net" || lowerTransport == "tcp") { - return IOType::NETWORK; - } else { - logger->error("❌ Unknown transport: '{}'", transportStr); - auto availableTransports = getAvailableTransports(); - std::string availableStr = "["; - for (size_t i = 0; i < availableTransports.size(); ++i) { - availableStr += availableTransports[i]; - if (i < availableTransports.size() - 1) availableStr += ", "; - } - availableStr += "]"; - - throw std::invalid_argument("Unknown transport '" + transportStr + "'. Available transports: " + availableStr); - } -} - -std::string IOFactory::transportToString(IOType ioType) { - switch (ioType) { - case IOType::INTRA: - return "intra"; - case IOType::LOCAL: - return "local"; - case IOType::NETWORK: - return "network"; - default: - return "unknown"; - } -} - -IOType IOFactory::getRecommendedTransport(int expectedClients, bool distributed, bool development) { - auto logger = getFactoryLogger(); - - logger->debug("🎯 Recommending transport for: {} clients, distributed={}, dev={}", - expectedClients, distributed, development); - - if (development || expectedClients <= 1) { - logger->debug("💡 Development/single-user -> INTRA"); - return IOType::INTRA; - } else if (!distributed && expectedClients <= 10) { - logger->debug("💡 Local deployment, few clients -> LOCAL"); - return IOType::LOCAL; - } else if (distributed || expectedClients > 10) { - logger->debug("💡 Distributed/many clients -> NETWORK"); - return IOType::NETWORK; - } else { - logger->debug("💡 Default fallback -> INTRA"); - return IOType::INTRA; - } -} - -std::unique_ptr IOFactory::createWithEndpoint(const std::string& transportType, const std::string& endpoint, const std::string& instanceId) { - auto logger = getFactoryLogger(); - logger->info("🌐 IOFactory: Creating '{}' with endpoint '{}' and instanceId '{}'", transportType, endpoint, instanceId); - - IOType ioType = parseTransport(transportType); - auto io = create(ioType, instanceId); - - std::string actualEndpoint = endpoint; - if (endpoint.empty()) { - actualEndpoint = generateEndpoint(ioType); - logger->info("🔧 Auto-generated endpoint: '{}'", actualEndpoint); - } - - // TODO: Configure endpoint when implementations support it - logger->debug("🚧 TODO: Configure endpoint '{}' on {} transport", actualEndpoint, transportType); - - return io; -} - -// Private helper methods -std::shared_ptr IOFactory::getFactoryLogger() { - static std::shared_ptr logger = nullptr; - - if (!logger) { - auto console_sink = std::make_shared(); - console_sink->set_level(spdlog::level::debug); - - logger = std::make_shared("IOFactory", console_sink); - logger->set_level(spdlog::level::debug); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - } - - return logger; -} - -std::string IOFactory::toLowercase(const std::string& str) { - std::string result = str; - std::transform(result.begin(), result.end(), result.begin(), - [](char c) { return std::tolower(c); }); - return result; -} - -std::string IOFactory::generateEndpoint(IOType ioType) { - switch (ioType) { - case IOType::INTRA: - return "intra://localhost"; - - case IOType::LOCAL: - return "/tmp/warfactory_" + std::to_string(std::random_device{}()); - - case IOType::NETWORK: { - // Generate random port between 8000-9000 - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(8000, 9000); - return "tcp://localhost:" + std::to_string(dis(gen)); - } - - default: - return "unknown://endpoint"; - } -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/IntraIO.cpp b/core/src/IntraIO.cpp deleted file mode 100644 index 640aa38..0000000 --- a/core/src/IntraIO.cpp +++ /dev/null @@ -1,484 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace warfactory { - -// Factory function for IntraIOManager to avoid circular include -std::shared_ptr createIntraIOInstance(const std::string& instanceId) { - return std::make_shared(instanceId); -} - -IntraIO::IntraIO(const std::string& instanceId) : instanceId(instanceId) { - // Create logger with file and console output - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared("logs/intra_io.log", true); - - console_sink->set_level(spdlog::level::debug); - file_sink->set_level(spdlog::level::trace); - - logger = std::make_shared("IntraIO[" + instanceId + "]", - spdlog::sinks_init_list{console_sink, file_sink}); - logger->set_level(spdlog::level::trace); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - - logIOStart(); - lastHealthCheck = std::chrono::high_resolution_clock::now(); -} - -IntraIO::~IntraIO() { - logger->info("🌐 IntraIO[{}] destructor called", instanceId); - - // Unregister from manager - try { - IntraIOManager::getInstance().removeInstance(instanceId); - } catch (const std::exception& e) { - logger->warn("⚠️ Failed to unregister from manager: {}", e.what()); - } - - auto finalMetrics = getDetailedMetrics(); - logger->info("📊 Final IntraIO[{}] metrics:", instanceId); - logger->info(" Total published: {}", finalMetrics["total_published"]); - logger->info(" Total pulled: {}", finalMetrics["total_pulled"]); - logger->info(" Total dropped: {}", finalMetrics["total_dropped"]); - logger->info(" Final queue size: {}", finalMetrics["queue_size"]); - - logger->trace("🏗️ IntraIO[{}] destroyed", instanceId); -} - -void IntraIO::publish(const std::string& topic, const json& message) { - std::lock_guard lock(operationMutex); - - logPublish(topic, message); - totalPublished++; - - try { - // Route message through manager to all interested instances - IntraIOManager::getInstance().routeMessage(instanceId, topic, message); - logger->trace("📤 Message routed through manager: '{}'", topic); - - } catch (const std::exception& e) { - logger->error("❌ Error publishing message to topic '{}': {}", topic, e.what()); - throw; - } -} - -void IntraIO::subscribe(const std::string& topicPattern, const SubscriptionConfig& config) { - std::lock_guard lock(operationMutex); - - logSubscription(topicPattern, false); - - try { - // Register with manager for routing - IntraIOManager::getInstance().registerSubscription(instanceId, topicPattern, false); - - Subscription sub; - sub.pattern = compileTopicPattern(topicPattern); - sub.originalPattern = topicPattern; - sub.config = config; - sub.lastBatch = std::chrono::high_resolution_clock::now(); - - highFreqSubscriptions.push_back(std::move(sub)); - - logger->info("✅ High-frequency subscription added: '{}'", topicPattern); - logger->debug("🔧 Subscription config: replaceable={}, compress={}", - config.replaceable, config.compress); - - } catch (const std::exception& e) { - logger->error("❌ Error creating subscription for pattern '{}': {}", topicPattern, e.what()); - throw; - } -} - -void IntraIO::subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config) { - std::lock_guard lock(operationMutex); - - logSubscription(topicPattern, true); - - try { - // Register with manager for routing - IntraIOManager::getInstance().registerSubscription(instanceId, topicPattern, true); - - Subscription sub; - sub.pattern = compileTopicPattern(topicPattern); - sub.originalPattern = topicPattern; - sub.config = config; - sub.lastBatch = std::chrono::high_resolution_clock::now(); - - lowFreqSubscriptions.push_back(std::move(sub)); - - logger->info("✅ Low-frequency subscription added: '{}' (interval: {}ms)", - topicPattern, config.batchInterval); - logger->debug("🔧 LowFreq config: replaceable={}, batchSize={}, interval={}ms", - config.replaceable, config.maxBatchSize, config.batchInterval); - - } catch (const std::exception& e) { - logger->error("❌ Error creating low-freq subscription for pattern '{}': {}", topicPattern, e.what()); - throw; - } -} - -int IntraIO::hasMessages() const { - std::lock_guard lock(operationMutex); - - int totalMessages = messageQueue.size() + lowFreqMessageQueue.size(); - - logger->trace("🔍 Messages available: {} (high-freq: {}, low-freq: {})", - totalMessages, messageQueue.size(), lowFreqMessageQueue.size()); - - return totalMessages; -} - -Message IntraIO::pullMessage() { - std::lock_guard lock(operationMutex); - - Message msg; - - // Pull from high-frequency queue first (priority) - if (!messageQueue.empty()) { - msg = messageQueue.front(); - messageQueue.pop(); - logger->trace("📥 Pulled high-frequency message from topic: '{}'", msg.topic); - } else if (!lowFreqMessageQueue.empty()) { - msg = lowFreqMessageQueue.front(); - lowFreqMessageQueue.pop(); - logger->trace("📥 Pulled low-frequency message from topic: '{}'", msg.topic); - } else { - logger->error("❌ No messages available to pull"); - throw std::runtime_error("No messages available in IntraIO"); - } - - totalPulled++; - logPull(msg); - updateHealthMetrics(); - - return msg; -} - -IOHealth IntraIO::getHealth() const { - std::lock_guard lock(operationMutex); - updateHealthMetrics(); - - IOHealth health; - health.queueSize = messageQueue.size() + lowFreqMessageQueue.size(); - health.maxQueueSize = maxQueueSize; - health.dropping = health.queueSize >= maxQueueSize; - health.averageProcessingRate = averageProcessingRate; - health.droppedMessageCount = totalDropped.load(); - - logger->trace("🏥 Health check: queue={}/{}, dropping={}, rate={:.1f}msg/s", - health.queueSize, health.maxQueueSize, health.dropping, health.averageProcessingRate); - - return health; -} - -IOType IntraIO::getType() const { - logger->trace("🏷️ IO type requested: INTRA"); - return IOType::INTRA; -} - -void IntraIO::setMaxQueueSize(size_t maxSize) { - std::lock_guard lock(operationMutex); - - logger->info("🔧 Setting max queue size: {} -> {}", maxQueueSize, maxSize); - maxQueueSize = maxSize; -} - -size_t IntraIO::getMaxQueueSize() const { - return maxQueueSize; -} - -void IntraIO::clearAllMessages() { - std::lock_guard lock(operationMutex); - - size_t clearedCount = messageQueue.size() + lowFreqMessageQueue.size(); - - while (!messageQueue.empty()) messageQueue.pop(); - while (!lowFreqMessageQueue.empty()) lowFreqMessageQueue.pop(); - - logger->info("🧹 Cleared all messages: {} messages removed", clearedCount); -} - -void IntraIO::clearAllSubscriptions() { - std::lock_guard lock(operationMutex); - - size_t clearedCount = highFreqSubscriptions.size() + lowFreqSubscriptions.size(); - - highFreqSubscriptions.clear(); - lowFreqSubscriptions.clear(); - - logger->info("🧹 Cleared all subscriptions: {} subscriptions removed", clearedCount); -} - -json IntraIO::getDetailedMetrics() const { - std::lock_guard lock(operationMutex); - - json metrics = { - {"io_type", "intra"}, - {"queue_size", messageQueue.size() + lowFreqMessageQueue.size()}, - {"high_freq_queue_size", messageQueue.size()}, - {"low_freq_queue_size", lowFreqMessageQueue.size()}, - {"max_queue_size", maxQueueSize}, - {"total_published", totalPublished.load()}, - {"total_pulled", totalPulled.load()}, - {"total_dropped", totalDropped.load()}, - {"high_freq_subscriptions", highFreqSubscriptions.size()}, - {"low_freq_subscriptions", lowFreqSubscriptions.size()}, - {"average_processing_rate", averageProcessingRate} - }; - - logger->trace("📊 Detailed metrics: {}", metrics.dump()); - return metrics; -} - -void IntraIO::setLogLevel(spdlog::level::level_enum level) { - logger->info("🔧 Setting log level to: {}", spdlog::level::to_string_view(level)); - logger->set_level(level); -} - -size_t IntraIO::getSubscriptionCount() const { - std::lock_guard lock(operationMutex); - return highFreqSubscriptions.size() + lowFreqSubscriptions.size(); -} - -std::vector IntraIO::getActiveTopics() const { - std::lock_guard lock(operationMutex); - - std::unordered_set topicSet; - std::queue tempQueue = messageQueue; - - while (!tempQueue.empty()) { - topicSet.insert(tempQueue.front().topic); - tempQueue.pop(); - } - - tempQueue = lowFreqMessageQueue; - while (!tempQueue.empty()) { - topicSet.insert(tempQueue.front().topic); - tempQueue.pop(); - } - - return std::vector(topicSet.begin(), topicSet.end()); -} - -void IntraIO::simulateHighLoad(int messageCount, const std::string& topicPrefix) { - logger->info("🧪 Simulating high load: {} messages with prefix '{}'", messageCount, topicPrefix); - - for (int i = 0; i < messageCount; ++i) { - json testMessage = { - {"test_id", i}, - {"payload", "test_data_" + std::to_string(i)}, - {"timestamp", std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count()} - }; - - publish(topicPrefix + ":" + std::to_string(i), testMessage); - } - - logger->info("✅ High load simulation completed"); -} - -void IntraIO::forceProcessLowFreqBatches() { - std::lock_guard lock(operationMutex); - logger->debug("🔧 Force processing all low-frequency batches"); - - for (auto& sub : lowFreqSubscriptions) { - flushBatchedMessages(sub); - } -} - -// Private helper methods -void IntraIO::logIOStart() { - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🌐 INTRA-PROCESS IO INITIALIZED"); - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🎯 Transport Type: INTRA (Same-process)"); - logger->info("🔧 Features: Direct function calls, zero latency"); - logger->info("📊 Performance: ~10-50ns publish, thread-safe"); - logger->info("🔧 Max queue size: {}", maxQueueSize); - logger->trace("🏗️ IntraIO object created at: {}", static_cast(this)); -} - -bool IntraIO::matchesPattern(const std::string& topic, const std::regex& pattern) const { - return std::regex_match(topic, pattern); -} - -std::regex IntraIO::compileTopicPattern(const std::string& pattern) const { - // Convert wildcard pattern to regex - std::string regexPattern = pattern; - - // Escape special regex characters except our wildcards - std::string specialChars = ".^$+()[]{}|\\"; - for (char c : specialChars) { - std::string from = std::string(1, c); - std::string to = "\\" + from; - - size_t pos = 0; - while ((pos = regexPattern.find(from, pos)) != std::string::npos) { - regexPattern.replace(pos, 1, to); - pos += 2; - } - } - - // Convert * to regex equivalent - size_t pos2 = 0; - while ((pos2 = regexPattern.find("*", pos2)) != std::string::npos) { - regexPattern.replace(pos2, 1, ".*"); - pos2 += 2; - } - - logger->trace("🔍 Compiled pattern '{}' -> '{}'", pattern, regexPattern); - - return std::regex(regexPattern); -} - -void IntraIO::processLowFreqSubscriptions() { - auto currentTime = std::chrono::high_resolution_clock::now(); - - for (auto& sub : lowFreqSubscriptions) { - auto elapsed = std::chrono::duration_cast( - currentTime - sub.lastBatch).count(); - - if (elapsed >= sub.config.batchInterval) { - logger->trace("⏰ Processing low-freq batch for pattern '{}' ({}ms elapsed)", - sub.originalPattern, elapsed); - flushBatchedMessages(sub); - sub.lastBatch = currentTime; - } - } -} - -void IntraIO::flushBatchedMessages(Subscription& sub) { - size_t flushedCount = 0; - - // Flush replaceable messages (latest only) - for (auto& [topic, message] : sub.batchedMessages) { - lowFreqMessageQueue.push(message); - flushedCount++; - logger->trace("📤 Flushed replaceable message: topic '{}', data size {}", - topic, message.data.dump().size()); - } - sub.batchedMessages.clear(); - - // Flush accumulated messages (all) - for (const auto& message : sub.accumulatedMessages) { - lowFreqMessageQueue.push(message); - flushedCount++; - logger->trace("📤 Flushed accumulated message: topic '{}', data size {}", - message.topic, message.data.dump().size()); - } - sub.accumulatedMessages.clear(); - - if (flushedCount > 0) { - logger->debug("📦 Flushed {} low-freq messages for pattern '{}'", - flushedCount, sub.originalPattern); - } -} - -void IntraIO::updateHealthMetrics() const { - auto currentTime = std::chrono::high_resolution_clock::now(); - auto elapsed = std::chrono::duration(currentTime - lastHealthCheck).count(); - - if (elapsed >= 1.0f) { // Update every second - size_t currentPulled = totalPulled.load(); - static size_t lastPulledCount = 0; - - averageProcessingRate = (currentPulled - lastPulledCount) / elapsed; - lastPulledCount = currentPulled; - lastHealthCheck = currentTime; - - logger->trace("📊 Health metrics updated: rate={:.1f}msg/s", averageProcessingRate); - } -} - -void IntraIO::enforceQueueLimits() { - size_t totalSize = messageQueue.size() + lowFreqMessageQueue.size(); - - if (totalSize >= maxQueueSize) { - logger->warn("⚠️ Queue size limit reached: {}/{} - dropping oldest messages", totalSize, maxQueueSize); - - // Drop oldest messages to make room - size_t toDrop = totalSize - maxQueueSize + 1; - - for (size_t i = 0; i < toDrop && !messageQueue.empty(); ++i) { - messageQueue.pop(); - totalDropped++; - } - - logger->warn("🗑️ Dropped {} messages to enforce queue limit", toDrop); - } -} - -void IntraIO::logPublish(const std::string& topic, const json& message) const { - logger->trace("📡 Publishing to topic '{}', data size: {} bytes", - topic, message.dump().size()); -} - -void IntraIO::logSubscription(const std::string& pattern, bool isLowFreq) const { - logger->debug("📨 {} subscription request: pattern '{}'", - isLowFreq ? "Low-frequency" : "High-frequency", pattern); -} - -void IntraIO::logPull(const Message& message) const { - logger->trace("📥 Message pulled: topic '{}', timestamp {}, data size {} bytes", - message.topic, message.timestamp, message.data.dump().size()); -} - -void IntraIO::deliverMessage(const std::string& topic, const json& message, bool isLowFreq) { - std::lock_guard lock(operationMutex); - - auto timestamp = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count(); - - Message msg{topic, message, static_cast(timestamp)}; - - try { - if (isLowFreq) { - // Handle low-frequency message delivery - for (auto& sub : lowFreqSubscriptions) { - if (matchesPattern(topic, sub.pattern)) { - if (sub.config.replaceable) { - sub.batchedMessages[topic] = msg; - logger->trace("🔄 Low-freq replaceable message delivered: '{}'", topic); - } else { - sub.accumulatedMessages.push_back(msg); - logger->trace("📚 Low-freq message accumulated: '{}'", topic); - } - break; - } - } - } else { - // Handle high-frequency message delivery - logger->info("🔍 deliverMessage: looking for high-freq subscriptions for '{}', have {} subs", topic, highFreqSubscriptions.size()); - for (const auto& sub : highFreqSubscriptions) { - logger->info("🔍 deliverMessage: testing pattern '{}' vs topic '{}'", sub.originalPattern, topic); - if (matchesPattern(topic, sub.pattern)) { - messageQueue.push(msg); - logger->info("📨 High-freq message delivered to queue: '{}'", topic); - break; - } else { - logger->info("❌ Pattern '{}' did not match topic '{}'", sub.originalPattern, topic); - } - } - } - - // Enforce queue limits - enforceQueueLimits(); - - } catch (const std::exception& e) { - logger->error("❌ Error delivering message to topic '{}': {}", topic, e.what()); - throw; - } -} - -const std::string& IntraIO::getInstanceId() const { - return instanceId; -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/IntraIOManager.cpp b/core/src/IntraIOManager.cpp deleted file mode 100644 index ebfd646..0000000 --- a/core/src/IntraIOManager.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include - -namespace warfactory { - -IntraIOManager::IntraIOManager() { - // Create logger - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared("logs/intra_io_manager.log", true); - - console_sink->set_level(spdlog::level::debug); - file_sink->set_level(spdlog::level::trace); - - logger = std::make_shared("IntraIOManager", - spdlog::sinks_init_list{console_sink, file_sink}); - logger->set_level(spdlog::level::trace); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - - logger->info("🌐🔗 IntraIOManager created - Central message router initialized"); -} - -IntraIOManager::~IntraIOManager() { - std::lock_guard lock(managerMutex); - - auto stats = getRoutingStats(); - logger->info("📊 Final routing stats:"); - logger->info(" Total routed messages: {}", stats["total_routed_messages"]); - logger->info(" Total routes: {}", stats["total_routes"]); - logger->info(" Active instances: {}", stats["active_instances"]); - - instances.clear(); - routingTable.clear(); - - logger->info("🌐🔗 IntraIOManager destroyed"); -} - -std::shared_ptr IntraIOManager::createInstance(const std::string& instanceId) { - std::lock_guard lock(managerMutex); - - auto it = instances.find(instanceId); - if (it != instances.end()) { - logger->warn("⚠️ Instance '{}' already exists, returning existing", instanceId); - // Need to cast back to IntraIO - return std::static_pointer_cast(it->second); - } - - // Create new IntraIO instance via factory function - auto instance = createIntraIOInstance(instanceId); - instances[instanceId] = instance; - - logger->info("✅ Created IntraIO instance: '{}'", instanceId); - logger->debug("📊 Total instances: {}", instances.size()); - - return instance; -} - -void IntraIOManager::registerInstance(const std::string& instanceId, std::shared_ptr instance) { - std::lock_guard lock(managerMutex); - instances[instanceId] = instance; - logger->info("📋 Registered instance: '{}'", instanceId); -} - -void IntraIOManager::removeInstance(const std::string& instanceId) { - std::lock_guard lock(managerMutex); - - auto it = instances.find(instanceId); - if (it == instances.end()) { - logger->warn("⚠️ Instance '{}' not found for removal", instanceId); - return; - } - - // Remove all routing entries for this instance - routingTable.erase( - std::remove_if(routingTable.begin(), routingTable.end(), - [&instanceId](const RouteEntry& entry) { - return entry.instanceId == instanceId; - }), - routingTable.end() - ); - - instances.erase(it); - - logger->info("🗑️ Removed IntraIO instance: '{}'", instanceId); - logger->debug("📊 Remaining instances: {}", instances.size()); -} - -std::shared_ptr IntraIOManager::getInstance(const std::string& instanceId) const { - std::lock_guard lock(managerMutex); - - auto it = instances.find(instanceId); - if (it != instances.end()) { - return std::static_pointer_cast(it->second); - } - return nullptr; -} - -void IntraIOManager::routeMessage(const std::string& sourceId, const std::string& topic, const json& message) { - std::lock_guard lock(managerMutex); - - totalRoutedMessages++; - size_t deliveredCount = 0; - - logger->info("📨 Routing message: {} → '{}'", sourceId, topic); - - // Find all matching routes - for (const auto& route : routingTable) { - // Don't deliver back to sender - if (route.instanceId == sourceId) { - continue; - } - - // Check pattern match - logger->info(" 🔍 Testing pattern '{}' against topic '{}'", route.originalPattern, topic); - if (std::regex_match(topic, route.pattern)) { - auto targetInstance = instances.find(route.instanceId); - if (targetInstance != instances.end()) { - // Direct delivery to target instance's queue - targetInstance->second->deliverMessage(topic, message, route.isLowFreq); - deliveredCount++; - logger->info(" ↪️ Delivered to '{}' ({})", - route.instanceId, - route.isLowFreq ? "low-freq" : "high-freq"); - } else { - logger->warn("⚠️ Target instance '{}' not found for route", route.instanceId); - } - } else { - logger->info(" ❌ Pattern '{}' did not match topic '{}'", route.originalPattern, topic); - } - } - - if (deliveredCount > 0) { - logger->debug("📤 Message '{}' delivered to {} instances", topic, deliveredCount); - } else { - logger->trace("📪 No subscribers for topic '{}'", topic); - } -} - -void IntraIOManager::registerSubscription(const std::string& instanceId, const std::string& pattern, bool isLowFreq) { - std::lock_guard lock(managerMutex); - - try { - // Convert topic pattern to regex - use same logic as IntraIO - std::string regexPattern = pattern; - - // Escape special regex characters except our wildcards (: is NOT special) - std::string specialChars = ".^$+()[]{}|\\"; - for (char c : specialChars) { - std::string from = std::string(1, c); - std::string to = "\\" + from; - - size_t pos = 0; - while ((pos = regexPattern.find(from, pos)) != std::string::npos) { - regexPattern.replace(pos, 1, to); - pos += 2; - } - } - - // Convert * to regex equivalent - size_t pos2 = 0; - while ((pos2 = regexPattern.find("*", pos2)) != std::string::npos) { - regexPattern.replace(pos2, 1, ".*"); - pos2 += 2; - } - - logger->info("🔍 Pattern conversion: '{}' → '{}'", pattern, regexPattern); - - RouteEntry entry; - entry.instanceId = instanceId; - entry.pattern = std::regex(regexPattern); - entry.originalPattern = pattern; - entry.isLowFreq = isLowFreq; - - routingTable.push_back(entry); - totalRoutes++; - - logger->info("📋 Registered subscription: '{}' → '{}' ({})", - instanceId, pattern, isLowFreq ? "low-freq" : "high-freq"); - logger->debug("📊 Total routes: {}", routingTable.size()); - - } catch (const std::exception& e) { - logger->error("❌ Failed to register subscription '{}' for '{}': {}", - pattern, instanceId, e.what()); - throw; - } -} - -void IntraIOManager::unregisterSubscription(const std::string& instanceId, const std::string& pattern) { - std::lock_guard lock(managerMutex); - - auto oldSize = routingTable.size(); - routingTable.erase( - std::remove_if(routingTable.begin(), routingTable.end(), - [&instanceId, &pattern](const RouteEntry& entry) { - return entry.instanceId == instanceId && entry.originalPattern == pattern; - }), - routingTable.end() - ); - - auto removed = oldSize - routingTable.size(); - if (removed > 0) { - logger->info("🗑️ Unregistered {} subscription(s): '{}' → '{}'", removed, instanceId, pattern); - } else { - logger->warn("⚠️ Subscription not found for removal: '{}' → '{}'", instanceId, pattern); - } -} - -void IntraIOManager::clearAllRoutes() { - std::lock_guard lock(managerMutex); - - auto clearedCount = routingTable.size(); - routingTable.clear(); - - logger->info("🧹 Cleared {} routing entries", clearedCount); -} - -size_t IntraIOManager::getInstanceCount() const { - std::lock_guard lock(managerMutex); - return instances.size(); -} - -std::vector IntraIOManager::getInstanceIds() const { - std::lock_guard lock(managerMutex); - - std::vector ids; - for (const auto& pair : instances) { - ids.push_back(pair.first); - } - return ids; -} - -json IntraIOManager::getRoutingStats() const { - std::lock_guard lock(managerMutex); - - json stats; - stats["total_routed_messages"] = totalRoutedMessages.load(); - stats["total_routes"] = totalRoutes.load(); - stats["active_instances"] = instances.size(); - stats["routing_entries"] = routingTable.size(); - - // Instance details - json instanceDetails = json::object(); - for (const auto& pair : instances) { - instanceDetails[pair.first] = { - {"active", true}, - {"type", "IntraIO"} - }; - } - stats["instances"] = instanceDetails; - - return stats; -} - -void IntraIOManager::setLogLevel(spdlog::level::level_enum level) { - logger->set_level(level); - logger->info("📝 Log level set to: {}", spdlog::level::to_string_view(level)); -} - -// Singleton implementation -IntraIOManager& IntraIOManager::getInstance() { - static IntraIOManager instance; - return instance; -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/ModuleFactory.cpp b/core/src/ModuleFactory.cpp deleted file mode 100644 index dfe54db..0000000 --- a/core/src/ModuleFactory.cpp +++ /dev/null @@ -1,509 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; - -namespace warfactory { - -ModuleFactory::ModuleFactory() { - // Create logger with file and console output - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared("logs/module_factory.log", true); - - console_sink->set_level(spdlog::level::info); - file_sink->set_level(spdlog::level::trace); - - logger = std::make_shared("ModuleFactory", - spdlog::sinks_init_list{console_sink, file_sink}); - logger->set_level(spdlog::level::trace); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🏭 MODULE FACTORY INITIALIZED"); - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🔧 Dynamic module loading with dlopen/dlsym"); - logger->info("🔥 Hot-reload support available"); - logger->info("📁 Default modules directory: ./modules/"); - - modulesDirectory = "./modules/"; -} - -ModuleFactory::~ModuleFactory() { - logger->info("🏭 ModuleFactory destructor called"); - unloadAllModules(); - logger->trace("🏗️ ModuleFactory destroyed"); -} - -std::unique_ptr ModuleFactory::loadModule(const std::string& modulePath) { - logger->info("🏭 Loading module from path: '{}'", modulePath); - - if (!fs::exists(modulePath)) { - logger->error("❌ Module file not found: '{}'", modulePath); - throw std::runtime_error("Module file not found: " + modulePath); - } - - if (!isValidModuleFile(modulePath)) { - logger->error("❌ Invalid module file: '{}'", modulePath); - throw std::runtime_error("Invalid module file: " + modulePath); - } - - ModuleInfo info; - info.path = modulePath; - - try { - if (!loadSharedLibrary(modulePath, info)) { - logger->error("❌ Failed to load shared library: '{}'", modulePath); - throw std::runtime_error("Failed to load shared library: " + modulePath); - } - - if (!resolveSymbols(info)) { - logger->error("❌ Failed to resolve symbols: '{}'", modulePath); - unloadSharedLibrary(info); - throw std::runtime_error("Failed to resolve symbols: " + modulePath); - } - - // Create module instance - auto module = std::unique_ptr(info.createFunc()); - if (!module) { - logger->error("❌ Module creation function returned nullptr: '{}'", modulePath); - unloadSharedLibrary(info); - throw std::runtime_error("Module creation failed: " + modulePath); - } - - // Verify module type consistency - std::string actualType = module->getType(); - if (actualType != info.type) { - logger->warn("⚠️ Module type mismatch: expected '{}', got '{}'", info.type, actualType); - } - - // Register loaded module - loadedModules[info.type] = info; - availableModules[info.type] = modulePath; - - logModuleLoad(info.type, modulePath); - logger->info("✅ Module '{}' loaded successfully from '{}'", info.type, modulePath); - - return module; - - } catch (const std::exception& e) { - logModuleError("load", e.what()); - unloadSharedLibrary(info); - throw; - } -} - -std::unique_ptr ModuleFactory::createModule(const std::string& moduleType) { - logger->info("🏭 Creating module of type: '{}'", moduleType); - - auto it = availableModules.find(moduleType); - if (it == availableModules.end()) { - logger->error("❌ Module type '{}' not available", moduleType); - - auto available = getAvailableModules(); - std::string availableStr = "["; - for (size_t i = 0; i < available.size(); ++i) { - availableStr += available[i]; - if (i < available.size() - 1) availableStr += ", "; - } - availableStr += "]"; - - throw std::invalid_argument("Module type '" + moduleType + "' not available. Available: " + availableStr); - } - - return loadModule(it->second); -} - -void ModuleFactory::scanModulesDirectory(const std::string& directory) { - logger->info("🔍 Scanning modules directory: '{}'", directory); - - if (!fs::exists(directory) || !fs::is_directory(directory)) { - logger->warn("⚠️ Modules directory does not exist: '{}'", directory); - return; - } - - size_t foundCount = 0; - - for (const auto& entry : fs::directory_iterator(directory)) { - if (entry.is_regular_file() && isValidModuleFile(entry.path().string())) { - try { - registerModule(entry.path().string()); - foundCount++; - } catch (const std::exception& e) { - logger->warn("⚠️ Failed to register module '{}': {}", entry.path().string(), e.what()); - } - } - } - - logger->info("✅ Scan complete: {} modules found in '{}'", foundCount, directory); -} - -void ModuleFactory::registerModule(const std::string& modulePath) { - logger->debug("📝 Registering module: '{}'", modulePath); - - if (!fs::exists(modulePath)) { - throw std::runtime_error("Module file not found: " + modulePath); - } - - if (!isValidModuleFile(modulePath)) { - throw std::runtime_error("Invalid module file: " + modulePath); - } - - // Extract module type from the path for registration - std::string moduleType = extractModuleTypeFromPath(modulePath); - - // Quick validation - try to load and get type - ModuleInfo tempInfo; - tempInfo.path = modulePath; - - if (loadSharedLibrary(modulePath, tempInfo)) { - if (resolveSymbols(tempInfo)) { - // Get the actual type from the module - typedef const char* (*GetTypeFunc)(); - auto getTypeFunc = (GetTypeFunc)dlsym(tempInfo.handle, "get_module_type"); - if (getTypeFunc) { - moduleType = getTypeFunc(); - } - } - unloadSharedLibrary(tempInfo); - } - - availableModules[moduleType] = modulePath; - logger->debug("✅ Module '{}' registered from '{}'", moduleType, modulePath); -} - -void ModuleFactory::unloadModule(const std::string& moduleType) { - logger->info("🗑️ Unloading module: '{}'", moduleType); - - auto it = loadedModules.find(moduleType); - if (it == loadedModules.end()) { - logger->warn("⚠️ Module '{}' is not loaded", moduleType); - return; - } - - unloadSharedLibrary(it->second); - loadedModules.erase(it); - - logModuleUnload(moduleType); - logger->info("✅ Module '{}' unloaded successfully", moduleType); -} - -void ModuleFactory::unloadAllModules() { - logger->info("🗑️ Unloading all modules ({} loaded)", loadedModules.size()); - - for (auto& [type, info] : loadedModules) { - logger->debug("🗑️ Unloading module: '{}'", type); - unloadSharedLibrary(info); - } - - loadedModules.clear(); - logger->info("✅ All modules unloaded"); -} - -std::vector ModuleFactory::getAvailableModules() const { - std::vector modules; - modules.reserve(availableModules.size()); - - for (const auto& [type, path] : availableModules) { - modules.push_back(type); - } - - std::sort(modules.begin(), modules.end()); - return modules; -} - -std::vector ModuleFactory::getLoadedModules() const { - std::vector modules; - modules.reserve(loadedModules.size()); - - for (const auto& [type, info] : loadedModules) { - modules.push_back(type); - } - - std::sort(modules.begin(), modules.end()); - return modules; -} - -ModuleFactory::ModuleInfo ModuleFactory::getModuleInfo(const std::string& moduleType) const { - auto it = loadedModules.find(moduleType); - if (it != loadedModules.end()) { - return it->second; - } - - // Return empty info if not loaded - return ModuleInfo{}; -} - -bool ModuleFactory::isModuleLoaded(const std::string& moduleType) const { - return loadedModules.find(moduleType) != loadedModules.end(); -} - -bool ModuleFactory::isModuleAvailable(const std::string& moduleType) const { - return availableModules.find(moduleType) != availableModules.end(); -} - -void ModuleFactory::setModulesDirectory(const std::string& directory) { - logger->info("📁 Setting modules directory: '{}'", directory); - modulesDirectory = directory; - - // Auto-scan new directory - if (fs::exists(directory)) { - scanModulesDirectory(directory); - } -} - -std::string ModuleFactory::getModulesDirectory() const { - return modulesDirectory; -} - -bool ModuleFactory::reloadModule(const std::string& moduleType) { - logger->info("🔄 Reloading module: '{}'", moduleType); - - if (!hotReloadEnabled) { - logger->warn("⚠️ Hot-reload is disabled"); - return false; - } - - auto it = loadedModules.find(moduleType); - if (it == loadedModules.end()) { - logger->warn("⚠️ Module '{}' is not loaded, cannot reload", moduleType); - return false; - } - - std::string modulePath = it->second.path; - - try { - unloadModule(moduleType); - auto reloadedModule = loadModule(modulePath); - - logger->info("✅ Module '{}' reloaded successfully", moduleType); - return true; - - } catch (const std::exception& e) { - logger->error("❌ Failed to reload module '{}': {}", moduleType, e.what()); - return false; - } -} - -void ModuleFactory::enableHotReload(bool enable) { - logger->info("🔧 Hot-reload {}", enable ? "enabled" : "disabled"); - hotReloadEnabled = enable; -} - -bool ModuleFactory::isHotReloadEnabled() const { - return hotReloadEnabled; -} - -json ModuleFactory::getDetailedStatus() const { - json status = { - {"modules_directory", modulesDirectory}, - {"hot_reload_enabled", hotReloadEnabled}, - {"available_modules_count", availableModules.size()}, - {"loaded_modules_count", loadedModules.size()} - }; - - json availableList = json::array(); - for (const auto& [type, path] : availableModules) { - availableList.push_back({ - {"type", type}, - {"path", path} - }); - } - status["available_modules"] = availableList; - - json loadedList = json::array(); - for (const auto& [type, info] : loadedModules) { - loadedList.push_back({ - {"type", type}, - {"path", info.path}, - {"version", info.version}, - {"handle", reinterpret_cast(info.handle)} - }); - } - status["loaded_modules"] = loadedList; - - return status; -} - -void ModuleFactory::validateModule(const std::string& modulePath) { - logger->info("🔍 Validating module: '{}'", modulePath); - - if (!fs::exists(modulePath)) { - throw std::runtime_error("Module file not found: " + modulePath); - } - - if (!isValidModuleFile(modulePath)) { - throw std::runtime_error("Invalid module file extension: " + modulePath); - } - - ModuleInfo tempInfo; - tempInfo.path = modulePath; - - if (!loadSharedLibrary(modulePath, tempInfo)) { - throw std::runtime_error("Failed to load shared library: " + modulePath); - } - - if (!resolveSymbols(tempInfo)) { - unloadSharedLibrary(tempInfo); - throw std::runtime_error("Failed to resolve required symbols: " + modulePath); - } - - // Test module creation - auto testModule = std::unique_ptr(tempInfo.createFunc()); - if (!testModule) { - unloadSharedLibrary(tempInfo); - throw std::runtime_error("Module creation function returned nullptr"); - } - - // Test module type - std::string moduleType = testModule->getType(); - if (moduleType.empty()) { - tempInfo.destroyFunc(testModule.release()); - unloadSharedLibrary(tempInfo); - throw std::runtime_error("Module getType() returned empty string"); - } - - // Cleanup - tempInfo.destroyFunc(testModule.release()); - unloadSharedLibrary(tempInfo); - - logger->info("✅ Module validation passed: '{}' (type: '{}')", modulePath, moduleType); -} - -void ModuleFactory::setLogLevel(spdlog::level::level_enum level) { - logger->info("🔧 Setting log level to: {}", spdlog::level::to_string_view(level)); - logger->set_level(level); -} - -// Private helper methods -std::shared_ptr ModuleFactory::getFactoryLogger() { - return logger; -} - -bool ModuleFactory::loadSharedLibrary(const std::string& path, ModuleInfo& info) { - logger->trace("📚 Loading shared library: '{}'", path); - - // Clear any existing error - dlerror(); - - // Load the shared library - info.handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); - if (!info.handle) { - const char* error = dlerror(); - logger->error("❌ dlopen failed for '{}': {}", path, error ? error : "unknown error"); - return false; - } - - logger->trace("✅ Shared library loaded: '{}'", path); - return true; -} - -void ModuleFactory::unloadSharedLibrary(ModuleInfo& info) { - if (info.handle) { - logger->trace("🗑️ Unloading shared library: '{}'", info.path); - - int result = dlclose(info.handle); - if (result != 0) { - const char* error = dlerror(); - logger->warn("⚠️ dlclose warning for '{}': {}", info.path, error ? error : "unknown error"); - } - - info.handle = nullptr; - info.createFunc = nullptr; - info.destroyFunc = nullptr; - } -} - -bool ModuleFactory::resolveSymbols(ModuleInfo& info) { - logger->trace("🔍 Resolving symbols for: '{}'", info.path); - - // Clear any existing error - dlerror(); - - // Resolve create_module function - typedef IModule* (*CreateFunc)(); - auto createFunc = (CreateFunc)dlsym(info.handle, "create_module"); - const char* error = dlerror(); - if (error || !createFunc) { - logger->error("❌ Failed to resolve 'create_module': {}", error ? error : "symbol not found"); - return false; - } - info.createFunc = createFunc; - - // Resolve destroy_module function - typedef void (*DestroyFunc)(IModule*); - auto destroyFunc = (DestroyFunc)dlsym(info.handle, "destroy_module"); - error = dlerror(); - if (error || !destroyFunc) { - logger->error("❌ Failed to resolve 'destroy_module': {}", error ? error : "symbol not found"); - return false; - } - info.destroyFunc = destroyFunc; - - // Resolve get_module_type function - typedef const char* (*GetTypeFunc)(); - auto getTypeFunc = (GetTypeFunc)dlsym(info.handle, "get_module_type"); - error = dlerror(); - if (error || !getTypeFunc) { - logger->error("❌ Failed to resolve 'get_module_type': {}", error ? error : "symbol not found"); - return false; - } - info.type = getTypeFunc(); - - // Resolve get_module_version function - typedef const char* (*GetVersionFunc)(); - auto getVersionFunc = (GetVersionFunc)dlsym(info.handle, "get_module_version"); - error = dlerror(); - if (error || !getVersionFunc) { - logger->warn("⚠️ Failed to resolve 'get_module_version': {}", error ? error : "symbol not found"); - info.version = "unknown"; - } else { - info.version = getVersionFunc(); - } - - logger->trace("✅ All symbols resolved for '{}' (type: '{}', version: '{}')", - info.path, info.type, info.version); - return true; -} - -std::string ModuleFactory::extractModuleTypeFromPath(const std::string& path) const { - fs::path p(path); - std::string filename = p.stem().string(); // Remove extension - - // Remove common prefixes - if (filename.find("lib") == 0) { - filename = filename.substr(3); - } - if (filename.find("warfactory-") == 0) { - filename = filename.substr(11); - } - - return filename; -} - -bool ModuleFactory::isValidModuleFile(const std::string& path) const { - fs::path p(path); - std::string extension = p.extension().string(); - - // Check for valid shared library extensions - return extension == ".so" || extension == ".dylib" || extension == ".dll"; -} - -void ModuleFactory::logModuleLoad(const std::string& type, const std::string& path) const { - logger->debug("📦 Module loaded: type='{}', path='{}'", type, path); -} - -void ModuleFactory::logModuleUnload(const std::string& type) const { - logger->debug("📤 Module unloaded: type='{}'", type); -} - -void ModuleFactory::logModuleError(const std::string& operation, const std::string& details) const { - logger->error("❌ Module {} error: {}", operation, details); -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/ModuleSystemFactory.cpp b/core/src/ModuleSystemFactory.cpp deleted file mode 100644 index 1f63220..0000000 --- a/core/src/ModuleSystemFactory.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include -#include -#include -#include - -// Include implemented systems -#include -// Forward declarations for future implementations -// #include "ThreadedModuleSystem.h" -// #include "ThreadPoolModuleSystem.h" -// #include "ClusterModuleSystem.h" - -namespace warfactory { - -std::unique_ptr ModuleSystemFactory::create(const std::string& strategy) { - auto logger = getFactoryLogger(); - logger->info("⚙️ ModuleSystemFactory: Creating strategy '{}'", strategy); - - ModuleSystemType type = parseStrategy(strategy); - return create(type); -} - -std::unique_ptr ModuleSystemFactory::create(ModuleSystemType systemType) { - auto logger = getFactoryLogger(); - std::string typeStr = strategyToString(systemType); - logger->info("⚙️ ModuleSystemFactory: Creating enum type '{}'", typeStr); - - std::unique_ptr moduleSystem; - - switch (systemType) { - case ModuleSystemType::SEQUENTIAL: - logger->debug("🔧 Creating SequentialModuleSystem instance"); - moduleSystem = std::make_unique(); - logger->info("✅ SequentialModuleSystem created successfully"); - break; - - case ModuleSystemType::THREADED: - logger->debug("🔧 Creating ThreadedModuleSystem instance"); - // TODO: Implement ThreadedModuleSystem - // moduleSystem = std::make_unique(); - logger->error("❌ ThreadedModuleSystem not yet implemented"); - throw std::invalid_argument("ThreadedModuleSystem not yet implemented"); - - case ModuleSystemType::THREAD_POOL: - logger->debug("🔧 Creating ThreadPoolModuleSystem instance"); - // TODO: Implement ThreadPoolModuleSystem - // moduleSystem = std::make_unique(); - logger->error("❌ ThreadPoolModuleSystem not yet implemented"); - throw std::invalid_argument("ThreadPoolModuleSystem not yet implemented"); - - case ModuleSystemType::CLUSTER: - logger->debug("🔧 Creating ClusterModuleSystem instance"); - // TODO: Implement ClusterModuleSystem - // moduleSystem = std::make_unique(); - logger->error("❌ ClusterModuleSystem not yet implemented"); - throw std::invalid_argument("ClusterModuleSystem not yet implemented"); - - default: - logger->error("❌ Unknown ModuleSystemType enum value: {}", static_cast(systemType)); - throw std::invalid_argument("Unknown ModuleSystemType enum value: " + std::to_string(static_cast(systemType))); - } - - logger->debug("🎯 ModuleSystem type verification: created system reports type '{}'", - strategyToString(moduleSystem->getType())); - - return moduleSystem; -} - -std::unique_ptr ModuleSystemFactory::createFromConfig(const json& config) { - auto logger = getFactoryLogger(); - logger->info("⚙️ ModuleSystemFactory: Creating from config"); - logger->trace("📄 Config: {}", config.dump()); - - try { - if (!config.contains("strategy")) { - logger->error("❌ Config missing 'strategy' field"); - throw std::invalid_argument("ModuleSystem config missing 'strategy' field"); - } - - std::string strategy = config["strategy"]; - logger->info("📋 Config specifies strategy: '{}'", strategy); - - // Create base ModuleSystem - auto moduleSystem = create(strategy); - - // Apply additional configuration based on strategy type - auto systemType = moduleSystem->getType(); - - if (systemType == ModuleSystemType::THREAD_POOL) { - if (config.contains("thread_count")) { - int threadCount = config["thread_count"]; - logger->info("🔧 Thread pool config: {} threads", threadCount); - // TODO: Apply thread count when ThreadPoolModuleSystem is implemented - } - - if (config.contains("queue_size")) { - int queueSize = config["queue_size"]; - logger->info("🔧 Thread pool config: queue size {}", queueSize); - // TODO: Apply queue size when ThreadPoolModuleSystem is implemented - } - } - - if (config.contains("priority")) { - std::string priority = config["priority"]; - logger->info("🔧 ModuleSystem priority: {}", priority); - // TODO: Apply priority settings when implementations support it - } - - logger->info("✅ ModuleSystem created from config successfully"); - return moduleSystem; - - } catch (const json::exception& e) { - logger->error("❌ JSON parsing error in config: {}", e.what()); - throw std::invalid_argument("Invalid JSON in ModuleSystem config: " + std::string(e.what())); - } catch (const std::exception& e) { - logger->error("❌ Error creating ModuleSystem from config: {}", e.what()); - throw; - } -} - -std::vector ModuleSystemFactory::getAvailableStrategies() { - return { - "sequential", - "threaded", - "thread_pool", - "cluster" - }; -} - -bool ModuleSystemFactory::isStrategySupported(const std::string& strategy) { - try { - parseStrategy(strategy); - return true; - } catch (const std::invalid_argument&) { - return false; - } -} - -ModuleSystemType ModuleSystemFactory::parseStrategy(const std::string& strategyStr) { - auto logger = getFactoryLogger(); - std::string lowerStrategy = toLowercase(strategyStr); - - logger->trace("🔍 Parsing strategy: '{}' -> '{}'", strategyStr, lowerStrategy); - - if (lowerStrategy == "sequential") { - return ModuleSystemType::SEQUENTIAL; - } else if (lowerStrategy == "threaded") { - return ModuleSystemType::THREADED; - } else if (lowerStrategy == "thread_pool" || lowerStrategy == "threadpool" || lowerStrategy == "thread-pool") { - return ModuleSystemType::THREAD_POOL; - } else if (lowerStrategy == "cluster") { - return ModuleSystemType::CLUSTER; - } else { - logger->error("❌ Unknown strategy: '{}'", strategyStr); - auto availableStrategies = getAvailableStrategies(); - std::string availableStr = "["; - for (size_t i = 0; i < availableStrategies.size(); ++i) { - availableStr += availableStrategies[i]; - if (i < availableStrategies.size() - 1) availableStr += ", "; - } - availableStr += "]"; - - throw std::invalid_argument("Unknown strategy '" + strategyStr + "'. Available strategies: " + availableStr); - } -} - -std::string ModuleSystemFactory::strategyToString(ModuleSystemType systemType) { - switch (systemType) { - case ModuleSystemType::SEQUENTIAL: - return "sequential"; - case ModuleSystemType::THREADED: - return "threaded"; - case ModuleSystemType::THREAD_POOL: - return "thread_pool"; - case ModuleSystemType::CLUSTER: - return "cluster"; - default: - return "unknown"; - } -} - -ModuleSystemType ModuleSystemFactory::getRecommendedStrategy(int targetFPS, int moduleCount, int cpuCores) { - auto logger = getFactoryLogger(); - - if (cpuCores == 0) { - cpuCores = detectCpuCores(); - } - - logger->debug("🎯 Recommending strategy for: {}fps, {} modules, {} cores", - targetFPS, moduleCount, cpuCores); - - // Simple recommendation logic - if (moduleCount <= 1) { - logger->debug("💡 Single module -> SEQUENTIAL"); - return ModuleSystemType::SEQUENTIAL; - } else if (moduleCount <= cpuCores && targetFPS <= 30) { - logger->debug("💡 Few modules, low FPS -> THREADED"); - return ModuleSystemType::THREADED; - } else if (targetFPS > 30 || moduleCount > cpuCores) { - logger->debug("💡 High performance needs -> THREAD_POOL"); - return ModuleSystemType::THREAD_POOL; - } else { - logger->debug("💡 Default fallback -> SEQUENTIAL"); - return ModuleSystemType::SEQUENTIAL; - } -} - -// Private helper methods -std::shared_ptr ModuleSystemFactory::getFactoryLogger() { - static std::shared_ptr logger = nullptr; - - if (!logger) { - auto console_sink = std::make_shared(); - console_sink->set_level(spdlog::level::debug); - - logger = std::make_shared("ModuleSystemFactory", console_sink); - logger->set_level(spdlog::level::debug); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - } - - return logger; -} - -std::string ModuleSystemFactory::toLowercase(const std::string& str) { - std::string result = str; - std::transform(result.begin(), result.end(), result.begin(), - [](char c) { return std::tolower(c); }); - return result; -} - -int ModuleSystemFactory::detectCpuCores() { - int cores = std::thread::hardware_concurrency(); - if (cores == 0) cores = 4; // Fallback - return cores; -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/SequentialModuleSystem.cpp b/core/src/SequentialModuleSystem.cpp deleted file mode 100644 index f6badbb..0000000 --- a/core/src/SequentialModuleSystem.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include -#include - -namespace warfactory { - -SequentialModuleSystem::SequentialModuleSystem() { - // Create logger with file and console output - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared("logs/sequential_system.log", true); - - console_sink->set_level(spdlog::level::debug); - file_sink->set_level(spdlog::level::trace); - - logger = std::make_shared("SequentialModuleSystem", - spdlog::sinks_init_list{console_sink, file_sink}); - logger->set_level(spdlog::level::trace); - logger->flush_on(spdlog::level::debug); - - spdlog::register_logger(logger); - - logSystemStart(); - lastProcessTime = std::chrono::high_resolution_clock::now(); -} - -SequentialModuleSystem::~SequentialModuleSystem() { - logger->info("🔧 SequentialModuleSystem destructor called"); - - if (module) { - logger->info("📊 Final performance metrics:"); - logger->info(" Total process calls: {}", processCallCount); - logger->info(" Total process time: {:.2f}ms", totalProcessTime); - logger->info(" Average process time: {:.3f}ms", getAverageProcessTime()); - logger->info(" Total task executions: {}", taskExecutionCount); - } - - logger->trace("🏗️ SequentialModuleSystem destroyed"); -} - -void SequentialModuleSystem::setModule(std::unique_ptr newModule) { - logger->info("🔧 Setting module in SequentialModuleSystem"); - - if (module) { - logger->warn("⚠️ Replacing existing module '{}' with new module", moduleName); - try { - module->shutdown(); - logger->debug("✅ Previous module shut down successfully"); - } catch (const std::exception& e) { - logger->error("❌ Error shutting down previous module: {}", e.what()); - } - } - - if (!newModule) { - logger->error("❌ Cannot set null module"); - throw std::invalid_argument("Cannot set null module"); - } - - module = std::move(newModule); - - // Get module type for better logging - try { - moduleName = module->getType(); - logger->info("✅ Module set successfully: type '{}'", moduleName); - } catch (const std::exception& e) { - logger->warn("⚠️ Could not get module type: {} - using 'unknown'", e.what()); - moduleName = "unknown"; - } - - // Reset performance metrics for new module - resetPerformanceMetrics(); - logger->debug("📊 Performance metrics reset for new module"); -} - -IModule* SequentialModuleSystem::getModule() const { - logger->trace("🔍 Module pointer requested"); - return module.get(); -} - -int SequentialModuleSystem::processModule(float deltaTime) { - logProcessStart(deltaTime); - - auto processStartTime = std::chrono::high_resolution_clock::now(); - - try { - validateModule(); - - // Create input JSON for module - json moduleInput = { - {"deltaTime", deltaTime}, - {"frameCount", processCallCount}, - {"system", "sequential"}, - {"timestamp", std::chrono::duration_cast( - processStartTime.time_since_epoch()).count()} - }; - - logger->trace("📥 Calling module process() with input: {}", moduleInput.dump()); - - // Process the module - module->process(moduleInput); - - processCallCount++; - - auto processEndTime = std::chrono::high_resolution_clock::now(); - lastProcessDuration = std::chrono::duration(processEndTime - processStartTime).count(); - totalProcessTime += lastProcessDuration; - - logProcessEnd(lastProcessDuration); - - // Check for performance warnings - if (lastProcessDuration > 16.67f) { // More than 60fps budget - logger->warn("🐌 Slow module processing: {:.2f}ms (target: <16.67ms for 60fps)", lastProcessDuration); - } - - logger->trace("✅ Module processing completed successfully"); - return 0; // Success - - } catch (const std::exception& e) { - logger->error("❌ Error processing module '{}': {}", moduleName, e.what()); - logger->error("🔍 Error occurred at frame {}, deltaTime: {:.3f}ms", processCallCount, deltaTime * 1000); - - auto processEndTime = std::chrono::high_resolution_clock::now(); - lastProcessDuration = std::chrono::duration(processEndTime - processStartTime).count(); - - logProcessEnd(lastProcessDuration); - - return 1; // Error - } -} - -ModuleSystemType SequentialModuleSystem::getType() const { - logger->trace("🏷️ ModuleSystem type requested: SEQUENTIAL"); - return ModuleSystemType::SEQUENTIAL; -} - -void SequentialModuleSystem::scheduleTask(const std::string& taskType, const json& taskData) { - logger->debug("⚙️ Task scheduled for immediate execution: '{}'", taskType); - logTaskExecution(taskType, taskData); - - try { - // In sequential system, tasks execute immediately - // This is just a placeholder - real task execution would happen here - logger->trace("🔧 Executing task '{}' immediately", taskType); - - // TODO: Implement actual task execution - // For now, we just log and count - taskExecutionCount++; - - logger->debug("✅ Task '{}' completed immediately", taskType); - - } catch (const std::exception& e) { - logger->error("❌ Error executing task '{}': {}", taskType, e.what()); - throw; - } -} - -int SequentialModuleSystem::hasCompletedTasks() const { - // Sequential system executes tasks immediately, so no completed tasks queue - logger->trace("🔍 Completed tasks count requested: 0 (sequential execution)"); - return 0; -} - -json SequentialModuleSystem::getCompletedTask() { - logger->warn("⚠️ getCompletedTask() called on sequential system - no queued tasks"); - throw std::runtime_error("SequentialModuleSystem executes tasks immediately - no completed tasks queue"); -} - -json SequentialModuleSystem::getPerformanceMetrics() const { - logger->debug("📊 Performance metrics requested"); - - json metrics = { - {"system_type", "sequential"}, - {"module_name", moduleName}, - {"process_calls", processCallCount}, - {"total_process_time_ms", totalProcessTime}, - {"average_process_time_ms", getAverageProcessTime()}, - {"last_process_time_ms", lastProcessDuration}, - {"task_executions", taskExecutionCount} - }; - - if (processCallCount > 0) { - auto currentTime = std::chrono::high_resolution_clock::now(); - auto totalRunTime = std::chrono::duration(currentTime - lastProcessTime).count(); - metrics["total_runtime_seconds"] = totalRunTime; - metrics["average_fps"] = totalRunTime > 0 ? processCallCount / totalRunTime : 0.0f; - } - - logger->trace("📄 Metrics JSON: {}", metrics.dump()); - return metrics; -} - -void SequentialModuleSystem::resetPerformanceMetrics() { - logger->debug("📊 Resetting performance metrics"); - - processCallCount = 0; - totalProcessTime = 0.0f; - lastProcessDuration = 0.0f; - taskExecutionCount = 0; - lastProcessTime = std::chrono::high_resolution_clock::now(); - - logger->trace("✅ Performance metrics reset"); -} - -float SequentialModuleSystem::getAverageProcessTime() const { - if (processCallCount == 0) return 0.0f; - return totalProcessTime / processCallCount; -} - -size_t SequentialModuleSystem::getProcessCallCount() const { - return processCallCount; -} - -size_t SequentialModuleSystem::getTaskExecutionCount() const { - return taskExecutionCount; -} - -void SequentialModuleSystem::setLogLevel(spdlog::level::level_enum level) { - logger->info("🔧 Setting log level to: {}", spdlog::level::to_string_view(level)); - logger->set_level(level); -} - -// Private helper methods -void SequentialModuleSystem::logSystemStart() { - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("⚙️ SEQUENTIAL MODULE SYSTEM INITIALIZED"); - logger->info("=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "=" "="); - logger->info("🎯 System Type: SEQUENTIAL (Debug/Test mode)"); - logger->info("🔧 Features: Immediate execution, comprehensive logging"); - logger->info("📊 Performance: Single-threaded, deterministic"); - logger->trace("🏗️ SequentialModuleSystem object created at: {}", static_cast(this)); -} - -void SequentialModuleSystem::logProcessStart(float deltaTime) { - logger->trace("🎬 Process call {} START - deltaTime: {:.3f}ms, module: '{}'", - processCallCount, deltaTime * 1000, moduleName); -} - -void SequentialModuleSystem::logProcessEnd(float processTime) { - logger->trace("🏁 Process call {} END - processTime: {:.3f}ms", processCallCount, processTime); - - // Log performance summary every 60 calls - if (processCallCount > 0 && processCallCount % 60 == 0) { - logger->debug("📊 Performance summary (frame {}): Avg: {:.3f}ms, Total: {:.1f}ms", - processCallCount, getAverageProcessTime(), totalProcessTime); - } -} - -void SequentialModuleSystem::logTaskExecution(const std::string& taskType, const json& taskData) { - logger->trace("⚙️ Task execution {} - type: '{}', data size: {} bytes", - taskExecutionCount + 1, taskType, taskData.dump().size()); - logger->trace("📄 Task data: {}", taskData.dump()); -} - -std::unique_ptr SequentialModuleSystem::extractModule() { - logger->info("🔓 Extracting module from system"); - - if (!module) { - logger->warn("⚠️ No module to extract"); - return nullptr; - } - - auto extractedModule = std::move(module); - moduleName = "unknown"; - - logger->info("✅ Module extracted successfully"); - return extractedModule; -} - -void SequentialModuleSystem::validateModule() const { - if (!module) { - logger->error("❌ No module set - cannot process"); - throw std::runtime_error("No module set in SequentialModuleSystem"); - } -} - -} // namespace warfactory \ No newline at end of file diff --git a/core/src/focused_hot_reload_test.cpp b/core/src/focused_hot_reload_test.cpp deleted file mode 100644 index 9397eef..0000000 --- a/core/src/focused_hot_reload_test.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using json = nlohmann::json; -using namespace warfactory; - -// Lightweight test implementations -class LightTestIO : public IIO { - std::vector messageQueue; - size_t publishCount = 0; - -public: - void publish(const std::string& topic, const json& message) override { - publishCount++; - Message msg{topic, message, static_cast( - std::chrono::high_resolution_clock::now().time_since_epoch().count())}; - messageQueue.push_back(msg); - std::cout << "📤 [" << publishCount << "] " << topic << std::endl; - } - - void subscribe(const std::string& topicPattern, const SubscriptionConfig& config = {}) override { - std::cout << "📨 Subscribed: " << topicPattern << std::endl; - } - - void subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config = {}) override { - std::cout << "📨 LowFreq: " << topicPattern << std::endl; - } - - int hasMessages() const override { - return static_cast(messageQueue.size()); - } - - Message pullMessage() override { - if (messageQueue.empty()) { - throw std::runtime_error("No messages"); - } - Message msg = messageQueue.front(); - messageQueue.erase(messageQueue.begin()); - return msg; - } - - IOHealth getHealth() const override { - return IOHealth{static_cast(messageQueue.size()), 1000, false, 0.0f, 0}; - } - - IOType getType() const override { return IOType::INTRA; } - - size_t getPublishCount() const { return publishCount; } -}; - -class LightTestScheduler : public ITaskScheduler { - size_t taskCount = 0; - -public: - void scheduleTask(const std::string& taskType, const json& taskData) override { - taskCount++; - std::cout << "⚡ [" << taskCount << "] " << taskType << std::endl; - } - - int hasCompletedTasks() const override { return 0; } - json getCompletedTask() override { throw std::runtime_error("No tasks"); } - size_t getTaskCount() const { return taskCount; } -}; - -struct ModuleHandle { - void* dlHandle = nullptr; - std::unique_ptr module; - std::function create; - std::function destroy; - std::string type; - std::string path; - - ~ModuleHandle() { - if (module) { - destroy(module.release()); - } - if (dlHandle) { - dlclose(dlHandle); - } - } -}; - -std::unique_ptr loadModule(const std::string& path) { - auto handle = std::make_unique(); - handle->path = path; - - // Load library - handle->dlHandle = dlopen(path.c_str(), RTLD_LAZY); - if (!handle->dlHandle) { - throw std::runtime_error("dlopen failed: " + std::string(dlerror())); - } - - // Get entry points - typedef IModule* (*CreateFunc)(); - typedef void (*DestroyFunc)(IModule*); - typedef const char* (*GetTypeFunc)(); - - handle->create = (CreateFunc)dlsym(handle->dlHandle, "create_module"); - handle->destroy = (DestroyFunc)dlsym(handle->dlHandle, "destroy_module"); - auto getType = (GetTypeFunc)dlsym(handle->dlHandle, "get_module_type"); - - if (!handle->create || !handle->destroy || !getType) { - throw std::runtime_error("Symbol resolution failed"); - } - - handle->type = getType(); - handle->module = std::unique_ptr(handle->create()); - - return handle; -} - -int main() { - std::cout << "🔥 FOCUSED HOT-RELOAD PERFORMANCE TEST" << std::endl; - std::cout << "=======================================" << std::endl; - - const std::string modulePath = "../modules/debug-world-gen/debug-world-gen-light.so"; - - try { - // Test services - LightTestIO testIO; - LightTestScheduler testScheduler; - - json config = {{"seed", 123}, {"size", 150}, {"chunk_size", 24}}; - - // Performance test: Multiple hot-reload cycles - std::cout << "\n🧪 PERFORMANCE TEST: Multiple hot-reload cycles" << std::endl; - std::cout << "================================================" << std::endl; - - const int cycles = 5; - std::vector reloadTimes; - - for (int cycle = 1; cycle <= cycles; ++cycle) { - std::cout << "\n--- Cycle " << cycle << "/" << cycles << " ---" << std::endl; - - auto cycleStart = std::chrono::high_resolution_clock::now(); - - // Load module - auto handle = loadModule(modulePath); - std::cout << "📦 Module loaded: " << handle->type << std::endl; - - // Initialize - handle->module->initialize(config, &testIO, &testScheduler); - std::cout << "🚀 Module initialized" << std::endl; - - // Do some work - json chunkRequest = {{"chunk_x", cycle}, {"chunk_y", cycle * 2}}; - testIO.publish("world:request:chunk", chunkRequest); - - handle->module->process({}); - std::cout << "⚙️ Module processed work" << std::endl; - - // Get state - json state = handle->module->getState(); - int chunks = state.value("chunks_generated", 0); - std::cout << "📊 Chunks generated: " << chunks << std::endl; - - // Shutdown and measure complete cycle - handle->module->shutdown(); - handle.reset(); // Cleanup - - auto cycleEnd = std::chrono::high_resolution_clock::now(); - float cycleDuration = std::chrono::duration(cycleEnd - cycleStart).count(); - reloadTimes.push_back(cycleDuration); - - std::cout << "⚡ Complete cycle time: " << cycleDuration << "ms" << std::endl; - - // Brief pause - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - - // Performance analysis - std::cout << "\n📊 PERFORMANCE ANALYSIS" << std::endl; - std::cout << "=======================" << std::endl; - - float totalTime = 0.0f; - float minTime = reloadTimes[0]; - float maxTime = reloadTimes[0]; - - for (float time : reloadTimes) { - totalTime += time; - minTime = std::min(minTime, time); - maxTime = std::max(maxTime, time); - } - - float avgTime = totalTime / reloadTimes.size(); - - std::cout << "⚡ Average reload time: " << avgTime << "ms" << std::endl; - std::cout << "🚀 Best time: " << minTime << "ms" << std::endl; - std::cout << "🐌 Worst time: " << maxTime << "ms" << std::endl; - std::cout << "📊 Total test time: " << totalTime << "ms" << std::endl; - - // Test state persistence across reloads - std::cout << "\n🧪 STATE PERSISTENCE TEST" << std::endl; - std::cout << "=========================" << std::endl; - - auto handle1 = loadModule(modulePath); - handle1->module->initialize(config, &testIO, &testScheduler); - - // Generate some work - for (int i = 0; i < 3; ++i) { - testIO.publish("world:request:chunk", {{"chunk_x", i}, {"chunk_y", i}}); - handle1->module->process({}); - } - - json savedState = handle1->module->getState(); - int savedChunks = savedState.value("chunks_generated", 0); - std::cout << "💾 State saved: " << savedChunks << " chunks" << std::endl; - - handle1->module->shutdown(); - handle1.reset(); - - // Reload and restore - auto handle2 = loadModule(modulePath); - handle2->module->setState(savedState); - handle2->module->initialize(config, &testIO, &testScheduler); - - json restoredState = handle2->module->getState(); - int restoredChunks = restoredState.value("chunks_generated", 0); - std::cout << "🔄 State restored: " << restoredChunks << " chunks" << std::endl; - - if (savedChunks == restoredChunks) { - std::cout << "✅ STATE PERSISTENCE: PERFECT!" << std::endl; - } else { - std::cout << "❌ STATE PERSISTENCE: FAILED!" << std::endl; - } - - // Final summary - std::cout << "\n🎯 SUMMARY" << std::endl; - std::cout << "=========" << std::endl; - std::cout << "📈 IO Messages published: " << testIO.getPublishCount() << std::endl; - std::cout << "⚡ Tasks scheduled: " << testScheduler.getTaskCount() << std::endl; - - if (avgTime < 20) { - std::cout << "🚀 BLAZING: Sub-20ms average reload!" << std::endl; - } else if (avgTime < 50) { - std::cout << "⚡ EXCELLENT: Sub-50ms average reload!" << std::endl; - } else if (avgTime < 100) { - std::cout << "✅ GOOD: Sub-100ms average reload" << std::endl; - } else { - std::cout << "⚠️ SLOW: Over 100ms average reload" << std::endl; - } - - handle2.reset(); - - std::cout << "\n🎉 HOT-RELOAD TEST COMPLETED!" << std::endl; - - } catch (const std::exception& e) { - std::cerr << "❌ Test failed: " << e.what() << std::endl; - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/core/src/hot_reload_test.cpp b/core/src/hot_reload_test.cpp deleted file mode 100644 index 7b44930..0000000 --- a/core/src/hot_reload_test.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace warfactory; -using json = nlohmann::json; - -int main() { - std::cout << "🔥 HOT-RELOAD INTEGRATION TEST" << std::endl; - std::cout << "==============================" << std::endl; - - try { - // Create complete system - std::cout << "🏗️ Creating complete system..." << std::endl; - - auto engine = EngineFactory::create("debug"); - auto moduleSystem = ModuleSystemFactory::create("sequential"); - auto io = IOFactory::create("intra", "hot-reload-test"); - ModuleFactory moduleFactory; - - std::cout << "✅ All components created" << std::endl; - - // Setup module discovery - moduleFactory.setModulesDirectory("../modules"); - moduleFactory.enableHotReload(true); - - // Test 1: Load module initially - std::cout << "\n🧪 TEST 1: Initial module loading" << std::endl; - std::cout << "=================================" << std::endl; - - auto module = moduleFactory.loadModule("../modules/debug-world-gen/debug-world-gen.so"); - std::cout << "📦 Module loaded: " << module->getType() << std::endl; - - // Initialize module with test config - json testConfig = { - {"world_size", 100}, - {"seed", 42}, - {"chunk_size", 16} - }; - - // Create minimal task scheduler for test - class TestTaskScheduler : public ITaskScheduler { - public: - void scheduleTask(const std::string& taskType, const json& taskData) override { - std::cout << "⚡ Task: " << taskType << std::endl; - } - int hasCompletedTasks() const override { return 0; } - json getCompletedTask() override { throw std::runtime_error("No tasks"); } - } scheduler; - - module->initialize(testConfig, io.get(), &scheduler); - - // Get initial state - json initialState = module->getState(); - std::cout << "💾 Initial state captured" << std::endl; - - // Test 2: Process some work - std::cout << "\n🧪 TEST 2: Processing work" << std::endl; - std::cout << "==========================" << std::endl; - - // Simulate chunk requests via pub/sub - json chunkRequest = {{"chunk_x", 0}, {"chunk_y", 0}}; - io->publish("world:request:chunk", chunkRequest); - - // Process messages - module->process({}); - - json stateAfterWork = module->getState(); - std::cout << "📊 Work completed, state updated" << std::endl; - - // Test 3: Hot-reload simulation - std::cout << "\n🔥 TEST 3: HOT-RELOAD SIMULATION" << std::endl; - std::cout << "=================================" << std::endl; - - // Save current state - json savedState = module->getState(); - std::cout << "💾 State saved for hot-reload" << std::endl; - - // Shutdown current module - module->shutdown(); - std::cout << "🛑 Module shut down" << std::endl; - - // Simulate "recompilation" delay - std::cout << "⏳ Simulating recompilation (1s)..." << std::endl; - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - - // Reload module - std::cout << "🔄 Reloading module..." << std::endl; - auto reloadedModule = moduleFactory.loadModule("../modules/debug-world-gen/debug-world-gen.so"); - - // Restore state - reloadedModule->setState(savedState); - reloadedModule->initialize(testConfig, io.get(), &scheduler); - - json restoredState = reloadedModule->getState(); - std::cout << "✅ Module reloaded with state preserved" << std::endl; - - // Test 4: Verify state preservation - std::cout << "\n🧪 TEST 4: State preservation verification" << std::endl; - std::cout << "==========================================" << std::endl; - - if (savedState["generated_chunks"] == restoredState["generated_chunks"]) { - std::cout << "✅ Chunk count preserved" << std::endl; - } else { - std::cout << "❌ Chunk count lost" << std::endl; - } - - if (savedState["config"] == restoredState["config"]) { - std::cout << "✅ Configuration preserved" << std::endl; - } else { - std::cout << "❌ Configuration lost" << std::endl; - } - - // Test 5: Config hot-swap - std::cout << "\n🧪 TEST 5: Configuration hot-swap" << std::endl; - std::cout << "===================================" << std::endl; - - json newConfig = { - {"world_size", 200}, // Changed - {"seed", 999}, // Changed - {"chunk_size", 32} // Changed - }; - - io->publish("world:config:update", newConfig); - reloadedModule->process({}); - - json finalState = reloadedModule->getState(); - if (finalState["config"]["seed"] == 999) { - std::cout << "✅ Configuration hot-swapped successfully" << std::endl; - } else { - std::cout << "❌ Configuration hot-swap failed" << std::endl; - } - - // Test 6: Performance metrics - std::cout << "\n📊 PERFORMANCE METRICS" << std::endl; - std::cout << "=======================" << std::endl; - - auto start = std::chrono::high_resolution_clock::now(); - - // Simulate hot-reload cycle - json preReloadState = reloadedModule->getState(); - reloadedModule->shutdown(); - auto newModule = moduleFactory.loadModule("../modules/debug-world-gen/debug-world-gen.so"); - newModule->setState(preReloadState); - newModule->initialize(testConfig, io.get(), &scheduler); - - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration(end - start).count(); - - std::cout << "⚡ Hot-reload cycle time: " << duration << "ms" << std::endl; - - if (duration < 100) { - std::cout << "🚀 EXCELLENT: Sub-100ms hot-reload!" << std::endl; - } else if (duration < 500) { - std::cout << "✅ GOOD: Sub-500ms hot-reload" << std::endl; - } else { - std::cout << "⚠️ SLOW: Hot-reload over 500ms" << std::endl; - } - - // Cleanup - newModule->shutdown(); - - std::cout << "\n🎉 ALL HOT-RELOAD TESTS COMPLETED!" << std::endl; - std::cout << "===================================" << std::endl; - - } catch (const std::exception& e) { - std::cerr << "❌ Hot-reload test failed: " << e.what() << std::endl; - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/core/src/main.cpp b/core/src/main.cpp deleted file mode 100644 index 54b0c69..0000000 --- a/core/src/main.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -using namespace warfactory; - -int main(int argc, char* argv[]) { - std::cout << "🏭 Warfactory Modular Engine Starting..." << std::endl; - - try { - // Determine engine type from command line or default to debug - std::string engineType = "debug"; - - if (argc > 1) { - engineType = argv[1]; - std::cout << "🎯 Engine type specified: " << engineType << std::endl; - } else { - std::cout << "🔧 Using default engine type: " << engineType << std::endl; - } - - // Create engine using factory - std::cout << "🏭 Creating engine via EngineFactory..." << std::endl; - auto engine = EngineFactory::createEngine(engineType); - - std::cout << "✅ Engine created successfully!" << std::endl; - std::cout << "🎯 Engine type: " << EngineFactory::engineTypeToString(engine->getType()) << std::endl; - - // Initialize engine - std::cout << "🚀 Initializing engine..." << std::endl; - engine->initialize(); - - std::cout << "⚠️ Engine initialized but no modules loaded yet" << std::endl; - std::cout << "📋 Next steps:" << std::endl; - std::cout << " 1. ✅ DebugEngine implemented" << std::endl; - std::cout << " 2. ✅ EngineFactory implemented" << std::endl; - std::cout << " 3. ⭕ Implement SequentialModuleSystem" << std::endl; - std::cout << " 4. ⭕ Implement IntraIO" << std::endl; - std::cout << " 5. ⭕ Create first test module" << std::endl; - - // For now, just initialize and shutdown - std::cout << "🛑 Shutting down engine (no main loop yet)" << std::endl; - engine->shutdown(); - - return 0; - } - catch (const std::exception& e) { - std::cerr << "❌ Engine failed: " << e.what() << std::endl; - return 1; - } -} \ No newline at end of file diff --git a/core/src/minimal_hot_reload_test.cpp b/core/src/minimal_hot_reload_test.cpp deleted file mode 100644 index b90fbbc..0000000 --- a/core/src/minimal_hot_reload_test.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using json = nlohmann::json; -using namespace warfactory; - -// PROPER test implementations that actually inherit from interfaces -class TestIO : public IIO { -public: - void publish(const std::string& topic, const json& message) override { - std::cout << "📤 " << topic << ": " << message.dump() << std::endl; - } - - void subscribe(const std::string& topicPattern, const SubscriptionConfig& config = {}) override { - std::cout << "📨 Subscribed: " << topicPattern << std::endl; - } - - void subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config = {}) override { - std::cout << "📨 LowFreq subscribed: " << topicPattern << std::endl; - } - - int hasMessages() const override { - return 0; - } - - Message pullMessage() override { - throw std::runtime_error("No messages in test"); - } - - IOHealth getHealth() const override { - return IOHealth{0, 1000, false, 0.0f, 0}; - } - - IOType getType() const override { - return IOType::INTRA; - } -}; - -class TestTaskScheduler : public ITaskScheduler { -public: - void scheduleTask(const std::string& taskType, const json& taskData) override { - std::cout << "⚡ Task: " << taskType << " -> " << taskData.dump() << std::endl; - } - - int hasCompletedTasks() const override { - return 0; - } - - json getCompletedTask() override { - throw std::runtime_error("No completed tasks in test"); - } -}; - -int main() { - std::cout << "🔥 MINIMAL HOT-RELOAD TEST" << std::endl; - std::cout << "==========================" << std::endl; - - const char* modulePath = "../modules/debug-world-gen/debug-world-gen-light.so"; - - try { - // Test 1: Load module manually - std::cout << "\n🧪 TEST 1: Manual dlopen/dlsym" << std::endl; - - void* handle = dlopen(modulePath, RTLD_LAZY); - if (!handle) { - std::cerr << "❌ Failed to load: " << dlerror() << std::endl; - return 1; - } - - // Get entry points - typedef IModule* (*CreateFunc)(); - typedef void (*DestroyFunc)(IModule*); - typedef const char* (*GetTypeFunc)(); - - CreateFunc create = (CreateFunc)dlsym(handle, "create_module"); - DestroyFunc destroy = (DestroyFunc)dlsym(handle, "destroy_module"); - GetTypeFunc getType = (GetTypeFunc)dlsym(handle, "get_module_type"); - - if (!create || !destroy || !getType) { - std::cerr << "❌ Symbol resolution failed" << std::endl; - return 1; - } - - std::cout << "✅ Module type: " << getType() << std::endl; - - // Test 2: Create and use module - std::cout << "\n🧪 TEST 2: Module lifecycle" << std::endl; - - auto module = std::unique_ptr(create()); - std::cout << "📦 Module created: " << module->getType() << std::endl; - - // PROPER services that inherit from interfaces - TestIO testIO; - TestTaskScheduler testScheduler; - - json config = {{"seed", 42}, {"size", 100}}; - - // Initialize with proper inheritance - should work! - try { - module->initialize(config, &testIO, &testScheduler); - std::cout << "✅ Module initialized successfully!" << std::endl; - } catch (const std::exception& e) { - std::cout << "❌ Initialize failed: " << e.what() << std::endl; - } - - // Test state management - json state; - try { - state = module->getState(); - std::cout << "📊 State: " << state.dump() << std::endl; - } catch (...) { - std::cout << "⚠️ getState crashed" << std::endl; - } - - // Test 3: Hot-reload simulation - std::cout << "\n🔥 TEST 3: Hot-reload cycle" << std::endl; - - auto start = std::chrono::high_resolution_clock::now(); - - // Destroy current instance - destroy(module.release()); - std::cout << "🗑️ Module destroyed" << std::endl; - - // Unload library - dlclose(handle); - std::cout << "📤 Library unloaded" << std::endl; - - // Simulate recompilation delay - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - - // Reload - handle = dlopen(modulePath, RTLD_LAZY); - if (!handle) { - std::cerr << "❌ Reload failed: " << dlerror() << std::endl; - return 1; - } - - create = (CreateFunc)dlsym(handle, "create_module"); - destroy = (DestroyFunc)dlsym(handle, "destroy_module"); - - auto newModule = std::unique_ptr(create()); - - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration(end - start).count(); - - std::cout << "⚡ Hot-reload time: " << duration << "ms" << std::endl; - - if (duration < 10) { - std::cout << "🚀 BLAZING FAST: Sub-10ms reload!" << std::endl; - } else if (duration < 100) { - std::cout << "✅ EXCELLENT: Sub-100ms reload!" << std::endl; - } else { - std::cout << "⚠️ SLOW: Over 100ms reload" << std::endl; - } - - // Cleanup - destroy(newModule.release()); - dlclose(handle); - - std::cout << "\n🎉 MINIMAL HOT-RELOAD TESTS COMPLETED!" << std::endl; - - } catch (const std::exception& e) { - std::cerr << "❌ Test failed: " << e.what() << std::endl; - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/core/src/real_hot_reload_test.cpp b/core/src/real_hot_reload_test.cpp deleted file mode 100644 index 5e42669..0000000 --- a/core/src/real_hot_reload_test.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// Skip heavy implementations for now - test avec les minimales -#include -#include -#include -#include -#include -#include - -using namespace warfactory; -using json = nlohmann::json; - -int main() { - std::cout << "🔥 FOCUSED HOT-RELOAD INTEGRATION TEST" << std::endl; - std::cout << "======================================" << std::endl; - - try { - // Test the core hot-reload capability with real .so loading - std::cout << "\n🧪 TEST: Real module hot-reload cycle" << std::endl; - std::cout << "=====================================" << std::endl; - - // Setup module factory - moduleFactory->enableHotReload(true); - std::cout << "🔥 Hot-reload enabled" << std::endl; - - // Test 1: Load module with real system - std::cout << "\n🧪 TEST 1: Load module with real implementations" << std::endl; - std::cout << "=================================================" << std::endl; - - const std::string modulePath = "../modules/debug-world-gen/debug-world-gen-light.so"; - - auto module = moduleFactory->loadModule(modulePath); - std::cout << "📦 Module loaded: " << module->getType() << std::endl; - - // Connect module to system - moduleSystem->setModule(std::move(module)); - std::cout << "🔗 Module connected to SequentialModuleSystem" << std::endl; - - // Test 2: Initialize module with real IntraIO - std::cout << "\n🧪 TEST 2: Initialize with real IntraIO" << std::endl; - std::cout << "========================================" << std::endl; - - json config = { - {"seed", 12345}, - {"size", 200}, - {"chunk_size", 32}, - {"debug_mode", true} - }; - - // Get module back to initialize it - IModule* modulePtr = moduleSystem->getModule(); - if (!modulePtr) { - throw std::runtime_error("Module not found in system"); - } - - modulePtr->initialize(config, io.get(), moduleSystem.get()); - std::cout << "✅ Module initialized with REAL IntraIO and TaskScheduler" << std::endl; - - // Test 3: Process some real work with pub/sub - std::cout << "\n🧪 TEST 3: Process real work with pub/sub" << std::endl; - std::cout << "==========================================" << std::endl; - - // Publish some chunk requests - json chunkRequest1 = {{"chunk_x", 0}, {"chunk_y", 0}}; - json chunkRequest2 = {{"chunk_x", 1}, {"chunk_y", 1}}; - - io->publish("world:request:chunk", chunkRequest1); - io->publish("world:request:chunk", chunkRequest2); - - std::cout << "📤 Published 2 chunk requests" << std::endl; - std::cout << "📊 Messages available: " << io->hasMessages() << std::endl; - - // Process through module system - int processResult = moduleSystem->processModule(16.67f); // ~60fps - std::cout << "⚙️ Module processed, result code: " << processResult << std::endl; - - // Check for generated responses - std::cout << "📊 Messages after processing: " << io->hasMessages() << std::endl; - - // Test 4: State management and persistence - std::cout << "\n🧪 TEST 4: State management" << std::endl; - std::cout << "============================" << std::endl; - - json currentState = modulePtr->getState(); - std::cout << "📊 Current state: " << currentState.dump(2) << std::endl; - - // Verify chunks were processed - int chunksGenerated = currentState.value("chunks_generated", 0); - if (chunksGenerated > 0) { - std::cout << "✅ Module processed work: " << chunksGenerated << " chunks generated" << std::endl; - } else { - std::cout << "⚠️ No chunks generated (might be normal if no messages processed)" << std::endl; - } - - // Test 5: REAL Hot-reload with full system - std::cout << "\n🔥 TEST 5: FULL SYSTEM HOT-RELOAD" << std::endl; - std::cout << "==================================" << std::endl; - - auto startReload = std::chrono::high_resolution_clock::now(); - - // Save full state - json savedState = modulePtr->getState(); - std::cout << "💾 State saved for hot-reload" << std::endl; - - // Remove module from system - auto extractedModule = moduleSystem->extractModule(); - std::cout << "🔓 Module extracted from system" << std::endl; - - // Shutdown old module - extractedModule->shutdown(); - std::cout << "🛑 Old module shut down" << std::endl; - - // Hot-reload via factory - std::cout << "🔄 Hot-reloading module..." << std::endl; - auto reloadedModule = moduleFactory->reloadModule("debug-world-gen-light"); - if (!reloadedModule) { - // Fallback to manual reload - reloadedModule = moduleFactory->loadModule(modulePath); - } - - // Restore state - reloadedModule->setState(savedState); - reloadedModule->initialize(config, io.get(), moduleSystem.get()); - - // Reconnect to system - moduleSystem->setModule(std::move(reloadedModule)); - - auto endReload = std::chrono::high_resolution_clock::now(); - auto reloadDuration = std::chrono::duration(endReload - startReload).count(); - - std::cout << "⚡ COMPLETE HOT-RELOAD TIME: " << reloadDuration << "ms" << std::endl; - - // Verify state preservation - IModule* reloadedPtr = moduleSystem->getModule(); - json restoredState = reloadedPtr->getState(); - - if (savedState["chunks_generated"] == restoredState["chunks_generated"]) { - std::cout << "✅ State perfectly preserved across hot-reload!" << std::endl; - } else { - std::cout << "❌ State lost during hot-reload" << std::endl; - } - - // Test 6: Continue working after hot-reload - std::cout << "\n🧪 TEST 6: Post hot-reload functionality" << std::endl; - std::cout << "=========================================" << std::endl; - - // Send more work - json chunkRequest3 = {{"chunk_x", 2}, {"chunk_y", 2}}; - io->publish("world:request:chunk", chunkRequest3); - - processResult = moduleSystem->processModule(16.67f); - std::cout << "⚙️ Post-reload processing result: " << processResult << std::endl; - - json finalState = reloadedPtr->getState(); - int finalChunks = finalState.value("chunks_generated", 0); - std::cout << "📊 Final chunks generated: " << finalChunks << std::endl; - - // Performance summary - std::cout << "\n📊 PERFORMANCE SUMMARY" << std::endl; - std::cout << "======================" << std::endl; - std::cout << "🔥 Hot-reload time: " << reloadDuration << "ms" << std::endl; - - if (reloadDuration < 50) { - std::cout << "🚀 BLAZING FAST: Sub-50ms complete system hot-reload!" << std::endl; - } else if (reloadDuration < 200) { - std::cout << "✅ EXCELLENT: Sub-200ms hot-reload!" << std::endl; - } else if (reloadDuration < 500) { - std::cout << "👍 GOOD: Sub-500ms hot-reload" << std::endl; - } else { - std::cout << "⚠️ SLOW: Hot-reload over 500ms" << std::endl; - } - - // Health check - auto ioHealth = io->getHealth(); - std::cout << "📊 IO Health: queue=" << ioHealth.queueSize << "/" << ioHealth.maxQueueSize; - std::cout << ", rate=" << ioHealth.averageProcessingRate << "msg/s" << std::endl; - - // Cleanup - reloadedPtr->shutdown(); - std::cout << "\n✅ System shutdown complete" << std::endl; - - std::cout << "\n🎉 REAL HOT-RELOAD INTEGRATION TEST COMPLETED!" << std::endl; - std::cout << "===============================================" << std::endl; - - } catch (const std::exception& e) { - std::cerr << "❌ Integration test failed: " << e.what() << std::endl; - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/core/src/test_intra_io_routing.cpp b/core/src/test_intra_io_routing.cpp deleted file mode 100644 index 0f9dd68..0000000 --- a/core/src/test_intra_io_routing.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace warfactory; - -int main() { - std::cout << "🧪 Testing IntraIO routing system..." << std::endl; - - try { - // Create manager (singleton, auto-initialized) - auto& manager = IntraIOManager::getInstance(); - manager.setLogLevel(spdlog::level::trace); - - // Create two module instances through manager - auto moduleA = manager.createInstance("module-a"); - auto moduleB = manager.createInstance("module-b"); - - // Module A subscribes to "test:*" - moduleA->subscribe("test:*"); - std::cout << "✅ Module A subscribed to 'test:*'" << std::endl; - - // Module B subscribes to "test:data" - moduleB->subscribe("test:data"); - std::cout << "✅ Module B subscribed to 'test:data'" << std::endl; - - // Wait a bit for subscriptions to register - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - // Module A publishes a message - nlohmann::json testData = {{"value", 42}, {"source", "module-a"}}; - moduleA->publish("test:data", testData); - std::cout << "📤 Module A published message to 'test:data'" << std::endl; - - // Wait for routing - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - - // Check if modules received messages - std::cout << "\n📊 Checking message reception:" << std::endl; - std::cout << "Module A has " << moduleA->hasMessages() << " messages" << std::endl; - std::cout << "Module B has " << moduleB->hasMessages() << " messages" << std::endl; - - // Module B should have received the message - if (moduleB->hasMessages() > 0) { - auto msg = moduleB->pullMessage(); - std::cout << "✅ Module B received: " << msg.topic << " -> " << msg.data.dump() << std::endl; - } else { - std::cout << "❌ Module B did not receive message" << std::endl; - } - - // Test another direction - Module B publishes to Module A - nlohmann::json responseData = {{"response", "ok"}, {"source", "module-b"}}; - moduleB->publish("test:response", responseData); - std::cout << "\n📤 Module B published message to 'test:response'" << std::endl; - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - - // Module A should receive it (subscribed to test:*) - std::cout << "Module A has " << moduleA->hasMessages() << " messages" << std::endl; - if (moduleA->hasMessages() > 0) { - auto msg = moduleA->pullMessage(); - std::cout << "✅ Module A received: " << msg.topic << " -> " << msg.data.dump() << std::endl; - } else { - std::cout << "❌ Module A did not receive message" << std::endl; - std::cout << "🔍 Debug: Pattern 'test:*' should match 'test:response'" << std::endl; - } - - // Show routing stats - auto stats = manager.getRoutingStats(); - std::cout << "\n📊 Final routing statistics:" << std::endl; - std::cout << " Routed messages: " << stats["total_routed_messages"] << std::endl; - std::cout << " Total routes: " << stats["total_routes"] << std::endl; - std::cout << " Active instances: " << stats["active_instances"] << std::endl; - - std::cout << "\n🎉 Test completed successfully!" << std::endl; - return 0; - - } catch (const std::exception& e) { - std::cerr << "❌ Test failed: " << e.what() << std::endl; - return 1; - } -} \ No newline at end of file diff --git a/core/src/test_unified_io.cpp b/core/src/test_unified_io.cpp deleted file mode 100644 index cffad39..0000000 --- a/core/src/test_unified_io.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace warfactory; - -int main() { - std::cout << "🧪 Testing unified IOFactory with IntraIO routing..." << std::endl; - - try { - // Create two instances via IOFactory (like modules would) - auto moduleIO1 = IOFactory::create("intra", "module-factory-test-1"); - auto moduleIO2 = IOFactory::create("intra", "module-factory-test-2"); - - std::cout << "✅ Created 2 IO instances via IOFactory" << std::endl; - - // Test subscriptions - moduleIO1->subscribe("test:*"); - moduleIO2->subscribe("test:data"); - - std::cout << "✅ Set up subscriptions" << std::endl; - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - - // Test messaging between factory-created instances - nlohmann::json testData = {{"message", "from factory test"}, {"source", "module1"}}; - moduleIO1->publish("test:data", testData); - - std::cout << "📤 Module 1 published message" << std::endl; - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - - // Check if module 2 received it - if (moduleIO2->hasMessages() > 0) { - auto msg = moduleIO2->pullMessage(); - std::cout << "✅ Module 2 received: " << msg.topic << " -> " << msg.data.dump() << std::endl; - } else { - std::cout << "❌ Module 2 did not receive message" << std::endl; - return 1; - } - - // Test the reverse direction - nlohmann::json responseData = {{"response", "ok"}, {"source", "module2"}}; - moduleIO2->publish("test:response", responseData); - - std::cout << "📤 Module 2 published response" << std::endl; - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - - // Module 1 should receive it (subscribed to test:*) - if (moduleIO1->hasMessages() > 0) { - auto msg = moduleIO1->pullMessage(); - std::cout << "✅ Module 1 received: " << msg.topic << " -> " << msg.data.dump() << std::endl; - } else { - std::cout << "❌ Module 1 did not receive response" << std::endl; - return 1; - } - - // Show manager stats - auto& manager = IntraIOManager::getInstance(); - auto stats = manager.getRoutingStats(); - std::cout << "\n📊 Manager statistics:" << std::endl; - std::cout << " Routed messages: " << stats["total_routed_messages"] << std::endl; - std::cout << " Active instances: " << stats["active_instances"] << std::endl; - - std::cout << "\n🎉 Unified system test PASSED!" << std::endl; - return 0; - - } catch (const std::exception& e) { - std::cerr << "❌ Test failed: " << e.what() << std::endl; - return 1; - } -} \ No newline at end of file diff --git a/HYBRID_SIZE_SYSTEM.md b/docs/02-systems/HYBRID_SIZE_SYSTEM.md similarity index 100% rename from HYBRID_SIZE_SYSTEM.md rename to docs/02-systems/HYBRID_SIZE_SYSTEM.md diff --git a/docs/02-systems/SIZE_CONSTRAINTS_GUIDE.md b/docs/02-systems/SIZE_CONSTRAINTS_GUIDE.md new file mode 100644 index 0000000..627ec1c --- /dev/null +++ b/docs/02-systems/SIZE_CONSTRAINTS_GUIDE.md @@ -0,0 +1,166 @@ +# 📏 Size Constraints Guide + +## Overview + +Le système IUI supporte maintenant les **contraintes de taille en pixels** pour tous les types de fenêtres et docks. + +## ⚙️ Types de contraintes + +### **min_size** - Taille minimum +```json +{ + "min_size": {"width": 200, "height": 150} +} +``` +- Empêche l'utilisateur de rendre la fenêtre trop petite +- Garantit que le contenu reste utilisable +- **Obligatoire** pour les fenêtres critiques (console, alerts) + +### **max_size** - Taille maximum +```json +{ + "max_size": {"width": 800, "height": 600} +} +``` +- Empêche les fenêtres de dominer l'écran +- Maintient la cohérence de l'interface +- Utile pour les popups et dialogs + +### **size** - Taille initiale +```json +{ + "size": {"width": 400, "height": 300} +} +``` +- Taille au moment de la création +- Sera **clampée** entre min_size et max_size +- Si hors limites, ajustée automatiquement + +## 🏗️ Usage par type de fenêtre + +### **Docks** +```cpp +ui->createDock("sidebar", DockType::TABBED, DockPosition::LEFT, { + {"size", {{"width", 300}}}, + {"min_size", {{"width", 200}, {"height", 300}}}, + {"max_size", {{"width", 500}, {"height", 1000}}}, + {"resizable", true} +}); +``` + +### **Splits** +```cpp +ui->createSplit("main_split", Orientation::HORIZONTAL, { + {"min_panel_size", 80}, // Chaque panel min 80px + {"min_size", {{"width", 600}, {"height", 400}}}, // Split total min 600x400 + {"split_ratio", 0.6} // 60% / 40% +}); +``` + +### **Content Windows** +```cpp +ui->showData(DataType::ECONOMY, { + {"content", {...}}, + {"window", { + {"id", "economy_dash"}, + {"size", {{"width", 350}, {"height", 250}}}, + {"min_size", {{"width", 300}, {"height", 200}}}, // Lisibilité + {"max_size", {{"width", 600}, {"height", 400}}}, // Pas trop invasif + {"resizable", true} + }} +}); +``` + +### **Floating Windows** +```cpp +ui->showData(DataType::ALERTS, { + {"content", {...}}, + {"window", { + {"floating", true}, + {"size", {{"width", 400}, {"height", 200}}}, + {"min_size", {{"width", 320}, {"height", 150}}}, // Alert lisible + {"max_size", {{"width", 600}, {"height", 300}}}, // Pas trop grosse + {"closeable", true} + }} +}); +``` + +## 📋 Recommandations par usage + +### **Console/Log windows** +- **min_size**: `{"width": 400, "height": 100}` (au moins 3-4 lignes) +- **max_size**: `{"width": 2000, "height": 300}` (pas trop haute) + +### **Economy/Data tables** +- **min_size**: `{"width": 250, "height": 200}` (colonnes lisibles) +- **max_size**: `{"width": 500, "height": 600}` (pas trop large) + +### **Maps/Graphics** +- **min_size**: `{"width": 300, "height": 300}` (détails visibles) +- **max_size**: `{"width": 1200, "height": 1200}` (performance) + +### **Inventory grids** +- **min_size**: `{"width": 200, "height": 150}` (grid 2x2 minimum) +- **max_size**: `{"width": 400, "height": 500}` (pas trop de scroll) + +### **Settings/Dialogs** +- **min_size**: `{"width": 320, "height": 240}` (tous contrôles visibles) +- **max_size**: `{"width": 500, "height": 400}` (taille raisonnable) + +### **Alert popups** +- **min_size**: `{"width": 300, "height": 120}` (texte lisible) +- **max_size**: `{"width": 500, "height": 250}` (pas invasif) + +## 🔄 Comportement automatique + +### **Clamping** +Si `size` est hors des limites : +```cpp +// Taille demandée : 100x50 +// min_size : 200x150 +// max_size : 800x600 +// → Résultat : 200x150 (clampée au minimum) +``` + +### **Resize interactif** +- L'utilisateur ne peut **jamais** redimensionner en dessous de `min_size` +- L'utilisateur ne peut **jamais** redimensionner au-dessus de `max_size` +- Les **cursors de resize** changent quand les limites sont atteintes + +### **Split constraints** +```cpp +{ + "min_panel_size": 80, // Chaque panel minimum 80px + "split_ratio": 0.7 // Mais peut être ajusté si ça viole min_panel_size +} +``` + +## ⚡ Performance + +- **Enums** pour types communs = comparaisons int rapides +- **JSON** pour config flexible = parse une fois à la création +- **Pixel constraints** appliquées côté implémentation (ImGui, HTML, etc.) +- **Zero overhead** si pas de contraintes spécifiées + +## 🎯 Exemple complet + +```cpp +// Créer layout avec contraintes +ui->createDock("main_sidebar", DockType::TABBED, DockPosition::LEFT, { + {"min_size", {{"width", 250}, {"height", 400}}}, + {"max_size", {{"width", 500}, {"height", 1000}}} +}); + +// Ajouter contenu avec contraintes +ui->showData(DataType::ECONOMY, { + {"content", {{"prices", {...}}}}, + {"window", { + {"parent", "main_sidebar"}, + {"dock", "tab"}, + {"min_size", {{"width", 240}, {"height", 200}}}, + {"max_size", {{"width", 450}, {"height", 600}}} + }} +}); +``` + +**Résultat** : Interface qui reste **utilisable** à toutes les tailles ! 🚀 \ No newline at end of file diff --git a/ADVANCED_TESTING.md b/docs/03-implementation/ADVANCED_TESTING.md similarity index 100% rename from ADVANCED_TESTING.md rename to docs/03-implementation/ADVANCED_TESTING.md diff --git a/AUTOMATION_GUIDE.md b/docs/03-implementation/AUTOMATION_GUIDE.md similarity index 100% rename from AUTOMATION_GUIDE.md rename to docs/03-implementation/AUTOMATION_GUIDE.md diff --git a/CLAUDE-HOT-RELOAD-GUIDE.md b/docs/03-implementation/CLAUDE-HOT-RELOAD-GUIDE.md similarity index 100% rename from CLAUDE-HOT-RELOAD-GUIDE.md rename to docs/03-implementation/CLAUDE-HOT-RELOAD-GUIDE.md diff --git a/docs/Sources Documentaires/SMP.md b/docs/Sources Documentaires/SMP.md new file mode 100644 index 0000000..328ce7b --- /dev/null +++ b/docs/Sources Documentaires/SMP.md @@ -0,0 +1,173 @@ +Sociétés Militaires Privées : Analyse Stratégique et Étude de Cas d'Executive Outcomes + +Synthèse Exécutive + +Ce document de synthèse analyse le phénomène croissant des Sociétés Militaires Privées (SMP), des entités qui opèrent dans des secteurs traditionnellement réservés aux forces armées étatiques. Poussé par des logiques économiques post-Guerre Froide, des impératifs de discrétion politique et la volonté de contourner les contraintes légales, le recours aux SMP s'est intensifié depuis les années 1980. + +Le secteur se caractérise par une grande diversité de modèles. Le modèle américain privilégie le soutien logistique aux armées régulières, tandis que le modèle chinois, en pleine expansion, est dédié à la protection des intérêts économiques de l'État. Le modèle russe, incarné par le groupe Wagner, est une forme hybride, agissant à la fois en soutien de l'armée et de manière autonome pour des objectifs géopolitiques et économiques. + +L'archétype du modèle sud-africain est Executive Outcomes (EO), une SMP qui a démontré une efficacité redoutable dans les années 1990. Son étude de cas révèle un modèle d'affaires sophistiqué, intégrant verticalement les opérations militaires, l'exploitation de ressources naturelles (pétrole, diamants) et une structure corporative complexe conçue pour maximiser les profits tout en naviguant dans les zones grises du droit international. Fondée par d'anciens membres des forces spéciales sud-africaines de l'ère de l'apartheid, EO a mené des campagnes militaires autonomes en Angola et en Sierra Leone, liant directement ses succès militaires à l'obtention de concessions minières et pétrolières. + +Cependant, l'emploi des SMP soulève de graves questions éthiques et stratégiques : violations des droits humains (massacre de la place Nissour, torture à Abou Ghraib), guerres par procuration entre puissances, perte de compétences pour les armées nationales et manque de transparence. L'avenir du secteur est appelé à se développer, notamment avec l'émergence d'un vaste contingent de combattants expérimentés issus de la guerre en Ukraine, promettant une nouvelle ère de complexité dans les conflits mondiaux. + + +-------------------------------------------------------------------------------- + + +1. Le Phénomène des Sociétés Militaires Privées (SMP) + +1.1. Définition et Spectre d'Activités + +Une Société Militaire Privée (SMP) est une entreprise privée qui fournit des services et des compétences de nature militaire ou opérant dans un contexte militarisé. Leurs activités couvrent un large spectre : + +* Soutien logistique aux armées régulières. +* Conseil et formation de forces armées étrangères. +* Protection de personnes (VIP), de biens et de convois. +* Gardiennage d'infrastructures critiques (champs pétroliers, mines). +* Participation directe aux combats et opérations offensives. + +1.2. Distinction avec le Mercenariat Traditionnel + +Le statut juridique des SMP est ambigu, leur permettant souvent d'échapper à la définition stricte du mercenariat. + +* Article 47 du protocole additionnel de 1977 aux Conventions de Genève : Définit un mercenaire comme un combattant recruté spécifiquement pour un conflit, qui n'est pas ressortissant d'une des parties au conflit, et dont la rémunération est nettement supérieure à celle d'un militaire de rang similaire. +* Conventions Internationales : La Convention de l'Organisation de l'Unité Africaine de 1977 et la Convention de l'ONU de 2001 tentent d'encadrer le mercenariat, mais cette dernière n'a été ratifiée que par huit États et a peu d'impact. + +En pratique, les grandes SMP structurent leurs activités pour ne pas être considérées légalement comme du mercenariat, bien que la distinction sur le terrain soit souvent ténue. + +1.3. Aperçu Historique + +L'emploi d'acteurs militaires privés par des États n'est pas nouveau et remonte à plusieurs décennies avant l'ère contemporaine. + +* Seconde Guerre mondiale (1940) : L'entreprise américaine Central Aircraft Manufacturing Company (CAMC) monte l'escadrille des "Flying Tigers" pour soutenir la Chine contre le Japon. +* Guerre du Vietnam : L'entreprise Civil Air Transport ("Air America"), héritière de la CAMC, collabore avec la CIA pour des opérations au Vietnam. +* Années 1960-70 : + * Watchgard International Limited (1966) : Créée par David Sterling, fondateur des SAS britanniques, elle propose des formations et participe à des combats en Amérique du Sud, en Afrique et au Moyen-Orient. + * Kini Mini Services (1975) : Cette SMP britannique forme les moudjahidines afghans pour combattre l'URSS. + +2. Modèles Opérationnels des SMP à l'Échelle Mondiale + +2.1. Le Modèle Sud-Africain + +Représenté par Executive Outcomes, ce modèle est le plus proche du mercenariat traditionnel. + +* Caractéristiques : Mène des campagnes militaires autonomes, souvent pour le compte d'États en difficulté. +* Financement : Se finance via les contrats étatiques ou directement par l'exploitation des ressources naturelles (ex: mines de diamants en Sierra Leone) qu'elle est chargée de protéger. +* Motivation : Principalement lucrative, mais des variantes idéologiques existent, comme Malhama Tactical, une SMP djihadiste offrant ses services à des groupes islamistes en Syrie. + +2.2. Le Modèle Américain + +Ce modèle se concentre sur le soutien aux forces armées régulières, principalement celles des États-Unis. + +* Rôle : Fournir des services annexes (logistique, gardiennage, protection de VIP, transport) pour permettre à l'armée de se concentrer sur le combat. +* Exemple emblématique : La société Blackwater (devenue Academi), massivement employée en Irak et en Afghanistan. Elle a également été utilisée pour des actions offensives en collaboration avec la CIA et les forces spéciales. + +2.3. Le Modèle Russe + +Incarné par le groupe Wagner, il s'agit d'un modèle hybride combinant les approches américaine et sud-africaine. + +* Dualité : Peut intervenir en soutien de l'armée régulière russe (comme en Ukraine) ou mener des opérations autonomes pour promouvoir les intérêts géopolitiques de la Russie, notamment en Afrique. +* Activités diversifiées : Combat de haute intensité, protection de ressources, propagande, renseignement, et lutte anti-guérilla. +* Structure Corporative : Wagner fait partie d'un écosystème d'entreprises avec des intérêts dans le secteur minier. D'autres entités russes, comme le géant gazier Gazprom, possèdent également leur propre SMP. +* Statut Légal : Bien que les SMP soient officiellement interdites par la loi russe, elles sont tolérées et utilisées par le pouvoir. + +2.4. Le Modèle Chinois + +Ce modèle, en pleine expansion, est entièrement au service des intérêts économiques et stratégiques de l'État chinois. + +* Cadre Légal : Les SMP sont légalisées depuis 2011 mais doivent obtenir une licence du gouvernement. +* Mission Principale : Protéger les infrastructures et le personnel chinois le long des "Nouvelles Routes de la Soie", ainsi que les navires contre la piraterie. +* Exemples d'entreprises : + * Huaing Chong An Security Service : Fournit la sécurité pour la première compagnie maritime chinoise, China Ocean Shipping Company. + * Beijing Dayway Security Services Company : Intervient en Afrique (ex: Kenya) pour sécuriser des projets financés par la Chine, et protège des clients comme la China National Petroleum et le réseau d'ambassades. +* Forces et Faiblesses : + * Avantage : Coût très compétitif (un contracteur chinois coûte jusqu'à 12 fois moins cher qu'un occidental). + * Faiblesses : Manque d'expérience de terrain et mauvaise maîtrise des langues étrangères. + +3. Motivations et Avantages du Recours aux SMP + +3.1. Facteurs Économiques + +La fin de la Guerre Froide a entraîné une réduction des budgets militaires (jusqu'à 30 % en France et aux États-Unis), rendant chaque soldat "plus rare et plus cher". Une idéologie libérale de désengagement de l'État a favorisé l'externalisation des fonctions de sécurité. Cette tendance est illustrée par l'évolution du ratio contracteurs/militaires dans les déploiements américains : + +* Guerre du Golfe (1991) : 1 contracteur pour 100 militaires. +* Début de la guerre d'Irak (2003) : 1 contracteur pour 10 militaires. +* Irak (2008) : 1 contracteur pour 1 militaire. + +3.2. Impératifs Politiques et Stratégiques + +* Plausible Déniabilité : Les SMP permettent de mener des opérations sensibles ("sale besogne") comme la déstabilisation d'États ou des assassinats. En cas d'échec ou de scandale, l'État mandataire peut nier toute implication. Exemple : les Émirats Arabes Unis ont employé la SMP américaine Spear Operations Group pour des assassinats au Yémen. +* Gestion de l'Opinion Publique : La mort d'un contracteur a un impact médiatique et public bien moindre que celle d'un soldat de l'armée régulière. Cela permet de minimiser le coût politique des interventions militaires. Exemple : en 2016 en Syrie, la Russie a déploré officiellement une trentaine de morts militaires contre 500 à 600 personnels de Wagner tués. +* Contournement des Limites : Les SMP permettent de dépasser les limites capacitaires ou légales imposées à une armée. Exemple : durant la guerre de Bosnie, le Congrès américain ayant limité le déploiement à 20 000 soldats, cette limite a été contournée par l'envoi de contracteurs. + +4. Controverses, Dérives et Enjeux + +4.1. Violations des Droits Humains et Crimes de Guerre + +* Incident de la Place Nissour (16 septembre 2007) : Des contracteurs de Blackwater ont ouvert le feu sur des civils à Bagdad, tuant 17 personnes et en blessant 20 autres. +* Prison d'Abou Ghraib : Les SMP CACI Group et Titan Corporation sont impliquées dans des actes de torture sur des prisonniers irakiens. + +4.2. Maltraitance des Contractuels + +Les contracteurs eux-mêmes peuvent être victimes d'abus. La SMP émiratie Blackshield a recruté 611 Soudanais sous prétexte d'un emploi dans la sécurité privée aux Émirats, avant de les envoyer de force combattre en Libye pour le Maréchal Haftar. L'opération a été annulée suite à un scandale déclenché lorsque les recrues ont pu contacter leurs familles. + +4.3. Guerres par Procuration et Prolifération + +Les SMP peuvent être les instruments de conflits par procuration. En Libye, la SMP turque SADAT a envoyé des combattants (parfois d'anciens djihadistes) pour lutter contre le Maréchal Haftar, tandis que les Émirats Arabes Unis envoyaient des combattants via Blackshield pour le soutenir. + +4.4. Usage Domestique et Répression Interne + +Les SMP peuvent être utilisées par un gouvernement contre sa propre population. La société turque SADAT a été impliquée dans la répression qui a suivi la tentative de coup d'État de 2016 contre le président Erdoğan. + +4.5. Perte de Compétences pour les Armées Régulières + +Les SMP recrutent massivement d'anciens militaires, mais aussi des militaires d'active, en particulier des unités d'élite, attirés par des salaires bien plus élevés. Ce "drain des cerveaux" affaiblit les armées régulières. Pour contrer ce phénomène, le Royaume-Uni a expérimenté un programme permettant à ses militaires de travailler pour une SMP pendant 1 ou 2 ans avant de réintégrer l'armée. + +5. Étude de Cas Approfondie : Executive Outcomes (EO) + +5.1. Genèse et Contexte + +Executive Outcomes, fondée en 1989 par Eeben Barlow, est née des cendres du système de sécurité de l'Afrique du Sud de l'apartheid. + +* Origines du Personnel : Barlow et ses recrues étaient issus d'unités d'élite et secrètes comme le Bataillon 32 (une unité de contre-insurrection composée d'Angolais et d'officiers blancs sud-africains) et le Civil Cooperation Bureau (CCB), une cellule clandestine chargée d'assassiner des opposants au régime. +* Premier Contrat Majeur (1993) : Engagée en Angola pour reprendre des installations pétrolières à l'UNITA. Ironiquement, les mêmes hommes qui, au sein du Bataillon 32, soutenaient l'UNITA contre le MPLA (soutenu par les communistes), se sont retrouvés à combattre l'UNITA pour le compte du gouvernement MPLA, démontrant que les intérêts financiers priment sur l'idéologie. + +5.2. Le Modèle d'Affaires : Intégration Militaro-Industrielle + +Le succès d'EO reposait sur une synergie parfaite entre la force militaire et l'exploitation économique. + +* Angola (1994) : EO repousse une offensive de l'UNITA sur la capitale Luanda. En paiement, la société reçoit 40 millions de dollars par an ainsi que des concessions pétrolières et diamantaires. +* Sierra Leone (1996) : Le gouvernement engage EO pour repousser les rebelles du RUF. En échange, des sociétés liées à EO obtiennent d'importantes concessions sur les mines de diamants que les mercenaires sécurisent. + +5.3. Une Galaxie d'Entreprises : Structure et Acteurs Clés + +EO n'était que la partie visible d'un vaste conglomérat de plus de 30 sociétés. + +Entité Rôle et Description Personnages Clés +Executive Outcomes (EO) Branche militaire opérationnelle. Fournissait les hommes, le matériel et l'expertise. Eeben Barlow, Lafras Luitingh +Strategic Resources Corp. (SRC) Holding sud-africaine créée en 1995 pour chapeauter les activités africaines. Eeben Barlow +Sandline International SMP britannique utilisée comme "vitrine" pour signer des contrats et gérer les relations publiques. Sous-traitait les opérations à EO. Tim Spicer, Simon Mann +Heritage Oil and Gas Compagnie pétrolière dirigée par le contact britannique qui a fourni à EO son premier contrat. Anthony Buckingham +Branch Energy Branche minière du groupe, détenant des concessions en Angola, Sierra Leone, etc. Anthony Buckingham +Diamond Works Limited Née en 1996 de la fusion des actifs de Branch Energy et d'une société canadienne, pour exploiter les concessions de diamants. Anthony Buckingham, Eeben Barlow, Tim Spicer + +5.4. Le Déclin et la Reconversion + +La fin des années 1990 marque le déclin officiel d'EO. + +* Affaire de Papouasie-Nouvelle-Guinée (1997) : Un contrat signé par Sandline (sous-traitant EO) est révélé par la presse, provoquant un scandale politique majeur, une mutinerie et la démission du Premier ministre. +* Législation Sud-Africaine (1997) : Une nouvelle loi bannissant le mercenariat contraint EO à cesser officiellement ses activités en 1998. + +Cependant, les fondateurs ont poursuivi leurs carrières dans le secteur : + +* Eeben Barlow : Après une période de consulting, il fonde STTEP en 2006, qui combat Boko Haram au Nigéria (2015) et des djihadistes au Mozambique (2020). En 2020, il annonce la relance d'Executive Outcomes, la positionnant comme une solution "africaine pour les Africains". +* Tim Spicer : Fonde Aegis Defence Services en 2002. +* Simon Mann : Est arrêté au Zimbabwe en 2004 pour une tentative présumée de coup d'État en Guinée Équatoriale. Il est libéré en 2009 et meurt en mai 2025. +* Lafras Luitingh : Crée d'autres SMP comme Sarasen et Sterling Corporate, actives dans le secteur minier et la lutte anti-piraterie. + +6. Perspectives et Avenir du Secteur + +Le secteur des SMP est en constante évolution et devrait connaître une nouvelle phase d'expansion. + +* Impact de la Guerre en Ukraine : Le conflit a créé un immense vivier de combattants (estimé entre 250 000 et 300 000 Ukrainiens) dotés d'une expérience de combat de haute intensité, maîtrisant à la fois les technologies modernes (drones) et les équipements plus anciens. +* Demande Croissante : Les Ukrainiens figurent déjà dans le top 5 des nationalités les plus employées par les SMP. Ces vétérans très expérimentés pourront "se vendre cher" sur le marché mondial de la sécurité privée, complexifiant davantage les dynamiques des futurs conflits. diff --git a/external/imgui b/external/imgui new file mode 160000 index 0000000..d6cb3c9 --- /dev/null +++ b/external/imgui @@ -0,0 +1 @@ +Subproject commit d6cb3c923d28dcebb2d8d9605ccc7229ccef19eb diff --git a/external/nlohmann/json.hpp b/external/nlohmann/json.hpp new file mode 100644 index 0000000..8b72ea6 --- /dev/null +++ b/external/nlohmann/json.hpp @@ -0,0 +1,24765 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#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__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(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__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template