diff --git a/CMakeLists.txt b/CMakeLists.txt index 08369fd..4cc2490 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,9 @@ configure_file(${CMAKE_SOURCE_DIR}/source/project.h.in ${CMAKE_BINARY_DIR}/proje # --- LISTA DE FUENTES --- set(APP_SOURCES source/main.cpp + source/core/system/director.cpp source/core/rendering/sdl_manager.cpp + source/game/options.cpp source/game/joc_asteroides.cpp source/core/rendering/primitives.cpp ) diff --git a/source/core/rendering/sdl_manager.cpp b/source/core/rendering/sdl_manager.cpp index 0916c4f..9126ba9 100644 --- a/source/core/rendering/sdl_manager.cpp +++ b/source/core/rendering/sdl_manager.cpp @@ -3,210 +3,287 @@ #include "sdl_manager.hpp" #include "core/defaults.hpp" +#include "game/options.hpp" #include "project.h" -#include #include #include +#include SDLManager::SDLManager() - : finestra_(nullptr) - , renderer_(nullptr) - , current_width_(Defaults::Window::WIDTH) - , current_height_(Defaults::Window::HEIGHT) - , is_fullscreen_(false) - , max_width_(1920) - , max_height_(1080) -{ - // Inicialitzar SDL3 - if (!SDL_Init(SDL_INIT_VIDEO)) { - std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl; - return; - } + : finestra_(nullptr), renderer_(nullptr), + current_width_(Defaults::Window::WIDTH), + current_height_(Defaults::Window::HEIGHT), is_fullscreen_(false), + max_width_(1920), max_height_(1080) { + // Inicialitzar SDL3 + if (!SDL_Init(SDL_INIT_VIDEO)) { + std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl; + return; + } - // Calcular mida màxima des del display - calculateMaxWindowSize(); + // Calcular mida màxima des del display + calculateMaxWindowSize(); - // Construir títol dinàmic igual que en pollo - std::string window_title = std::format("{} v{} ({})", - Project::LONG_NAME, - Project::VERSION, - Project::COPYRIGHT - ); + // Construir títol dinàmic igual que en pollo + std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, + Project::VERSION, Project::COPYRIGHT); - // Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED) - finestra_ = SDL_CreateWindow( - window_title.c_str(), - current_width_, - current_height_, - SDL_WINDOW_RESIZABLE // Permetre resize manual també - ); + // Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED) + finestra_ = + SDL_CreateWindow(window_title.c_str(), current_width_, current_height_, + SDL_WINDOW_RESIZABLE // Permetre resize manual també + ); - if (!finestra_) { - std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl; - SDL_Quit(); - return; - } + if (!finestra_) { + std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl; + SDL_Quit(); + return; + } - // IMPORTANT: Centrar explícitament la finestra - SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + // IMPORTANT: Centrar explícitament la finestra + SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED); - // Crear renderer amb acceleració - renderer_ = SDL_CreateRenderer(finestra_, nullptr); + // Crear renderer amb acceleració + renderer_ = SDL_CreateRenderer(finestra_, nullptr); - if (!renderer_) { - std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl; - SDL_DestroyWindow(finestra_); - SDL_Quit(); - return; - } + if (!renderer_) { + std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl; + SDL_DestroyWindow(finestra_); + SDL_Quit(); + return; + } - // CRÍTIC: Configurar viewport scaling - updateLogicalPresentation(); + // CRÍTIC: Configurar viewport scaling + updateLogicalPresentation(); - std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_ - << " (logic: " << Defaults::Game::WIDTH << "x" << Defaults::Game::HEIGHT << ")" << std::endl; + std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_ + << " (logic: " << Defaults::Game::WIDTH << "x" + << Defaults::Game::HEIGHT << ")" << std::endl; +} + +// Constructor amb configuració +SDLManager::SDLManager(int width, int height, bool fullscreen) + : finestra_(nullptr), renderer_(nullptr), current_width_(width), + current_height_(height), is_fullscreen_(fullscreen), max_width_(1920), + max_height_(1080) { + // Inicialitzar SDL3 + if (!SDL_Init(SDL_INIT_VIDEO)) { + std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl; + return; + } + + // Calcular mida màxima des del display + calculateMaxWindowSize(); + + // Construir títol dinàmic + std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, + Project::VERSION, Project::COPYRIGHT); + + // Configurar flags de la finestra + SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE; + if (is_fullscreen_) { + flags = static_cast(flags | SDL_WINDOW_FULLSCREEN); + } + + // Crear finestra + finestra_ = SDL_CreateWindow(window_title.c_str(), current_width_, + current_height_, flags); + + if (!finestra_) { + std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl; + SDL_Quit(); + return; + } + + // Centrar explícitament la finestra (si no és fullscreen) + if (!is_fullscreen_) { + SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED); + } + + // Crear renderer amb acceleració + renderer_ = SDL_CreateRenderer(finestra_, nullptr); + + if (!renderer_) { + std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl; + SDL_DestroyWindow(finestra_); + SDL_Quit(); + return; + } + + // Configurar viewport scaling + updateLogicalPresentation(); + + std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_ + << " (logic: " << Defaults::Game::WIDTH << "x" + << Defaults::Game::HEIGHT << ")"; + if (is_fullscreen_) { + std::cout << " [FULLSCREEN]"; + } + std::cout << std::endl; } SDLManager::~SDLManager() { - if (renderer_) { - SDL_DestroyRenderer(renderer_); - renderer_ = nullptr; - } + if (renderer_) { + SDL_DestroyRenderer(renderer_); + renderer_ = nullptr; + } - if (finestra_) { - SDL_DestroyWindow(finestra_); - finestra_ = nullptr; - } + if (finestra_) { + SDL_DestroyWindow(finestra_); + finestra_ = nullptr; + } - SDL_Quit(); - std::cout << "SDL3 netejat correctament" << std::endl; + SDL_Quit(); + std::cout << "SDL3 netejat correctament" << std::endl; } void SDLManager::calculateMaxWindowSize() { - SDL_DisplayID display = SDL_GetPrimaryDisplay(); - const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display); + SDL_DisplayID display = SDL_GetPrimaryDisplay(); + const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display); - if (mode) { - // Deixar marge de 100px per a decoracions de l'OS - max_width_ = mode->w - 100; - max_height_ = mode->h - 100; - std::cout << "Display detectat: " << mode->w << "x" << mode->h - << " (max finestra: " << max_width_ << "x" << max_height_ << ")" << std::endl; - } else { - // Fallback conservador - max_width_ = 1920; - max_height_ = 1080; - std::cerr << "No s'ha pogut detectar el display, usant fallback: " - << max_width_ << "x" << max_height_ << std::endl; - } + if (mode) { + // Deixar marge de 100px per a decoracions de l'OS + max_width_ = mode->w - 100; + max_height_ = mode->h - 100; + std::cout << "Display detectat: " << mode->w << "x" << mode->h + << " (max finestra: " << max_width_ << "x" << max_height_ << ")" + << std::endl; + } else { + // Fallback conservador + max_width_ = 1920; + max_height_ = 1080; + std::cerr << "No s'ha pogut detectar el display, usant fallback: " + << max_width_ << "x" << max_height_ << std::endl; + } } void SDLManager::updateLogicalPresentation() { - // AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480, - // SDL escala automàticament a la mida física de la finestra - SDL_SetRenderLogicalPresentation( - renderer_, - Defaults::Game::WIDTH, // 640 (lògic) - Defaults::Game::HEIGHT, // 480 (lògic) - SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3 - ); + // AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480, + // SDL escala automàticament a la mida física de la finestra + SDL_SetRenderLogicalPresentation( + renderer_, + Defaults::Game::WIDTH, // 640 (lògic) + Defaults::Game::HEIGHT, // 480 (lògic) + SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3 + ); } void SDLManager::increaseWindowSize() { - if (is_fullscreen_) return; // No operar en fullscreen + if (is_fullscreen_) + return; // No operar en fullscreen - int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT; - int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT; + int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT; + int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT; - // Clamp a màxim - new_width = std::min(new_width, max_width_); - new_height = std::min(new_height, max_height_); + // Clamp a màxim + new_width = std::min(new_width, max_width_); + new_height = std::min(new_height, max_height_); - if (new_width != current_width_ || new_height != current_height_) { - applyWindowSize(new_width, new_height); - std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height << std::endl; - } + if (new_width != current_width_ || new_height != current_height_) { + applyWindowSize(new_width, new_height); + + // Persistir canvis a Options (es guardarà a config.yaml al tancar) + Options::window.width = current_width_; + Options::window.height = current_height_; + + std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height + << std::endl; + } } void SDLManager::decreaseWindowSize() { - if (is_fullscreen_) return; + if (is_fullscreen_) + return; - int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT; - int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT; + int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT; + int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT; - // Clamp a mínim - new_width = std::max(new_width, Defaults::Window::MIN_WIDTH); - new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT); + // Clamp a mínim + new_width = std::max(new_width, Defaults::Window::MIN_WIDTH); + new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT); - if (new_width != current_width_ || new_height != current_height_) { - applyWindowSize(new_width, new_height); - std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height << std::endl; - } + if (new_width != current_width_ || new_height != current_height_) { + applyWindowSize(new_width, new_height); + + // Persistir canvis a Options (es guardarà a config.yaml al tancar) + Options::window.width = current_width_; + Options::window.height = current_height_; + + std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height + << std::endl; + } } void SDLManager::applyWindowSize(int new_width, int new_height) { - // Obtenir posició actual ABANS del resize - int old_x, old_y; - SDL_GetWindowPosition(finestra_, &old_x, &old_y); + // Obtenir posició actual ABANS del resize + int old_x, old_y; + SDL_GetWindowPosition(finestra_, &old_x, &old_y); - int old_width = current_width_; - int old_height = current_height_; + int old_width = current_width_; + int old_height = current_height_; - // Actualitzar mida - SDL_SetWindowSize(finestra_, new_width, new_height); - current_width_ = new_width; - current_height_ = new_height; + // Actualitzar mida + SDL_SetWindowSize(finestra_, new_width, new_height); + current_width_ = new_width; + current_height_ = new_height; - // CENTRADO INTEL·LIGENT (algoritme de pollo) - // Calcular nova posició per mantenir la finestra centrada sobre si mateixa - int delta_width = old_width - new_width; - int delta_height = old_height - new_height; + // CENTRADO INTEL·LIGENT (algoritme de pollo) + // Calcular nova posició per mantenir la finestra centrada sobre si mateixa + int delta_width = old_width - new_width; + int delta_height = old_height - new_height; - int new_x = old_x + (delta_width / 2); - int new_y = old_y + (delta_height / 2); + int new_x = old_x + (delta_width / 2); + int new_y = old_y + (delta_height / 2); - // Evitar que la finestra surti de la pantalla - constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol - new_x = std::max(new_x, 0); - new_y = std::max(new_y, TITLEBAR_HEIGHT); + // Evitar que la finestra surti de la pantalla + constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol + new_x = std::max(new_x, 0); + new_y = std::max(new_y, TITLEBAR_HEIGHT); - SDL_SetWindowPosition(finestra_, new_x, new_y); + SDL_SetWindowPosition(finestra_, new_x, new_y); - // NO cal actualitzar el logical presentation aquí, - // SDL ho maneja automàticament + // NO cal actualitzar el logical presentation aquí, + // SDL ho maneja automàticament } void SDLManager::toggleFullscreen() { - is_fullscreen_ = !is_fullscreen_; - SDL_SetWindowFullscreen(finestra_, is_fullscreen_); + is_fullscreen_ = !is_fullscreen_; + SDL_SetWindowFullscreen(finestra_, is_fullscreen_); - std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat") << std::endl; + // Persistir canvis a Options (es guardarà a config.yaml al tancar) + Options::window.fullscreen = is_fullscreen_; - // En fullscreen, SDL gestiona tot automàticament - // En sortir, restaura la mida anterior + std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat") + << std::endl; + + // En fullscreen, SDL gestiona tot automàticament + // En sortir, restaura la mida anterior } -bool SDLManager::handleWindowEvent(const SDL_Event& event) { - if (event.type == SDL_EVENT_WINDOW_RESIZED) { - // Usuari ha redimensionat manualment (arrossegar vora) - // Actualitzar el nostre tracking - SDL_GetWindowSize(finestra_, ¤t_width_, ¤t_height_); - std::cout << "Finestra redimensionada manualment a " - << current_width_ << "x" << current_height_ << std::endl; - return true; - } - return false; +bool SDLManager::handleWindowEvent(const SDL_Event &event) { + if (event.type == SDL_EVENT_WINDOW_RESIZED) { + // Usuari ha redimensionat manualment (arrossegar vora) + // Actualitzar el nostre tracking + SDL_GetWindowSize(finestra_, ¤t_width_, ¤t_height_); + std::cout << "Finestra redimensionada manualment a " << current_width_ + << "x" << current_height_ << std::endl; + return true; + } + return false; } void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) { - if (!renderer_) return; + if (!renderer_) + return; - SDL_SetRenderDrawColor(renderer_, r, g, b, 255); - SDL_RenderClear(renderer_); + SDL_SetRenderDrawColor(renderer_, r, g, b, 255); + SDL_RenderClear(renderer_); } void SDLManager::presenta() { - if (!renderer_) return; + if (!renderer_) + return; - SDL_RenderPresent(renderer_); + SDL_RenderPresent(renderer_); } diff --git a/source/core/rendering/sdl_manager.hpp b/source/core/rendering/sdl_manager.hpp index fdbacd1..68d6467 100644 --- a/source/core/rendering/sdl_manager.hpp +++ b/source/core/rendering/sdl_manager.hpp @@ -9,41 +9,44 @@ class SDLManager { public: - SDLManager(); - ~SDLManager(); + SDLManager(); // Constructor per defecte (usa Defaults::) + SDLManager(int width, int height, + bool fullscreen); // Constructor amb configuració + ~SDLManager(); - // No permetre còpia ni assignació - SDLManager(const SDLManager&) = delete; - SDLManager& operator=(const SDLManager&) = delete; + // No permetre còpia ni assignació + SDLManager(const SDLManager &) = delete; + SDLManager &operator=(const SDLManager &) = delete; - // [NUEVO] Gestió de finestra dinàmica - void increaseWindowSize(); // F2: +100px - void decreaseWindowSize(); // F1: -100px - void toggleFullscreen(); // F3 - bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED + // [NUEVO] Gestió de finestra dinàmica + void increaseWindowSize(); // F2: +100px + void decreaseWindowSize(); // F1: -100px + void toggleFullscreen(); // F3 + bool + handleWindowEvent(const SDL_Event &event); // Per a SDL_EVENT_WINDOW_RESIZED - // Funcions principals (renderitzat) - void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0); - void presenta(); + // Funcions principals (renderitzat) + void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0); + void presenta(); - // Getters - SDL_Renderer* obte_renderer() { return renderer_; } + // Getters + SDL_Renderer *obte_renderer() { return renderer_; } private: - SDL_Window* finestra_; - SDL_Renderer* renderer_; + SDL_Window *finestra_; + SDL_Renderer *renderer_; - // [NUEVO] Estat de la finestra - int current_width_; // Mida física actual - int current_height_; - bool is_fullscreen_; - int max_width_; // Calculat des del display - int max_height_; + // [NUEVO] Estat de la finestra + int current_width_; // Mida física actual + int current_height_; + bool is_fullscreen_; + int max_width_; // Calculat des del display + int max_height_; - // [NUEVO] Funcions internes - void calculateMaxWindowSize(); // Llegir resolució del display - void applyWindowSize(int width, int height); // Canviar mida + centrar - void updateLogicalPresentation(); // Actualitzar viewport + // [NUEVO] Funcions internes + void calculateMaxWindowSize(); // Llegir resolució del display + void applyWindowSize(int width, int height); // Canviar mida + centrar + void updateLogicalPresentation(); // Actualitzar viewport }; #endif // SDL_MANAGER_HPP diff --git a/source/external/fkyaml_node.hpp b/source/external/fkyaml_node.hpp new file mode 100644 index 0000000..8791774 --- /dev/null +++ b/source/external/fkyaml_node.hpp @@ -0,0 +1,15659 @@ +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_NODE_HPP +#define FK_YAML_NODE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_MACROS_DEFINE_MACROS_HPP +#define FK_YAML_DETAIL_MACROS_DEFINE_MACROS_HPP + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +// Check version definitions if already defined. +#if defined(FK_YAML_MAJOR_VERSION) && defined(FK_YAML_MINOR_VERSION) && \ + defined(FK_YAML_PATCH_VERSION) +#if FK_YAML_MAJOR_VERSION != 0 || FK_YAML_MINOR_VERSION != 4 || \ + FK_YAML_PATCH_VERSION != 2 +#warning Already included a different version of the fkYAML library! +#else +// define macros to skip defining macros down below. +#define FK_YAML_VERCHECK_SUCCEEDED +#endif +#endif + +#ifndef FK_YAML_VERCHECK_SUCCEEDED + +#define FK_YAML_MAJOR_VERSION 0 +#define FK_YAML_MINOR_VERSION 4 +#define FK_YAML_PATCH_VERSION 2 + +#define FK_YAML_NAMESPACE_VERSION_CONCAT_IMPL(major, minor, patch) \ + v##major##_##minor##_##patch + +#define FK_YAML_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + FK_YAML_NAMESPACE_VERSION_CONCAT_IMPL(major, minor, patch) + +#define FK_YAML_NAMESPACE_VERSION \ + FK_YAML_NAMESPACE_VERSION_CONCAT( \ + FK_YAML_MAJOR_VERSION, FK_YAML_MINOR_VERSION, FK_YAML_PATCH_VERSION) + +#define FK_YAML_NAMESPACE_BEGIN \ + namespace fkyaml { \ + inline namespace FK_YAML_NAMESPACE_VERSION { + +#define FK_YAML_NAMESPACE_END \ + } /* inline namespace FK_YAML_NAMESPACE_VERSION */ \ + } // namespace fkyaml + +#define FK_YAML_DETAIL_NAMESPACE_BEGIN \ + FK_YAML_NAMESPACE_BEGIN \ + namespace detail { + +#define FK_YAML_DETAIL_NAMESPACE_END \ + } /* namespace detail */ \ + FK_YAML_NAMESPACE_END + +#endif // !defined(FK_YAML_VERCHECK_SUCCEEDED) + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_MACROS_CPP_CONFIG_MACROS_HPP +#define FK_YAML_DETAIL_MACROS_CPP_CONFIG_MACROS_HPP + +// This file is assumed to be included only by version_macros.hpp file. +// To avoid redundant inclusion, do not include version_macros.hpp file as the +// other files do. + +// With the MSVC compilers, the value of __cplusplus is by default always +// "199611L"(C++98). To avoid that, the library instead references _MSVC_LANG +// which is always set a correct value. See +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +// for more details. +#if defined(_MSVC_LANG) && !defined(__clang__) +#define FK_YAML_CPLUSPLUS _MSVC_LANG +#else +#define FK_YAML_CPLUSPLUS __cplusplus +#endif + +// C++ language standard detection +// Skip detection if the definitions listed below already exist. +#if !defined(FK_YAML_HAS_CXX_23) && !defined(FK_YAML_HAS_CXX_20) && \ + !defined(FK_YAML_HAS_CXX_17) && !defined(FK_YAML_HAS_CXX_14) && \ + !defined(FK_YAML_CXX_11) +#if FK_YAML_CPLUSPLUS >= 202302L +#define FK_YAML_HAS_CXX_23 +#define FK_YAML_HAS_CXX_20 +#define FK_YAML_HAS_CXX_17 +#define FK_YAML_HAS_CXX_14 +#elif FK_YAML_CPLUSPLUS >= 202002L +#define FK_YAML_HAS_CXX_20 +#define FK_YAML_HAS_CXX_17 +#define FK_YAML_HAS_CXX_14 +#elif FK_YAML_CPLUSPLUS >= 201703L +#define FK_YAML_HAS_CXX_17 +#define FK_YAML_HAS_CXX_14 +#elif FK_YAML_CPLUSPLUS >= 201402L +#define FK_YAML_HAS_CXX_14 +#endif + +// C++11 is the minimum required version of the fkYAML library. +#define FK_YAML_HAS_CXX_11 +#endif + +// switch usage of the deprecated attribute. [[deprecated]] is available since +// C++14. +#if defined(FK_YAML_HAS_CXX_14) +#define FK_YAML_DEPRECATED(msg) [[deprecated(msg)]] +#else +#if defined(_MSC_VER) +#define FK_YAML_DEPRECATED(msg) __declspec(deprecated(msg)) +#elif defined(__GNUC__) || defined(__clang__) +#define FK_YAML_DEPRECATED(msg) __attribute__((deprecated(msg))) +#else +#define FK_YAML_DEPRECATED(msg) +#endif +#endif + +// switch usage of inline variables which have been available since C++17. +#if defined(FK_YAML_HAS_CXX_17) +#define FK_YAML_INLINE_VAR inline +#else +#define FK_YAML_INLINE_VAR +#endif + +// switch usage of constexpr keyword depending on active C++ standard. +#if defined(FK_YAML_HAS_CXX_17) +#define FK_YAML_CXX17_CONSTEXPR constexpr +#else +#define FK_YAML_CXX17_CONSTEXPR +#endif + +// Detect __has_* macros. +// The following macros replace redundant `defined(__has_*) && __has_*(...)`. + +#ifdef __has_include +#define FK_YAML_HAS_INCLUDE(header) __has_include(header) +#else +#define FK_YAML_HAS_INCLUDE(header) (0) +#endif + +#ifdef __has_builtin +#define FK_YAML_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else +#define FK_YAML_HAS_BUILTIN(builtin) (0) +#endif + +#ifdef __has_cpp_attribute +#define FK_YAML_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define FK_YAML_HAS_CPP_ATTRIBUTE(attr) (0) +#endif + +#ifdef __has_feature +#define FK_YAML_HAS_FEATURE(feat) __has_feature(feat) +#else +#define FK_YAML_HAS_FEATURE(feat) (0) +#endif + +// switch usage of the no_sanitize attribute only when Clang sanitizer is +// active. +#if defined(__clang__) && FK_YAML_HAS_FEATURE(address_sanitizer) +#define FK_YAML_NO_SANITIZE(...) __attribute__((no_sanitize(__VA_ARGS__))) +#else +#define FK_YAML_NO_SANITIZE(...) +#endif + +#if FK_YAML_HAS_INCLUDE() +// is available since C++20 +#include +#endif + +// +// C++ feature detections +// + +// switch usages of the std::to_chars()/std::from_chars() functions which have +// been available since C++17. +#if defined(FK_YAML_HAS_CXX_17) && defined(__cpp_lib_to_chars) && \ + __cpp_lib_to_chars >= 201611L +#define FK_YAML_HAS_TO_CHARS (1) +#else +#define FK_YAML_HAS_TO_CHARS (0) +#endif + +// switch usage of char8_t which has been available since C++20. +#if defined(FK_YAML_HAS_CXX_20) && defined(__cpp_char8_t) && \ + __cpp_char8_t >= 201811L +#define FK_YAML_HAS_CHAR8_T (1) +#else +#define FK_YAML_HAS_CHAR8_T (0) +#endif + +// +// utility macros +// + +// switch usage of [[likely]] C++ attribute which has been available since +// C++20. +#if defined(FK_YAML_HAS_CXX_20) && FK_YAML_HAS_CPP_ATTRIBUTE(likely) >= 201803L +#define FK_YAML_LIKELY(expr) (!!(expr)) [[likely]] +#elif FK_YAML_HAS_BUILTIN(__builtin_expect) +#define FK_YAML_LIKELY(expr) (__builtin_expect(!!(expr), 1)) +#else +#define FK_YAML_LIKELY(expr) (!!(expr)) +#endif + +// switch usage of [[unlikely]] C++ attribute which has been available since +// C++20. +#if defined(FK_YAML_HAS_CXX_20) && \ + FK_YAML_HAS_CPP_ATTRIBUTE(unlikely) >= 201803L +#define FK_YAML_UNLIKELY(expr) (!!(expr)) [[unlikely]] +#elif FK_YAML_HAS_BUILTIN(__builtin_expect) +#define FK_YAML_UNLIKELY(expr) (__builtin_expect(!!(expr), 0)) +#else +#define FK_YAML_UNLIKELY(expr) (!!(expr)) +#endif + +#endif /* FK_YAML_DETAIL_MACROS_CPP_CONFIG_MACROS_HPP */ + +#endif /* FK_YAML_DETAIL_MACROS_DEFINE_MACROS_HPP */ + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_ASSERT_HPP +#define FK_YAML_DETAIL_ASSERT_HPP + +// if FK_YAML_ASSERT is not user-defined. apply the default assert impl. +#ifndef FK_YAML_ASSERT +#ifndef NDEBUG +#include +#define FK_YAML_ASSERT(x) assert(x) +#else +#define FK_YAML_ASSERT(x) +#endif +#endif + +#endif /* FK_YAML_DETAIL_ASSERT_HPP */ + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_DOCUMENT_METAINFO_HPP +#define FK_YAML_DETAIL_DOCUMENT_METAINFO_HPP + +#include +#include + +// #include + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_META_NODE_TRAITS_HPP +#define FK_YAML_DETAIL_META_NODE_TRAITS_HPP + +// #include + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_META_DETECT_HPP +#define FK_YAML_DETAIL_META_DETECT_HPP + +#include +#include + +// #include + +// #include +// _______ __ __ __ _____ __ __ __ +// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML +// library | __| _ < \_ _/| ___ | _ | |___ version 0.4.2 +// |__| |_| \__| |_| |_| |_|___||___|______| +// https://github.com/fktn-k/fkYAML +// +// SPDX-FileCopyrightText: 2023-2025 Kensuke Fukutani +// SPDX-License-Identifier: MIT + +#ifndef FK_YAML_DETAIL_META_STL_SUPPLEMENT_HPP +#define FK_YAML_DETAIL_META_STL_SUPPLEMENT_HPP + +#include +#include + +// #include + +#ifdef FK_YAML_HAS_CXX_14 +#include +#endif + +FK_YAML_DETAIL_NAMESPACE_BEGIN + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// For contributors: +// This file is for supplementing future C++ STL implementations to utilize +// some useful features implemented in C++14 or better. This file is needed +// to keep the fkYAML library requirement to C++11. +// **DO NOT** implement features which are not included any version of STL +// in this file. Such implementations must be in the type_traits.hpp file. +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef FK_YAML_HAS_CXX_14 + +/// @brief An alias template for std::add_pointer::type with C++11. +/// @note std::add_pointer_t is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/add_pointer +/// @tparam T A type to be added a pointer. +template using add_pointer_t = typename std::add_pointer::type; + +/// @brief An alias template for std::enable_if::type with C++11. +/// @note std::enable_if_t is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/enable_if +/// @tparam Condition A condition tested at compile time. +/// @tparam T The type defined only if Condition is true. +template +using enable_if_t = typename std::enable_if::type; + +/// @brief A simple implementation to use std::is_null_pointer with C++11. +/// @note std::is_null_pointer is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/is_null_pointer +/// @tparam T The type to be checked if it's equal to std::nullptr_t. +template +struct is_null_pointer + : std::is_same::type> {}; + +/// @brief An alias template for std::remove_cv::type with C++11. +/// @note std::remove_cv_t is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/remove_cv +/// @tparam T A type from which const-volatile qualifiers are removed. +template using remove_cv_t = typename std::remove_cv::type; + +/// @brief An alias template for std::remove_pointer::type with C++11. +/// @note std::remove_pointer_t is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/remove_pointer +/// @tparam T A type from which a pointer is removed. +template +using remove_pointer_t = typename std::remove_pointer::type; + +/// @brief An alias template for std::remove_reference::type with C++11. +/// @note std::remove_reference_t is available since C++14. +/// @sa https://en.cppreference.com/w/cpp/types/remove_reference +/// @tparam T A type from which a reference is removed. +template +using remove_reference_t = typename std::remove_reference::type; + +template struct integer_sequence { + using value_type = T; + static constexpr std::size_t size() noexcept { return sizeof...(I); } +}; + +#if !FK_YAML_HAS_BUILTIN(__make_integer_seq) && \ + !FK_YAML_HAS_BUILTIN(__integer_pack) + +namespace make_int_seq_impl { + +template struct merger; + +template +struct merger, integer_sequence> { + using type = integer_sequence; +}; + +template struct generator { + using type = + typename merger::type, + typename generator::type>::type; +}; + +template struct generator { + using type = integer_sequence; +}; + +template struct generator { + using type = integer_sequence; +}; + +} // namespace make_int_seq_impl + +#endif + +template +using make_integer_sequence +#if FK_YAML_HAS_BUILTIN(__make_integer_seq) + // clang defines built-in __make_integer_seq to generate an integer + // sequence. + = __make_integer_seq; +#elif FK_YAML_HAS_BUILTIN(__integer_pack) + // GCC or other compilers may implement built-in __integer_pack to generate + // an integer sequence. + = integer_sequence; +#else + // fallback to the library implementation of make_integer_sequence. + = typename make_int_seq_impl::generator::type; +#endif + +template +using index_sequence = integer_sequence; + +template +using make_index_sequence = make_integer_sequence; + +template +using index_sequence_for = make_index_sequence; + +#else // !defined(FK_YAML_HAS_CXX_14) + +using std::add_pointer_t; +using std::enable_if_t; +using std::index_sequence; +using std::index_sequence_for; +using std::integer_sequence; +using std::is_null_pointer; +using std::make_index_sequence; +using std::make_integer_sequence; +using std::remove_cv_t; +using std::remove_pointer_t; +using std::remove_reference_t; + +#endif // !defined(FK_YAML_HAS_CXX_14) + +#ifndef FK_YAML_HAS_CXX_17 + +/// @brief A simple implementation to use std::bool_constant with C++11/C++14. +/// @tparam Val +template using bool_constant = std::integral_constant; + +/// @brief A simple implementation to use std::void_t with C++11/C++14. +/// @note +/// std::conjunction is available since C++17. +/// This is applied when no traits are specified as inputs. +/// @sa https://en.cppreference.com/w/cpp/types/conjunction +/// @tparam Traits Type traits to be checked if their ::value are all true. +template struct conjunction : std::true_type {}; + +/// @brief A partial specialization of conjunction if only one Trait is given. +/// @tparam Trait Type trait to be checked if its ::value is true. +template struct conjunction : Trait {}; + +/// @brief A partial specialization of conjunction if more than one traits are +/// given. +/// @tparam First The first type trait to be checked if its ::value is true. +/// @tparam Rest The rest of traits passed as another conjunction template +/// arguments if First::value is true. +template +struct conjunction + : std::conditional, First>::type {}; + +/// @brief A simple implementation to use std::disjunction with C++11/C++14. +/// @note +/// std::disjunction is available since C++17. +/// This is applied when no traits are specified as inputs. +/// @sa https://en.cppreference.com/w/cpp/types/disjunction +/// @tparam Traits Type traits to be checked if at least one of their ::value is +/// true. +template struct disjunction : std::false_type {}; + +/// @brief A partial specialization of disjunction if only one Trait is given. +/// @tparam Trait Type trait to be checked if its ::value is true. +template struct disjunction : Trait {}; + +/// @brief A partial specialization of disjunction if more than one traits are +/// given. +/// @tparam First The first type trait to be checked if its ::value is true. +/// @tparam Rest The rest of traits passed as another conjunction template +/// arguments if First::value is false. +template +struct disjunction + : std::conditional>::type {}; + +/// @brief A simple implementation to use std::negation with C++11/C++14. +/// @note std::negation is available since C++17. +/// @sa https://en.cppreference.com/w/cpp/types/negation +/// @tparam Trait Type trait whose ::value is negated. +template +struct negation : std::integral_constant {}; + +/// @brief A helper for void_t. +/// @tparam Types Any types to be transformed to void type. +template struct make_void { + using type = void; +}; + +/// @brief A simple implementation to use std::void_t with C++11/C++14. +/// @note std::void_t is available since C++17. +/// @sa https://en.cppreference.com/w/cpp/types/void_t +/// @tparam Types Any types to be transformed to void type. +template using void_t = typename make_void::type; + +#else // !defined(FK_YAML_HAS_CXX_17) + +using std::bool_constant; +using std::conjunction; +using std::disjunction; +using std::negation; +using std::void_t; + +#endif // !defined(FK_YAML_HAS_CXX_17) + +#ifndef FK_YAML_HAS_CXX_20 + +/// @brief A simple implementation to use std::remove_cvref_t with +/// C++11/C++14/C++17. +/// @note std::remove_cvref & std::remove_cvref_t are available since C++20. +/// @sa https://en.cppreference.com/w/cpp/types/remove_cvref +/// @tparam T A type from which cv-qualifiers and reference are removed. +template +using remove_cvref_t = + typename std::remove_cv::type>::type; + +#else + +using std::remove_cvref_t; + +#endif + +/// @brief A wrapper function to call std::unreachable() (since C++23) or +/// similar compiler specific extensions. +/// @note This function is implemented only for better code optimization against +/// dead code and thus excluded from coverage report. +// LCOV_EXCL_START +[[noreturn]] inline void unreachable() { + // use compiler specific extensions if possible. + // undefined behavior should be raised by an empty function with noreturn + // attribute. + +#if defined(FK_YAML_HAS_CXX_23) || \ + (defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L) + std::unreachable(); +#elif defined(_MSC_VER) && !defined(__clang__) // MSVC + __assume(false); +#else + __builtin_unreachable(); +#endif +} +// LCOV_EXCL_STOP + +FK_YAML_DETAIL_NAMESPACE_END + +#endif /* FK_YAML_DETAIL_META_STL_SUPPLEMENT_HPP */ + +FK_YAML_DETAIL_NAMESPACE_BEGIN + +/// @brief A dummy struct to represent detection failure. +struct nonesuch { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(const nonesuch &) = delete; + nonesuch(nonesuch &&) = delete; + nonesuch &operator=(const nonesuch &) = delete; + nonesuch &operator=(nonesuch &&) = delete; +}; + +/// @brief namespace to implement detector type traits +namespace detector_impl { + +/// @brief A helper for general type detection. +/// @tparam Default A type to represent detection failure. +/// @tparam AlwaysVoid This must be void type. +/// @tparam Op A type for desired operation type. +/// @tparam Args Argument types passed to desired operation. +template class Op, typename... Args> +struct detector : std::false_type { + /// @brief A type which represents detection failure. + using type = Default; +}; + +/// @brief A partial specialization of detector if desired operation type is +/// found. +/// @tparam Default A type to represent detection failure. +/// @tparam Op A type for desired operation type. +/// @tparam Args Argument types passed to desired operation. +template class Op, typename... Args> +struct detector>, Op, Args...> : std::true_type { + /// @brief A detected type. + using type = Op; +}; + +} // namespace detector_impl + +/// @brief Type traits to detect Op operation with Args argument types +/// @tparam Op A desired operation type. +/// @tparam Args Argument types passed to desired operation. +template