diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index fdb0302..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/neko-player.iml b/.idea/neko-player.iml
deleted file mode 100644
index bc2cd87..0000000
--- a/.idea/neko-player.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 552d15a..7b98b07 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -6,5 +6,8 @@
+
+
+
\ No newline at end of file
diff --git a/assets/licenses/TomlPlusPlus.txt b/assets/licenses/TomlPlusPlus.txt
new file mode 100644
index 0000000..261cd61
--- /dev/null
+++ b/assets/licenses/TomlPlusPlus.txt
@@ -0,0 +1,16 @@
+MIT License
+
+Copyright (c) Mark Gillard
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/assets/update-assets.sh b/assets/update-assets.sh
index 939f80d..967c0b2 100755
--- a/assets/update-assets.sh
+++ b/assets/update-assets.sh
@@ -35,6 +35,7 @@ add_basic 'licenses/libportal.txt' 'libportal_license'
add_basic 'licenses/ForkAwesome.txt' 'forkawesome_license'
add_basic 'licenses/libintl.txt' 'libintl_license'
add_basic 'licenses/cli11.txt' 'cli11_license'
+add_basic 'licenses/TomlPlusPlus.txt' 'tomlplusplus_license'
add_basic '../IconFontCppHeaders/licence.txt' 'icnfntcpphdrs_license'
echo '#pragma once' > 'assets.h'
for i in "${ASSETS[@]}"; do
diff --git a/main.cpp b/main.cpp
index a9d8264..3957a05 100644
--- a/main.cpp
+++ b/main.cpp
@@ -335,7 +335,8 @@ void MainLoop::GuiFunction() {
#endif
LicenseData(_TR_CTX("Library name", "Noto Sans"), "OFL-1.1-RFN"),
LicenseData(_TR_CTX("Library name", "Fork Awesome"), "OFL-1.1-RFN"),
- LicenseData(_TR_CTX("Library name", "IconFontCppHeaders"), "Zlib")
+ LicenseData(_TR_CTX("Library name", "IconFontCppHeaders"), "Zlib"),
+ LicenseData(_TR_CTX("Library name", "TOML++"), "MIT")
};
// Do this in an inner scope so that 'i' isn't accidentally used outside it,
// and so that 'i' can refer to another variable such as in a for loop.
@@ -356,6 +357,7 @@ void MainLoop::GuiFunction() {
LOAD_LICENSE(projects[i], notosans); i++;
LOAD_LICENSE(projects[i], forkawesome); i++;
LOAD_LICENSE(projects[i], icnfntcpphdrs); i++;
+ LOAD_LICENSE(projects[i], tomlplusplus); i++;
}
// Left
static LicenseData selected = projects[0];
diff --git a/meson.build b/meson.build
index 6da14fc..ec5a371 100644
--- a/meson.build
+++ b/meson.build
@@ -62,6 +62,7 @@ if get_option('portals') and target_machine.system() == 'linux'
endif
srcs = [
+ 'IconSet.cpp',
'main.cpp',
'RendererBackend.cpp',
'playback.cpp',
diff --git a/playback.cpp b/playback.cpp
index aeac9de..b345462 100644
--- a/playback.cpp
+++ b/playback.cpp
@@ -17,25 +17,26 @@ void Playback::SDLCallbackInner(Uint8 *stream, int len) {
if (!playback_ready.load()) {
return;
}
- size_t i = 0;
- size_t max = 0;
- size_t unit = sizeof(SAMPLETYPE) * spec.channels;
- size_t bytes_per_iter = std::min(((bufsize / unit)) * unit, (size_t)fakespec.size);
- while (st->numSamples() <= (uint)len) {
- if (general_mixer == nullptr) {
- return;
- }
- general_mixer(NULL, buf + i, bytes_per_iter);
- i += bytes_per_iter;
- max = i + bytes_per_iter;
- if (i + bytes_per_iter >= bufsize) {
- st->putSamples((SAMPLETYPE*)buf, i / unit);
- max = 0;
- i = 0;
- SDL_memset((void*)buf, 0, bufsize);
- }
+ if (st == nullptr) {
+ return;
}
- st->putSamples((SAMPLETYPE*)buf, max / unit);
+ size_t i = 0;
+ size_t max = 0;
+ size_t unit = sizeof(SAMPLETYPE) * spec.channels;
+ size_t bytes_per_iter = std::min(((bufsize / unit)) * unit, (size_t)fakespec.size);
+ while (st->numSamples() < (size_t)len) {
+ if (general_mixer == nullptr) {
+ return;
+ }
+ general_mixer(nullptr, buf + i, (int)bytes_per_iter);
+ i += bytes_per_iter;
+ max = i + bytes_per_iter;
+ if (max >= bufsize) {
+ st->putSamples((SAMPLETYPE*)buf, i/unit);
+ i = 0;
+ max = i + bytes_per_iter;
+ }
+ }
st->receiveSamples((SAMPLETYPE*)stream, len / unit);
}
void Playback::SDLCallback(void *userdata, Uint8 *stream, int len) {
@@ -43,9 +44,12 @@ void Playback::SDLCallback(void *userdata, Uint8 *stream, int len) {
}
Mix_Music *Playback::Load(const char *file) {
Mix_Music *output = Mix_LoadMUS(file);
- if (!output) {
+ if (output == nullptr) {
printf("Error loading music '%s': %s\n", file, Mix_GetError());
- throw std::exception();
+ error_mutex.lock();
+ errors.emplace("Error loading music!");
+ error_mutex.unlock();
+ return nullptr;
}
Mix_PlayMusicStream(output, -1);
length = Mix_MusicDuration(output);
@@ -57,18 +61,22 @@ void Playback::Unload(Mix_Music *music) {
Mix_FreeMusic(music);
}
void Playback::UpdateST() {
+
if (speed > 0.0f) {
+ pitch = std::max(std::min(speed, MaxSpeed), MinSpeed);
st->setRate(speed);
}
if (tempo > 0.0f) {
+ pitch = std::max(std::min(tempo, MaxTempo), MinTempo);
st->setTempo(tempo);
}
if (pitch > 0.0f) {
+ pitch = std::max(std::min(pitch, MaxPitch), MinPitch);
st->setPitch(pitch);
}
}
double Playback::GetMaxSeconds() {
- return std::max(MaxSpeed * MaxTempo, st->getInputOutputSampleRatio());
+ return std::max((double)(MaxSpeed * MaxTempo), st->getInputOutputSampleRatio());
}
void Playback::ThreadFunc() {
#ifdef __linux__
@@ -77,13 +85,13 @@ void Playback::ThreadFunc() {
bool reload = false;
while (running) {
playback_ready.store(false);
- if (reload) {
- printf("Resuming playback...\n");
- }
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
printf("Error initializing SDL: '%s'\n", SDL_GetError());
- throw std::exception();
+ error_mutex.lock();
+ errors.emplace("Failed to initialize SDL!");
+ error_mutex.unlock();
+ return;
}
}
SDL_AudioSpec obtained;
@@ -101,9 +109,13 @@ void Playback::ThreadFunc() {
desired.userdata = this;
st = new SoundTouch();
Mix_Init(MIX_INIT_FLAC|MIX_INIT_MID|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_OPUS|MIX_INIT_WAVPACK);
- if ((device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)) == 0) {
+ if ((device = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)) == 0) {
printf("Error opening audio device: '%s'\n", SDL_GetError());
- throw std::exception();
+ error_mutex.lock();
+ errors.emplace("Failed to open audio device!");
+ error_mutex.unlock();
+ running = false;
+ break;
}
spec = obtained;
st->setSampleRate(spec.freq);
@@ -116,23 +128,33 @@ void Playback::ThreadFunc() {
fakespec.samples *= maxSeconds;
size_t new_bufsize = CalculateBufSize(&spec, GetMaxSeconds(), MaxSeconds);
buf = (Uint8*)malloc(new_bufsize);
- if (buf == NULL) {
- throw std::exception();
+ if (buf == nullptr) {
+ error_mutex.lock();
+ errors.emplace("Failed to allocate memory for playback!");
+ error_mutex.unlock();
+ running = false;
+ break;
}
bufsize = new_bufsize;
general_mixer = Mix_GetGeneralMixer();
- Mix_InitMixer(&fakespec, SDL_TRUE);
+ Mix_InitMixer(&fakespec, SDL_FALSE);
SDL_PauseAudioDevice(device, 0);
Mix_Music *music = Load(filePath.c_str());
- if (reload) {
- Seek(position);
- }
reload = false;
- playback_ready.store(true);
- while (running && !reload) {
+ if (music) {
+ playback_ready.store(true);
+ } else {
+ playback_ready.store(false);
+ }
+ while (running) {
if (file_changed.exchange(false)) {
Unload(music);
music = Load(filePath.c_str());
+ if (music) {
+ playback_ready.store(true);
+ } else {
+ playback_ready.store(false);
+ }
}
if (flag_mutex.try_lock()) {
if (seeking.exchange(false)) {
@@ -144,7 +166,7 @@ void Playback::ThreadFunc() {
Mix_ResumeMusicStream(music);
}
if (update.exchange(false)) {
- Mix_VolumeMusicStream(music, (volume / 100.0 * MIX_MAX_VOLUME));
+ Mix_VolumeMusicStream(music, (int)(volume / 100.0 * MIX_MAX_VOLUME));
SDL_LockAudioDevice(device);
UpdateST();
size_t correct_buf_size = CalculateBufSize(&spec, GetMaxSeconds(), MaxSeconds);
@@ -161,7 +183,11 @@ void Playback::ThreadFunc() {
general_mixer = nullptr;
bufsize = 0;
buf = (Uint8*)realloc((void*)buf, correct_buf_size);
- if (buf == NULL) {
+ if (buf == nullptr) {
+ error_mutex.lock();
+ errors.emplace("Failed to allocate memory for playback!");
+ error_mutex.unlock();
+ running = false;
break;
}
bufsize = correct_buf_size;
@@ -251,3 +277,20 @@ void Playback::Update() {
bool Playback::IsStopped() {
return !running;
}
+optional Playback::GetError() {
+ if (ErrorExists()) {
+ error_mutex.lock();
+ std::string error = errors.back();
+ errors.pop();
+ error_mutex.unlock();
+ return error;
+ } else {
+ return {};
+ }
+}
+bool Playback::ErrorExists() {
+ error_mutex.lock();
+ bool output = !errors.empty();
+ error_mutex.unlock();
+ return output;
+}
\ No newline at end of file
diff --git a/playback.h b/playback.h
index 499c630..65e4ff0 100644
--- a/playback.h
+++ b/playback.h
@@ -10,9 +10,13 @@
#include
#include
#include
+#include
+#include
using namespace soundtouch;
using std::span;
using std::optional;
+using std::vector;
+using std::queue;
class Playback {
private:
std::string filePath;
@@ -23,6 +27,7 @@ private:
std::atomic_bool restart;
std::atomic_bool playback_ready;
std::mutex flag_mutex;
+ std::mutex error_mutex;
std::thread thread;
double position;
double length;
@@ -42,6 +47,7 @@ private:
void ThreadFunc();
void UpdateST();
double GetMaxSeconds();
+ queue errors;
public:
Playback();
~Playback();
@@ -58,11 +64,13 @@ public:
float speed;
float tempo;
float pitch;
- double MaxSeconds = 100.0;
- double MaxSpeed = 4.0;
- double MaxPitch = 4.0;
- double MaxTempo = 4.0;
- double MinSpeed = 0.25;
- double MinPitch = 0.25;
- double MinTempo = 0.25;
+ float MaxSeconds = 100.0;
+ float MaxSpeed = 4.0;
+ float MaxPitch = 4.0;
+ float MaxTempo = 4.0;
+ float MinSpeed = 0.25;
+ float MinPitch = 0.25;
+ float MinTempo = 0.25;
+ optional GetError();
+ bool ErrorExists();
};
\ No newline at end of file
diff --git a/theme.cpp b/theme.cpp
index 6678977..970b8d5 100644
--- a/theme.cpp
+++ b/theme.cpp
@@ -1,6 +1,7 @@
#include "theme.h"
#include "imgui.h"
#include "json/value.h"
+#include "thirdparty/toml.hpp"
#include "translation.h"
#include
#include
@@ -303,7 +304,7 @@ bool Theme::ShowEditor(bool* open, Theme* &theme, ImGuiID dockid, int window_wid
selectedThemeName = "";
filter = "";
saveAsOpen = false;
- theme->Save(Theme::themeDir / selectedThemePath.replace_extension(".json"));
+ theme->Save(Theme::themeDir / selectedThemePath.replace_extension(".toml"));
theme->file_path = selectedThemePath.generic_string();
}
}
@@ -324,25 +325,18 @@ AccentColorizer::AccentColorizer() {
Value = false;
Alpha = false;
}
-AccentColorizer::AccentColorizer(Json::Value json) : AccentColorizer() {
- if (json.isBool()) {
- Hue = json.asBool();
- Saturation = Hue;
- Value = Hue;
- Alpha = Hue;
- } else {
- Hue = json["hue"].asBool();
- Saturation = json["saturation"].asBool();
- Value = json["value"].asBool();
- Alpha = json["alpha"].asBool();
- }
+AccentColorizer::AccentColorizer(toml::table table) : AccentColorizer() {
+ Hue = **table["hue"].as_boolean();
+ Saturation = **table["saturation"].as_boolean();
+ Value = **table["value"].as_boolean();
+ Alpha = **table["alpha"].as_boolean();
}
-Json::Value AccentColorizer::Serialize() {
- Json::Value output;
- output["hue"] = Hue;
- output["saturation"] = Saturation;
- output["value"] = Value;
- output["alpha"] = Alpha;
+toml::table AccentColorizer::Serialize() {
+ toml::table output;
+ output.insert("hue", Hue);
+ output.insert("saturation", Saturation);
+ output.insert("value", Value);
+ output.insert("alpha", Alpha);
return output;
}
void AccentColorizer::Colorize(ImVec4 accent, ImVec4 &color) {
@@ -375,79 +369,78 @@ void Theme::Apply(ImVec4 accent) {
void Theme::Save(string path) {
printf("Saving theme to %s...\n", path.c_str());
{
- Json::Value config;
+ toml::table config;
std::ofstream stream;
stream.open(path);
{
- Json::Value metadata;
- metadata["SchemaVersion"] = 2;
+ toml::table metadata;
+ metadata.insert("SchemaVersion", 3);
{
- Json::Value stringsList;
+ toml::table stringsList;
for (auto kv : strings) {
- Json::Value stringsEntryJson;
+ toml::table stringsEntryJson;
string language = kv.first;
ThemeStrings stringsEntry = kv.second;
- stringsEntryJson["Name"] = stringsEntry.name;
- stringsEntryJson["Description"] = stringsEntry.description;
- stringsList[language] = stringsEntryJson;
+ stringsEntryJson.insert("name", stringsEntry.name);
+ stringsEntryJson.insert("desc", stringsEntry.description);
+ stringsList.insert(language, stringsEntryJson);
}
- metadata["Strings"] = stringsList;
+ metadata.insert("Strings", stringsList);
}
- config["meta"] = metadata;
+ config.insert("meta", metadata);
}
{
- Json::Value rounding;
- rounding["Frame"] = style.FrameRounding;
- rounding["Window"] = style.WindowRounding;
- rounding["Child"] = style.ChildRounding;
- rounding["Popup"] = style.PopupRounding;
- rounding["Scrollbar"] = style.ScrollbarRounding;
- rounding["Grab"] = style.GrabRounding;
- rounding["Tab"] = style.TabRounding;
- config["rounding"] = rounding;
+ toml::table rounding;
+ rounding.insert("Frame", style.FrameRounding);
+ rounding.insert("Window", style.WindowRounding);
+ rounding.insert("Child", style.ChildRounding);
+ rounding.insert("Popup", style.PopupRounding);
+ rounding.insert("Scrollbar", style.ScrollbarRounding);
+ rounding.insert("Grab", style.GrabRounding);
+ rounding.insert("Tab", style.TabRounding);
+ config.insert("rounding", rounding);
}
{
- Json::Value sizing;
- sizing["FrameX"] = style.FramePadding.x;
- sizing["FrameY"] = style.FramePadding.y;
- sizing["WindowX"] = style.WindowPadding.x;
- sizing["WindowY"] = style.WindowPadding.y;
- sizing["CellX"] = style.CellPadding.x;
- sizing["CellY"] = style.CellPadding.y;
- sizing["SeparatorTextX"] = style.SeparatorTextPadding.x;
- sizing["SeparatorTextY"] = style.SeparatorTextPadding.y;
- sizing["ItemSpacingX"] = style.ItemSpacing.x;
- sizing["ItemSpacingY"] = style.ItemSpacing.y;
- sizing["Scrollbar"] = style.ScrollbarSize;
- sizing["Grab"] = style.GrabMinSize;
- config["sizing"] = sizing;
+ toml::table sizing;
+ sizing.insert("FrameX", style.FramePadding.x);
+ sizing.insert("FrameY", style.FramePadding.y);
+ sizing.insert("WindowX", style.WindowPadding.x);
+ sizing.insert("WindowY", style.WindowPadding.y);
+ sizing.insert("CellX", style.CellPadding.x);
+ sizing.insert("CellY", style.CellPadding.y);
+ sizing.insert("SeparatorTextX", style.SeparatorTextPadding.x);
+ sizing.insert("SeparatorTextY", style.SeparatorTextPadding.y);
+ sizing.insert("ItemSpacingX", style.ItemSpacing.x);
+ sizing.insert("ItemSpacingY", style.ItemSpacing.y);
+ sizing.insert("Scrollbar", style.ScrollbarSize);
+ sizing.insert("Grab", style.GrabMinSize);
+ config.insert("sizing", sizing);
}
{
- Json::Value borders;
- borders["Frame"] = style.FrameBorderSize;
- borders["Window"] = style.WindowBorderSize;
- borders["Child"] = style.ChildBorderSize;
- borders["Popup"] = style.PopupBorderSize;
- borders["Tab"] = style.TabBorderSize;
- borders["Tab"] = style.TabBorderSize;
- borders["SeparatorText"] = style.SeparatorTextBorderSize;
- config["borders"] = borders;
+ toml::table borders;
+ borders.insert("Frame", style.FrameBorderSize);
+ borders.insert("Window", style.WindowBorderSize);
+ borders.insert("Child", style.ChildBorderSize);
+ borders.insert("Popup", style.PopupBorderSize);
+ borders.insert("Tab", style.TabBorderSize);
+ borders.insert("SeparatorText", style.SeparatorTextBorderSize);
+ config.insert("borders", borders);
}
{
- Json::Value colors;
+ toml::table colors;
for (int i = 0; i < ImGuiCol_COUNT; i++)
{
const char* name = ImGui::GetStyleColorName(i);
ImVec4 color = style.Colors[i];
- Json::Value colorValue;
- colorValue["r"] = color.x;
- colorValue["g"] = color.y;
- colorValue["b"] = color.z;
- colorValue["a"] = color.w;
- colorValue["ConvertToAccent"] = AccentColorizers[i].Serialize();
- colors[name] = colorValue;
+ toml::table colorValue;
+ colorValue.insert("r", color.x);
+ colorValue.insert("g", color.y);
+ colorValue.insert("b", color.z);
+ colorValue.insert("a", color.w);
+ colorValue.insert("accent", AccentColorizers[i].Serialize());
+ colors.insert(name, colorValue);
}
- config["colors"] = colors;
+ config.insert("colors", colors);
}
stream << config;
stream.close();
@@ -465,15 +458,16 @@ void Theme::updateAvailableThemes() {
for (auto const& dir_entry : directory_iterator(themeDir)) {
if (dir_entry.is_regular_file()) {
if (dir_entry.path().extension().string() == ".json") {
- path path = dir_entry.path();
- availableThemes.insert(path);
- Json::Value config;
- std::ifstream stream;
- stream.open(path);
- if (stream.is_open()) {
- stream >> config;
- themeStrings[path] = ThemeStrings(config);
- }
+ string curpath = Migrate(dir_entry.path().string());
+ std::filesystem::remove(dir_entry.path());
+ availableThemes.insert(curpath);
+ toml::table config = toml::parse_file(curpath);
+ themeStrings[curpath] = ThemeStrings(config);
+ } else if (dir_entry.path().extension().string() == ".toml") {
+ string curpath = dir_entry.path().string();
+ availableThemes.insert(curpath);
+ toml::table config = toml::parse_file(curpath);
+ themeStrings[curpath] = ThemeStrings(config);
}
}
}
@@ -524,108 +518,200 @@ ThemeStrings Theme::GetStrings() {
return strings["fallback"];
}
}
-ThemeStrings::ThemeStrings(Json::Value config) : ThemeStrings() {
+ThemeStrings::ThemeStrings(toml::table config) : ThemeStrings() {
char *language_c = CURRENT_LANGUAGE;
string language = language_c;
- if (config.isMember("meta")) {
- Json::Value metadata = config["meta"];
+ if (config.contains("meta")) {
+ toml::table metadata = *config["meta"].as_table();
//metadata["SchemaVersion"] = 1;
- if (metadata.isMember("Strings")) {
- Json::Value stringsList = metadata["Strings"];
- if (stringsList.isMember(language)) {
- Json::Value stringsEntryJson = stringsList[language];
- if (stringsEntryJson.isMember("Name")) {
- name = stringsEntryJson["Name"].asString();
+ if (metadata.contains("Strings")) {
+ toml::table stringsList = *metadata["Strings"].as_table();
+ if (stringsList.contains(language)) {
+ toml::table stringsEntryJson = *stringsList[language].as_table();
+ if (stringsEntryJson.contains("name")) {
+ name = **stringsEntryJson["name"].as_string();
}
- if (stringsEntryJson.isMember("Description")) {
- description = stringsEntryJson["Description"].asString();
+ if (stringsEntryJson.contains("desc")) {
+ description = **stringsEntryJson["desc"].as_string();
}
- } else if (metadata.isMember("fallback")) {
- Json::Value stringsEntryJson = stringsList["fallback"];
- if (stringsEntryJson.isMember("Name")) {
- name = stringsEntryJson["Name"].asString();
+ } else if (metadata.contains("fallback")) {
+ toml::table stringsEntryJson = *stringsList["fallback"].as_table();
+ if (stringsEntryJson.contains("name")) {
+ name = **stringsEntryJson["name"].as_string();
}
- if (stringsEntryJson.isMember("Description")) {
- description = stringsEntryJson["Description"].asString();
+ if (stringsEntryJson.contains("desc")) {
+ description = **stringsEntryJson["desc"].as_string();
}
}
}
}
}
-Theme::Theme(string path) : Theme() {
- Json::Value config;
- std::ifstream stream;
- stream.open(path);
- if (stream.is_open()) {
+
+std::string Theme::Migrate(std::string path) {
+ if (path.ends_with(".json")) {
+ std::ifstream stream(path);
+ Json::Value config;
stream >> config;
+ toml::table newConfig;
if (config.isMember("meta")) {
Json::Value metadata = config["meta"];
- //metadata["SchemaVersion"] = 1;
+ toml::table newMeta;
if (metadata.isMember("Strings")) {
Json::Value stringsList = metadata["Strings"];
+ toml::table newStringsList;
for (string language : stringsList.getMemberNames()) {
Json::Value stringsEntryJson = stringsList[language];
- ThemeStrings stringsEntry;
+ toml::table newStringsEntry;
if (stringsEntryJson.isMember("Name")) {
- stringsEntry.name = stringsEntryJson["Name"].asString();
+ string value = stringsEntryJson["Name"].asString();
+ newStringsEntry.insert("name", value);
}
if (stringsEntryJson.isMember("Description")) {
- stringsEntry.description = stringsEntryJson["Description"].asString();
+ string value = stringsEntryJson["Description"].asString();
+ newStringsEntry.insert("desc", value);
}
- strings[language] = stringsEntry;
+ newStringsList.insert(language, newStringsEntry);
}
+ newMeta.insert("Strings", newStringsList);
}
+ newConfig.insert("meta", newMeta);
}
if (config.isMember("rounding")) {
Json::Value rounding = config["rounding"];
- style.FrameRounding = rounding["Frame"].asFloat();
- style.WindowRounding = rounding["Window"].asFloat();
- style.ChildRounding = rounding["Child"].asFloat();
- style.PopupRounding = rounding["Popup"].asFloat();
- style.ScrollbarRounding = rounding["Scrollbar"].asFloat();
- style.GrabRounding = rounding["Grab"].asFloat();
- style.TabRounding = rounding["Tab"].asFloat();
+ toml::table newRounding;
+ for (string key : rounding.getMemberNames()) {
+ newRounding.insert(key, rounding[key].asFloat());
+ }
+ newConfig.insert("rounding", newRounding);
}
if (config.isMember("sizing")) {
- Json::Value sizing = config["sizing"];
- style.FramePadding.x = sizing["FrameX"].asFloat();
- style.FramePadding.y = sizing["FrameY"].asFloat();
- style.WindowPadding.x = sizing["WindowX"].asFloat();
- style.WindowPadding.y = sizing["WindowY"].asFloat();
- style.CellPadding.x = sizing["CellX"].asFloat();
- style.CellPadding.y = sizing["CellY"].asFloat();
- style.SeparatorTextPadding.x = sizing["SeparatorTextX"].asFloat();
- style.SeparatorTextPadding.y = sizing["SeparatorTextY"].asFloat();
- style.ItemSpacing.x = sizing["ItemSpacingX"].asFloat();
- style.ItemSpacing.y = sizing["ItemSpacingY"].asFloat();
- style.ScrollbarSize = sizing["Scrollbar"].asFloat();
- style.GrabMinSize = sizing["Grab"].asFloat();
+ Json::Value rounding = config["sizing"];
+ toml::table newRounding;
+ for (string key : rounding.getMemberNames()) {
+ newRounding.insert(key, rounding[key].asFloat());
+ }
+ newConfig.insert("sizing", newRounding);
}
if (config.isMember("borders")) {
- Json::Value borders = config["borders"];
- style.FrameBorderSize = borders["Frame"].asFloat();
- style.WindowBorderSize = borders["Window"].asFloat();
- style.ChildBorderSize = borders["Child"].asFloat();
- style.PopupBorderSize = borders["Popup"].asFloat();
- style.TabBorderSize = borders["Tab"].asFloat();
- if (borders.isMember("SeparatorText")) {
- style.SeparatorTextBorderSize = borders["SeparatorText"].asFloat();
+ Json::Value rounding = config["borders"];
+ toml::table newRounding;
+ for (string key : rounding.getMemberNames()) {
+ newRounding.insert(key, rounding[key].asFloat());
}
+ newConfig.insert("borders", newRounding);
}
if (config.isMember("colors")) {
Json::Value colors = config["colors"];
+ toml::table newColors;
for (int i = 0; i < ImGuiCol_COUNT; i++)
{
+ toml::table newColor;
const char* name = ImGui::GetStyleColorName(i);
if (colors.isMember(name)) {
Json::Value colorValue = colors[name];
ImVec4 color = ImVec4(colorValue["r"].asFloat(), colorValue["g"].asFloat(), colorValue["b"].asFloat(), colorValue["a"].asFloat());
- AccentColorizers[i] = AccentColorizer(colorValue["ConvertToAccent"]);
- style.Colors[i] = color;
+ newColor.insert("r", colorValue["r"].asFloat());
+ newColor.insert("g", colorValue["g"].asFloat());
+ newColor.insert("b", colorValue["b"].asFloat());
+ newColor.insert("a", colorValue["a"].asFloat());
+ toml::table newAccentOptions;
+ if (colorValue["ConvertToAccent"].isBool()) {
+ newAccentOptions.insert("hue", colorValue["ConvertToAccent"].asBool());
+ newAccentOptions.insert("saturation", false);
+ newAccentOptions.insert("value", false);
+ newAccentOptions.insert("alpha", false);
+ } else {
+ Json::Value accentOptions = colorValue["ConvertToAccent"];
+ newAccentOptions.insert("hue", accentOptions["hue"].asBool());
+ newAccentOptions.insert("saturation", accentOptions["saturation"].asBool());
+ newAccentOptions.insert("value", accentOptions["value"].asBool());
+ newAccentOptions.insert("alpha", accentOptions["alpha"].asBool());
+ }
+ newColor.insert("accent", newAccentOptions);
+ newColors.insert(name, newColor);
}
}
}
stream.close();
+ std::string newPath = path.replace(path.size() - 4, 4, "toml");
+ std::ofstream outStream(newPath);
+ outStream << newConfig;
+ outStream.close();
+ return newPath;
+ }
+ return path;
+}
+Theme::Theme(string path) : Theme() {
+ path = Migrate(path);
+ toml::table config;
+ config = toml::parse_file(path);
+ if (config.contains("meta")) {
+ toml::table metadata = *config["meta"].as_table();
+ //metadata["SchemaVersion"] = 1;
+ if (metadata.contains("Strings")) {
+ toml::table stringsList = *metadata["Strings"].as_table();
+ for (auto kv : stringsList) {
+ string language = string(kv.first.str());
+ toml::table stringEntryToml = *kv.second.as_table();
+ ThemeStrings stringsEntry;
+ if (stringEntryToml.contains("name")) {
+ stringsEntry.name = stringEntryToml["name"].as_string()->value_or("Unknown");
+ }
+ if (stringEntryToml.contains("desc")) {
+ stringsEntry.description = stringEntryToml["desc"].as_string()->value_or("No description.");
+ }
+ strings[language] = stringsEntry;
+ }
+ }
+ }
+ if (config.contains("rounding")) {
+ toml::table rounding = *config["rounding"].as_table();
+ style.FrameRounding = (float)(**(rounding["Frame"].as_floating_point()));
+ style.WindowRounding = (float)(**(rounding["Window"].as_floating_point()));
+ style.ChildRounding = (float)(**(rounding["Child"].as_floating_point()));
+ style.PopupRounding = (float)(**(rounding["Popup"].as_floating_point()));
+ style.ScrollbarRounding = (float)(**(rounding["Scrollbar"].as_floating_point()));
+ style.GrabRounding = (float)(**(rounding["Grab"].as_floating_point()));
+ style.TabRounding = (float)(**(rounding["Tab"].as_floating_point()));
+ }
+ if (config.contains("sizing")) {
+ toml::table sizing = *config["sizing"].as_table();
+ style.FramePadding.x = (float)(**sizing["FrameX"].as_floating_point());
+ style.FramePadding.y = (float)(**sizing["FrameY"].as_floating_point());
+ style.WindowPadding.x = (float)(**sizing["WindowX"].as_floating_point());
+ style.WindowPadding.y = (float)(**sizing["WindowY"].as_floating_point());
+ style.CellPadding.x = (float)(**sizing["CellX"].as_floating_point());
+ style.CellPadding.y = (float)(**sizing["CellY"].as_floating_point());
+ style.SeparatorTextPadding.x = (float)(**sizing["SeparatorTextX"].as_floating_point());
+ style.SeparatorTextPadding.y = (float)(**sizing["SeparatorTextY"].as_floating_point());
+ style.ItemSpacing.x = (float)(**sizing["ItemSpacingX"].as_floating_point());
+ style.ItemSpacing.y = (float)(**sizing["ItemSpacingY"].as_floating_point());
+ style.ScrollbarSize = (float)(**sizing["Scrollbar"].as_floating_point());
+ style.GrabMinSize = (float)(**sizing["Grab"].as_floating_point());
+ }
+ if (config.contains("borders")) {
+ toml::table borders = *config["borders"].as_table();
+ style.FrameBorderSize = (float)(**borders["Frame"].as_floating_point());
+ style.WindowBorderSize = (float)(**borders["Window"].as_floating_point());
+ style.ChildBorderSize = (float)(**borders["Child"].as_floating_point());
+ style.PopupBorderSize = (float)(**borders["Popup"].as_floating_point());
+ style.TabBorderSize = (float)(**borders["Tab"].as_floating_point());
+ if (borders.contains("SeparatorText")) {
+ style.SeparatorTextBorderSize = (float)(**borders["SeparatorText"].as_floating_point());
+ }
+ }
+ if (config.contains("colors")) {
+ toml::table colors = *config["colors"].as_table();
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const char* name = ImGui::GetStyleColorName(i);
+ if (colors.contains(name)) {
+ toml::table colorValue = *colors[name].as_table();
+ ImVec4 color = ImVec4((float)**colorValue["r"].as_floating_point(), (float)**colorValue["g"].as_floating_point(), (float)**colorValue["b"].as_floating_point(), (float)**colorValue["a"].as_floating_point());
+ AccentColorizers[i] = AccentColorizer(*colorValue["accent"].as_table());
+ style.Colors[i] = color;
+ }
+ }
}
file_path = path;
}
diff --git a/theme.h b/theme.h
index 144a6e2..2c2210b 100644
--- a/theme.h
+++ b/theme.h
@@ -7,6 +7,7 @@
#include "file_browser.h"
#include
#include
+#include "thirdparty/toml.hpp"
using std::string;
using namespace std::filesystem;
@@ -14,7 +15,7 @@ struct ThemeStrings {
string name;
string description;
ThemeStrings();
- ThemeStrings(Json::Value config);
+ ThemeStrings(toml::table config);
};
struct AccentColorizer {
@@ -29,18 +30,19 @@ struct AccentColorizer {
/// @brief Colorizes a color stored as an ImVec4 according to preferences.
void Colorize(ImVec4 accent, ImVec4 &color);
/// @brief Serialize the settings to json.
- /// @returns The serialized JSON, as a Json::Value.
- Json::Value Serialize();
+ /// @returns The serialized TOML, as a toml::table.
+ toml::table Serialize();
/// @brief Create a default accent colorizer
AccentColorizer();
- /// @brief Deserialize the settings from JSON and construct.
- /// @param json The JSON to deserialize from.
- AccentColorizer(Json::Value json);
+ /// @brief Deserialize the settings from TOML and construct.
+ /// @param table The TOML to deserialize from.
+ AccentColorizer(toml::table table);
};
class Theme {
ImGuiStyle style;
+ static std::string Migrate(string path);
public:
static std::set availableThemes;
static std::map themeStrings;
diff --git a/thirdparty/toml.hpp b/thirdparty/toml.hpp
new file mode 100644
index 0000000..0599bf5
--- /dev/null
+++ b/thirdparty/toml.hpp
@@ -0,0 +1,17748 @@
+//----------------------------------------------------------------------------------------------------------------------
+//
+// toml++ v3.4.0
+// https://github.com/marzer/tomlplusplus
+// SPDX-License-Identifier: MIT
+//
+//----------------------------------------------------------------------------------------------------------------------
+//
+// - THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY -
+//
+// If you wish to submit a contribution to toml++, hooray and thanks! Before you crack on, please be aware that this
+// file was assembled from a number of smaller files by a python script, and code contributions should not be made
+// against it directly. You should instead make your changes in the relevant source file(s). The file names of the files
+// that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.
+//
+//----------------------------------------------------------------------------------------------------------------------
+//
+// TOML Language Specifications:
+// latest: https://github.com/toml-lang/toml/blob/master/README.md
+// v1.0.0: https://toml.io/en/v1.0.0
+// v0.5.0: https://toml.io/en/v0.5.0
+// changelog: https://github.com/toml-lang/toml/blob/master/CHANGELOG.md
+//
+//----------------------------------------------------------------------------------------------------------------------
+//
+// MIT License
+//
+// Copyright (c) Mark Gillard
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//----------------------------------------------------------------------------------------------------------------------
+#ifndef TOMLPLUSPLUS_HPP
+#define TOMLPLUSPLUS_HPP
+
+#define INCLUDE_TOMLPLUSPLUS_H // old guard name used pre-v3
+#define TOMLPLUSPLUS_H // guard name used in the legacy toml.h
+
+//******** impl/preprocessor.hpp *************************************************************************************
+
+#ifndef __cplusplus
+#error toml++ is a C++ library.
+#endif
+
+#ifndef TOML_CPP
+#ifdef _MSVC_LANG
+#if _MSVC_LANG > __cplusplus
+#define TOML_CPP _MSVC_LANG
+#endif
+#endif
+#ifndef TOML_CPP
+#define TOML_CPP __cplusplus
+#endif
+#if TOML_CPP >= 202900L
+#undef TOML_CPP
+#define TOML_CPP 29
+#elif TOML_CPP >= 202600L
+#undef TOML_CPP
+#define TOML_CPP 26
+#elif TOML_CPP >= 202302L
+#undef TOML_CPP
+#define TOML_CPP 23
+#elif TOML_CPP >= 202002L
+#undef TOML_CPP
+#define TOML_CPP 20
+#elif TOML_CPP >= 201703L
+#undef TOML_CPP
+#define TOML_CPP 17
+#elif TOML_CPP >= 201402L
+#undef TOML_CPP
+#define TOML_CPP 14
+#elif TOML_CPP >= 201103L
+#undef TOML_CPP
+#define TOML_CPP 11
+#else
+#undef TOML_CPP
+#define TOML_CPP 0
+#endif
+#endif
+
+#if !TOML_CPP
+#error toml++ requires C++17 or higher. For a pre-C++11 TOML library see https://github.com/ToruNiina/Boost.toml
+#elif TOML_CPP < 17
+#error toml++ requires C++17 or higher. For a C++11 TOML library see https://github.com/ToruNiina/toml11
+#endif
+
+#ifndef TOML_MAKE_VERSION
+#define TOML_MAKE_VERSION(major, minor, patch) (((major)*10000) + ((minor)*100) + ((patch)))
+#endif
+
+#ifndef TOML_INTELLISENSE
+#ifdef __INTELLISENSE__
+#define TOML_INTELLISENSE 1
+#else
+#define TOML_INTELLISENSE 0
+#endif
+#endif
+
+#ifndef TOML_DOXYGEN
+#if defined(DOXYGEN) || defined(__DOXYGEN) || defined(__DOXYGEN__) || defined(__doxygen__) || defined(__POXY__) \
+ || defined(__poxy__)
+#define TOML_DOXYGEN 1
+#else
+#define TOML_DOXYGEN 0
+#endif
+#endif
+
+#ifndef TOML_CLANG
+#ifdef __clang__
+#define TOML_CLANG __clang_major__
+#else
+#define TOML_CLANG 0
+#endif
+
+// special handling for apple clang; see:
+// - https://github.com/marzer/tomlplusplus/issues/189
+// - https://en.wikipedia.org/wiki/Xcode
+// -
+// https://stackoverflow.com/questions/19387043/how-can-i-reliably-detect-the-version-of-clang-at-preprocessing-time
+#if TOML_CLANG && defined(__apple_build_version__)
+#undef TOML_CLANG
+#define TOML_CLANG_VERSION TOML_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#if TOML_CLANG_VERSION >= TOML_MAKE_VERSION(15, 0, 0)
+#define TOML_CLANG 16
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(14, 3, 0)
+#define TOML_CLANG 15
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(14, 0, 0)
+#define TOML_CLANG 14
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(13, 1, 6)
+#define TOML_CLANG 13
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(13, 0, 0)
+#define TOML_CLANG 12
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(12, 0, 5)
+#define TOML_CLANG 11
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(12, 0, 0)
+#define TOML_CLANG 10
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(11, 0, 3)
+#define TOML_CLANG 9
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(11, 0, 0)
+#define TOML_CLANG 8
+#elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(10, 0, 1)
+#define TOML_CLANG 7
+#else
+#define TOML_CLANG 6 // not strictly correct but doesn't matter below this
+#endif
+#undef TOML_CLANG_VERSION
+#endif
+#endif
+
+#ifndef TOML_ICC
+#ifdef __INTEL_COMPILER
+#define TOML_ICC __INTEL_COMPILER
+#ifdef __ICL
+#define TOML_ICC_CL TOML_ICC
+#else
+#define TOML_ICC_CL 0
+#endif
+#else
+#define TOML_ICC 0
+#define TOML_ICC_CL 0
+#endif
+#endif
+
+#ifndef TOML_MSVC_LIKE
+#ifdef _MSC_VER
+#define TOML_MSVC_LIKE _MSC_VER
+#else
+#define TOML_MSVC_LIKE 0
+#endif
+#endif
+
+#ifndef TOML_MSVC
+#if TOML_MSVC_LIKE && !TOML_CLANG && !TOML_ICC
+#define TOML_MSVC TOML_MSVC_LIKE
+#else
+#define TOML_MSVC 0
+#endif
+#endif
+
+#ifndef TOML_GCC_LIKE
+#ifdef __GNUC__
+#define TOML_GCC_LIKE __GNUC__
+#else
+#define TOML_GCC_LIKE 0
+#endif
+#endif
+
+#ifndef TOML_GCC
+#if TOML_GCC_LIKE && !TOML_CLANG && !TOML_ICC
+#define TOML_GCC TOML_GCC_LIKE
+#else
+#define TOML_GCC 0
+#endif
+#endif
+
+#ifndef TOML_CUDA
+#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
+#define TOML_CUDA 1
+#else
+#define TOML_CUDA 0
+#endif
+#endif
+
+#ifndef TOML_ARCH_ITANIUM
+#if defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64)
+#define TOML_ARCH_ITANIUM 1
+#define TOML_ARCH_BITNESS 64
+#else
+#define TOML_ARCH_ITANIUM 0
+#endif
+#endif
+
+#ifndef TOML_ARCH_AMD64
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64)
+#define TOML_ARCH_AMD64 1
+#define TOML_ARCH_BITNESS 64
+#else
+#define TOML_ARCH_AMD64 0
+#endif
+#endif
+
+#ifndef TOML_ARCH_X86
+#if defined(__i386__) || defined(_M_IX86)
+#define TOML_ARCH_X86 1
+#define TOML_ARCH_BITNESS 32
+#else
+#define TOML_ARCH_X86 0
+#endif
+#endif
+
+#ifndef TOML_ARCH_ARM
+#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || defined(__ARM_64BIT_STATE) \
+ || defined(_M_ARM64EC)
+#define TOML_ARCH_ARM32 0
+#define TOML_ARCH_ARM64 1
+#define TOML_ARCH_ARM 1
+#define TOML_ARCH_BITNESS 64
+#elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_32BIT_STATE)
+#define TOML_ARCH_ARM32 1
+#define TOML_ARCH_ARM64 0
+#define TOML_ARCH_ARM 1
+#define TOML_ARCH_BITNESS 32
+#else
+#define TOML_ARCH_ARM32 0
+#define TOML_ARCH_ARM64 0
+#define TOML_ARCH_ARM 0
+#endif
+#endif
+
+#ifndef TOML_ARCH_BITNESS
+#define TOML_ARCH_BITNESS 0
+#endif
+
+#ifndef TOML_ARCH_X64
+#if TOML_ARCH_BITNESS == 64
+#define TOML_ARCH_X64 1
+#else
+#define TOML_ARCH_X64 0
+#endif
+#endif
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__)
+#define TOML_WINDOWS 1
+#else
+#define TOML_WINDOWS 0
+#endif
+
+#ifdef __unix__
+#define TOML_UNIX 1
+#else
+#define TOML_UNIX 0
+#endif
+
+#ifdef __linux__
+#define TOML_LINUX 1
+#else
+#define TOML_LINUX 0
+#endif
+
+// TOML_HAS_INCLUDE
+#ifndef TOML_HAS_INCLUDE
+#ifdef __has_include
+#define TOML_HAS_INCLUDE(header) __has_include(header)
+#else
+#define TOML_HAS_INCLUDE(header) 0
+#endif
+#endif
+
+// TOML_HAS_BUILTIN
+#ifndef TOML_HAS_BUILTIN
+#ifdef __has_builtin
+#define TOML_HAS_BUILTIN(name) __has_builtin(name)
+#else
+#define TOML_HAS_BUILTIN(name) 0
+#endif
+#endif
+
+// TOML_HAS_FEATURE
+#ifndef TOML_HAS_FEATURE
+#ifdef __has_feature
+#define TOML_HAS_FEATURE(name) __has_feature(name)
+#else
+#define TOML_HAS_FEATURE(name) 0
+#endif
+#endif
+
+// TOML_HAS_ATTR
+#ifndef TOML_HAS_ATTR
+#ifdef __has_attribute
+#define TOML_HAS_ATTR(attr) __has_attribute(attr)
+#else
+#define TOML_HAS_ATTR(attr) 0
+#endif
+#endif
+
+// TOML_HAS_CPP_ATTR
+#ifndef TOML_HAS_CPP_ATTR
+#ifdef __has_cpp_attribute
+#define TOML_HAS_CPP_ATTR(attr) __has_cpp_attribute(attr)
+#else
+#define TOML_HAS_CPP_ATTR(attr) 0
+#endif
+#endif
+
+// TOML_ATTR (gnu attributes)
+#ifndef TOML_ATTR
+#if TOML_CLANG || TOML_GCC_LIKE
+#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
+#else
+#define TOML_ATTR(...)
+#endif
+#endif
+
+// TOML_DECLSPEC (msvc attributes)
+#ifndef TOML_DECLSPEC
+#if TOML_MSVC_LIKE
+#define TOML_DECLSPEC(...) __declspec(__VA_ARGS__)
+#else
+#define TOML_DECLSPEC(...)
+#endif
+#endif
+
+// TOML_COMPILER_HAS_EXCEPTIONS
+#ifndef TOML_COMPILER_HAS_EXCEPTIONS
+#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(__cpp_exceptions)
+#define TOML_COMPILER_HAS_EXCEPTIONS 1
+#else
+#define TOML_COMPILER_HAS_EXCEPTIONS 0
+#endif
+#endif
+
+// TOML_COMPILER_HAS_RTTI
+#ifndef TOML_COMPILER_HAS_RTTI
+#if defined(_CPPRTTI) || defined(__GXX_RTTI) || TOML_HAS_FEATURE(cxx_rtti)
+#define TOML_COMPILER_HAS_RTTI 1
+#else
+#define TOML_COMPILER_HAS_RTTI 0
+#endif
+#endif
+
+// TOML_CONCAT
+#define TOML_CONCAT_1(x, y) x##y
+#define TOML_CONCAT(x, y) TOML_CONCAT_1(x, y)
+
+// TOML_MAKE_STRING
+#define TOML_MAKE_STRING_1(s) #s
+#define TOML_MAKE_STRING(s) TOML_MAKE_STRING_1(s)
+
+// TOML_PRAGMA_XXXX (compiler-specific pragmas)
+#if TOML_CLANG
+#define TOML_PRAGMA_CLANG(decl) _Pragma(TOML_MAKE_STRING(clang decl))
+#else
+#define TOML_PRAGMA_CLANG(decl)
+#endif
+#if TOML_CLANG >= 8
+#define TOML_PRAGMA_CLANG_GE_8(decl) TOML_PRAGMA_CLANG(decl)
+#else
+#define TOML_PRAGMA_CLANG_GE_8(decl)
+#endif
+#if TOML_CLANG >= 9
+#define TOML_PRAGMA_CLANG_GE_9(decl) TOML_PRAGMA_CLANG(decl)
+#else
+#define TOML_PRAGMA_CLANG_GE_9(decl)
+#endif
+#if TOML_CLANG >= 10
+#define TOML_PRAGMA_CLANG_GE_10(decl) TOML_PRAGMA_CLANG(decl)
+#else
+#define TOML_PRAGMA_CLANG_GE_10(decl)
+#endif
+#if TOML_CLANG >= 11
+#define TOML_PRAGMA_CLANG_GE_11(decl) TOML_PRAGMA_CLANG(decl)
+#else
+#define TOML_PRAGMA_CLANG_GE_11(decl)
+#endif
+#if TOML_GCC
+#define TOML_PRAGMA_GCC(decl) _Pragma(TOML_MAKE_STRING(GCC decl))
+#else
+#define TOML_PRAGMA_GCC(decl)
+#endif
+#if TOML_MSVC
+#define TOML_PRAGMA_MSVC(...) __pragma(__VA_ARGS__)
+#else
+#define TOML_PRAGMA_MSVC(...)
+#endif
+#if TOML_ICC
+#define TOML_PRAGMA_ICC(...) __pragma(__VA_ARGS__)
+#else
+#define TOML_PRAGMA_ICC(...)
+#endif
+
+// TOML_ALWAYS_INLINE
+#ifdef _MSC_VER
+#define TOML_ALWAYS_INLINE __forceinline
+#elif TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__always_inline__)
+#define TOML_ALWAYS_INLINE \
+ TOML_ATTR(__always_inline__) \
+ inline
+#else
+#define TOML_ALWAYS_INLINE inline
+#endif
+
+// TOML_NEVER_INLINE
+#ifdef _MSC_VER
+#define TOML_NEVER_INLINE TOML_DECLSPEC(noinline)
+#elif TOML_CUDA // https://gitlab.gnome.org/GNOME/glib/-/issues/2555
+#define TOML_NEVER_INLINE TOML_ATTR(noinline)
+#else
+#if TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__noinline__)
+#define TOML_NEVER_INLINE TOML_ATTR(__noinline__)
+#endif
+#endif
+#ifndef TOML_NEVER_INLINE
+#define TOML_NEVER_INLINE
+#endif
+
+// MSVC attributes
+#define TOML_ABSTRACT_INTERFACE TOML_DECLSPEC(novtable)
+#define TOML_EMPTY_BASES TOML_DECLSPEC(empty_bases)
+
+// TOML_TRIVIAL_ABI
+#if TOML_CLANG || TOML_HAS_ATTR(__trivial_abi__)
+#define TOML_TRIVIAL_ABI TOML_ATTR(__trivial_abi__)
+#else
+#define TOML_TRIVIAL_ABI
+#endif
+
+// TOML_NODISCARD
+#if TOML_CPP >= 17 && TOML_HAS_CPP_ATTR(nodiscard) >= 201603
+#define TOML_NODISCARD [[nodiscard]]
+#elif TOML_CLANG || TOML_GCC || TOML_HAS_ATTR(__warn_unused_result__)
+#define TOML_NODISCARD TOML_ATTR(__warn_unused_result__)
+#else
+#define TOML_NODISCARD
+#endif
+
+// TOML_NODISCARD_CTOR
+#if TOML_CPP >= 17 && TOML_HAS_CPP_ATTR(nodiscard) >= 201907
+#define TOML_NODISCARD_CTOR [[nodiscard]]
+#else
+#define TOML_NODISCARD_CTOR
+#endif
+
+// pure + const
+#ifndef TOML_PURE
+#ifdef NDEBUG
+#define TOML_PURE \
+ TOML_DECLSPEC(noalias) \
+ TOML_ATTR(pure)
+#else
+#define TOML_PURE
+#endif
+#endif
+#ifndef TOML_CONST
+#ifdef NDEBUG
+#define TOML_CONST \
+ TOML_DECLSPEC(noalias) \
+ TOML_ATTR(const)
+#else
+#define TOML_CONST
+#endif
+#endif
+#ifndef TOML_INLINE_GETTER
+#define TOML_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE
+#endif
+#ifndef TOML_PURE_GETTER
+#define TOML_PURE_GETTER \
+ TOML_NODISCARD \
+ TOML_PURE
+#endif
+#ifndef TOML_PURE_INLINE_GETTER
+#define TOML_PURE_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE \
+ TOML_PURE
+#endif
+#ifndef TOML_CONST_GETTER
+#define TOML_CONST_GETTER \
+ TOML_NODISCARD \
+ TOML_CONST
+#endif
+#ifndef TOML_CONST_INLINE_GETTER
+#define TOML_CONST_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE \
+ TOML_CONST
+#endif
+
+// TOML_ASSUME
+#ifdef _MSC_VER
+#define TOML_ASSUME(expr) __assume(expr)
+#elif TOML_ICC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_assume)
+#define TOML_ASSUME(expr) __builtin_assume(expr)
+#elif TOML_HAS_CPP_ATTR(assume) >= 202207
+#define TOML_ASSUME(expr) [[assume(expr)]]
+#elif TOML_HAS_ATTR(__assume__)
+#define TOML_ASSUME(expr) __attribute__((__assume__(expr)))
+#else
+#define TOML_ASSUME(expr) static_cast(0)
+#endif
+
+// TOML_UNREACHABLE
+#ifdef _MSC_VER
+#define TOML_UNREACHABLE __assume(0)
+#elif TOML_ICC || TOML_CLANG || TOML_GCC || TOML_HAS_BUILTIN(__builtin_unreachable)
+#define TOML_UNREACHABLE __builtin_unreachable()
+#else
+#define TOML_UNREACHABLE static_cast(0)
+#endif
+
+// TOML_LIKELY
+#if TOML_CPP >= 20 && TOML_HAS_CPP_ATTR(likely) >= 201803
+#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
+#define TOML_LIKELY_CASE [[likely]]
+#elif TOML_GCC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_expect)
+#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1))
+#else
+#define TOML_LIKELY(...) (__VA_ARGS__)
+#endif
+#ifndef TOML_LIKELY_CASE
+#define TOML_LIKELY_CASE
+#endif
+
+// TOML_UNLIKELY
+#if TOML_CPP >= 20 && TOML_HAS_CPP_ATTR(unlikely) >= 201803
+#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
+#define TOML_UNLIKELY_CASE [[unlikely]]
+#elif TOML_GCC || TOML_CLANG || TOML_HAS_BUILTIN(__builtin_expect)
+#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0))
+#else
+#define TOML_UNLIKELY(...) (__VA_ARGS__)
+#endif
+#ifndef TOML_UNLIKELY_CASE
+#define TOML_UNLIKELY_CASE
+#endif
+
+// TOML_FLAGS_ENUM
+#if TOML_CLANG || TOML_HAS_ATTR(flag_enum)
+#define TOML_FLAGS_ENUM __attribute__((flag_enum))
+#else
+#define TOML_FLAGS_ENUM
+#endif
+
+// TOML_OPEN_ENUM + TOML_CLOSED_ENUM
+#if TOML_CLANG || TOML_HAS_ATTR(enum_extensibility)
+#define TOML_OPEN_ENUM __attribute__((enum_extensibility(open)))
+#define TOML_CLOSED_ENUM __attribute__((enum_extensibility(closed)))
+#else
+#define TOML_OPEN_ENUM
+#define TOML_CLOSED_ENUM
+#endif
+
+// TOML_OPEN_FLAGS_ENUM + TOML_CLOSED_FLAGS_ENUM
+#define TOML_OPEN_FLAGS_ENUM TOML_OPEN_ENUM TOML_FLAGS_ENUM
+#define TOML_CLOSED_FLAGS_ENUM TOML_CLOSED_ENUM TOML_FLAGS_ENUM
+
+// TOML_MAKE_FLAGS
+#define TOML_MAKE_FLAGS_2(T, op, linkage) \
+ TOML_CONST_INLINE_GETTER \
+ linkage constexpr T operator op(T lhs, T rhs) noexcept \
+ { \
+ using under = std::underlying_type_t; \
+ return static_cast(static_cast(lhs) op static_cast(rhs)); \
+ } \
+ \
+ linkage constexpr T& operator TOML_CONCAT(op, =)(T & lhs, T rhs) noexcept \
+ { \
+ return lhs = (lhs op rhs); \
+ } \
+ \
+ static_assert(true)
+#define TOML_MAKE_FLAGS_1(T, linkage) \
+ static_assert(std::is_enum_v); \
+ \
+ TOML_MAKE_FLAGS_2(T, &, linkage); \
+ TOML_MAKE_FLAGS_2(T, |, linkage); \
+ TOML_MAKE_FLAGS_2(T, ^, linkage); \
+ \
+ TOML_CONST_INLINE_GETTER \
+ linkage constexpr T operator~(T val) noexcept \
+ { \
+ using under = std::underlying_type_t; \
+ return static_cast(~static_cast(val)); \
+ } \
+ \
+ TOML_CONST_INLINE_GETTER \
+ linkage constexpr bool operator!(T val) noexcept \
+ { \
+ using under = std::underlying_type_t; \
+ return !static_cast(val); \
+ } \
+ \
+ static_assert(true)
+#define TOML_MAKE_FLAGS(T) TOML_MAKE_FLAGS_1(T, )
+
+#define TOML_UNUSED(...) static_cast(__VA_ARGS__)
+
+#define TOML_DELETE_DEFAULTS(T) \
+ T(const T&) = delete; \
+ T(T&&) = delete; \
+ T& operator=(const T&) = delete; \
+ T& operator=(T&&) = delete
+
+#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \
+ __VA_ARGS__ TOML_NODISCARD \
+ friend bool operator==(RHS rhs, LHS lhs) noexcept \
+ { \
+ return lhs == rhs; \
+ } \
+ __VA_ARGS__ TOML_NODISCARD \
+ friend bool operator!=(LHS lhs, RHS rhs) noexcept \
+ { \
+ return !(lhs == rhs); \
+ } \
+ __VA_ARGS__ TOML_NODISCARD \
+ friend bool operator!=(RHS rhs, LHS lhs) noexcept \
+ { \
+ return !(lhs == rhs); \
+ } \
+ static_assert(true)
+
+#define TOML_EVAL_BOOL_1(T, F) T
+#define TOML_EVAL_BOOL_0(T, F) F
+
+#if !defined(__POXY__) && !defined(POXY_IMPLEMENTATION_DETAIL)
+#define POXY_IMPLEMENTATION_DETAIL(...) __VA_ARGS__
+#endif
+
+// COMPILER-SPECIFIC WARNING MANAGEMENT
+
+#if TOML_CLANG
+
+#define TOML_PUSH_WARNINGS \
+ TOML_PRAGMA_CLANG(diagnostic push) \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wunknown-warning-option") \
+ static_assert(true)
+
+#define TOML_DISABLE_SWITCH_WARNINGS \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wswitch") \
+ static_assert(true)
+
+#define TOML_DISABLE_ARITHMETIC_WARNINGS \
+ TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wimplicit-int-float-conversion") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wfloat-equal") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wshift-sign-overflow") \
+ static_assert(true)
+
+#define TOML_DISABLE_SPAM_WARNINGS \
+ TOML_PRAGMA_CLANG_GE_8(diagnostic ignored "-Wdefaulted-function-deleted") \
+ TOML_PRAGMA_CLANG_GE_9(diagnostic ignored "-Wctad-maybe-unsupported") \
+ TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wzero-as-null-pointer-constant") \
+ TOML_PRAGMA_CLANG_GE_11(diagnostic ignored "-Wsuggest-destructor-override") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-template-vtables") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wmissing-field-initializers") \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Wpadded") \
+ static_assert(true)
+
+#define TOML_POP_WARNINGS \
+ TOML_PRAGMA_CLANG(diagnostic pop) \
+ static_assert(true)
+
+#define TOML_DISABLE_WARNINGS \
+ TOML_PRAGMA_CLANG(diagnostic push) \
+ TOML_PRAGMA_CLANG(diagnostic ignored "-Weverything") \
+ static_assert(true, "")
+
+#define TOML_ENABLE_WARNINGS \
+ TOML_PRAGMA_CLANG(diagnostic pop) \
+ static_assert(true)
+
+#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 1
+
+#elif TOML_MSVC
+
+#define TOML_PUSH_WARNINGS \
+ __pragma(warning(push)) \
+ static_assert(true)
+
+#if TOML_HAS_INCLUDE()
+#pragma warning(push, 0)
+#include
+#pragma warning(pop)
+#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS \
+ __pragma(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) \
+ static_assert(true)
+#else
+#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS static_assert(true)
+#endif
+
+#define TOML_DISABLE_SWITCH_WARNINGS \
+ __pragma(warning(disable : 4061)) \
+ __pragma(warning(disable : 4062)) \
+ __pragma(warning(disable : 4063)) \
+ __pragma(warning(disable : 5262)) /* switch-case implicit fallthrough (false-positive) */ \
+ __pragma(warning(disable : 26819)) /* cg: unannotated fallthrough */ \
+ static_assert(true)
+
+#define TOML_DISABLE_SPAM_WARNINGS \
+ __pragma(warning(disable : 4127)) /* conditional expr is constant */ \
+ __pragma(warning(disable : 4324)) /* structure was padded due to alignment specifier */ \
+ __pragma(warning(disable : 4348)) \
+ __pragma(warning(disable : 4464)) /* relative include path contains '..' */ \
+ __pragma(warning(disable : 4505)) /* unreferenced local function removed */ \
+ __pragma(warning(disable : 4514)) /* unreferenced inline function has been removed */ \
+ __pragma(warning(disable : 4582)) /* constructor is not implicitly called */ \
+ __pragma(warning(disable : 4619)) /* there is no warning number 'XXXX' */ \
+ __pragma(warning(disable : 4623)) /* default constructor was implicitly defined as deleted */ \
+ __pragma(warning(disable : 4625)) /* copy constructor was implicitly defined as deleted */ \
+ __pragma(warning(disable : 4626)) /* assignment operator was implicitly defined as deleted */ \
+ __pragma(warning(disable : 4710)) /* function not inlined */ \
+ __pragma(warning(disable : 4711)) /* function selected for automatic expansion */ \
+ __pragma(warning(disable : 4820)) /* N bytes padding added */ \
+ __pragma(warning(disable : 4946)) /* reinterpret_cast used between related classes */ \
+ __pragma(warning(disable : 5026)) /* move constructor was implicitly defined as deleted */ \
+ __pragma(warning(disable : 5027)) /* move assignment operator was implicitly defined as deleted */ \
+ __pragma(warning(disable : 5039)) /* potentially throwing function passed to 'extern "C"' function */ \
+ __pragma(warning(disable : 5045)) /* Compiler will insert Spectre mitigation */ \
+ __pragma(warning(disable : 5264)) /* const variable is not used (false-positive) */ \
+ __pragma(warning(disable : 26451)) \
+ __pragma(warning(disable : 26490)) \
+ __pragma(warning(disable : 26495)) \
+ __pragma(warning(disable : 26812)) \
+ __pragma(warning(disable : 26819)) \
+ static_assert(true)
+
+#define TOML_DISABLE_ARITHMETIC_WARNINGS \
+ __pragma(warning(disable : 4365)) /* argument signed/unsigned mismatch */ \
+ __pragma(warning(disable : 4738)) /* storing 32-bit float result in memory */ \
+ __pragma(warning(disable : 5219)) /* implicit conversion from integral to float */ \
+ static_assert(true)
+
+#define TOML_POP_WARNINGS \
+ __pragma(warning(pop)) \
+ static_assert(true)
+
+#define TOML_DISABLE_WARNINGS \
+ __pragma(warning(push, 0)) \
+ __pragma(warning(disable : 4348)) \
+ __pragma(warning(disable : 4668)) \
+ __pragma(warning(disable : 5105)) \
+ __pragma(warning(disable : 5264)) \
+ TOML_DISABLE_CODE_ANALYSIS_WARNINGS; \
+ TOML_DISABLE_SWITCH_WARNINGS; \
+ TOML_DISABLE_SPAM_WARNINGS; \
+ TOML_DISABLE_ARITHMETIC_WARNINGS; \
+ static_assert(true)
+
+#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
+
+#elif TOML_ICC
+
+#define TOML_PUSH_WARNINGS \
+ __pragma(warning(push)) \
+ static_assert(true)
+
+#define TOML_DISABLE_SPAM_WARNINGS \
+ __pragma(warning(disable : 82)) /* storage class is not first */ \
+ __pragma(warning(disable : 111)) /* statement unreachable (false-positive) */ \
+ __pragma(warning(disable : 869)) /* unreferenced parameter */ \
+ __pragma(warning(disable : 1011)) /* missing return (false-positive) */ \
+ __pragma(warning(disable : 2261)) /* assume expr side-effects discarded */ \
+ static_assert(true)
+
+#define TOML_POP_WARNINGS \
+ __pragma(warning(pop)) \
+ static_assert(true)
+
+#define TOML_DISABLE_WARNINGS \
+ __pragma(warning(push, 0)) \
+ TOML_DISABLE_SPAM_WARNINGS
+
+#define TOML_ENABLE_WARNINGS \
+ __pragma(warning(pop)) \
+ static_assert(true)
+
+#elif TOML_GCC
+
+#define TOML_PUSH_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic push) \
+ static_assert(true)
+
+#define TOML_DISABLE_SWITCH_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-enum") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-default") \
+ static_assert(true)
+
+#define TOML_DISABLE_ARITHMETIC_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wfloat-equal") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wsign-conversion") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \
+ static_assert(true)
+
+#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=const") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=pure") \
+ static_assert(true)
+
+#define TOML_DISABLE_SPAM_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wpadded") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wcast-align") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wcomment") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wtype-limits") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wuseless-cast") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wsubobject-linkage") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wmissing-field-initializers") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wmaybe-uninitialized") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wnoexcept") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wnull-dereference") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wduplicated-branches") \
+ static_assert(true)
+
+#define TOML_POP_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic pop) \
+ static_assert(true)
+
+#define TOML_DISABLE_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic push) \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wall") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wextra") \
+ TOML_PRAGMA_GCC(diagnostic ignored "-Wpedantic") \
+ TOML_DISABLE_SWITCH_WARNINGS; \
+ TOML_DISABLE_ARITHMETIC_WARNINGS; \
+ TOML_DISABLE_SUGGEST_ATTR_WARNINGS; \
+ TOML_DISABLE_SPAM_WARNINGS; \
+ static_assert(true)
+
+#define TOML_ENABLE_WARNINGS \
+ TOML_PRAGMA_GCC(diagnostic pop) \
+ static_assert(true)
+
+#endif
+
+#ifndef TOML_PUSH_WARNINGS
+#define TOML_PUSH_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
+#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_SWITCH_WARNINGS
+#define TOML_DISABLE_SWITCH_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_SUGGEST_ATTR_WARNINGS
+#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_SPAM_WARNINGS
+#define TOML_DISABLE_SPAM_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_ARITHMETIC_WARNINGS
+#define TOML_DISABLE_ARITHMETIC_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_POP_WARNINGS
+#define TOML_POP_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_DISABLE_WARNINGS
+#define TOML_DISABLE_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_ENABLE_WARNINGS
+#define TOML_ENABLE_WARNINGS static_assert(true)
+#endif
+#ifndef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
+#define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 0
+#endif
+
+#ifdef TOML_CONFIG_HEADER
+#include TOML_CONFIG_HEADER
+#endif
+
+// is the library being built as a shared lib/dll using meson and friends?
+#ifndef TOML_SHARED_LIB
+#define TOML_SHARED_LIB 0
+#endif
+
+// header-only mode
+#if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0
+#define TOML_HEADER_ONLY TOML_ALL_INLINE
+#endif
+#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE
+#undef TOML_HEADER_ONLY
+#define TOML_HEADER_ONLY 1
+#endif
+#if TOML_DOXYGEN || TOML_SHARED_LIB
+#undef TOML_HEADER_ONLY
+#define TOML_HEADER_ONLY 0
+#endif
+
+// internal implementation switch
+#if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY
+#undef TOML_IMPLEMENTATION
+#define TOML_IMPLEMENTATION 1
+#else
+#define TOML_IMPLEMENTATION 0
+#endif
+
+// dll/shared lib function exports (legacy - TOML_API was the old name for this setting)
+#if !defined(TOML_EXPORTED_MEMBER_FUNCTION) && !defined(TOML_EXPORTED_STATIC_FUNCTION) \
+ && !defined(TOML_EXPORTED_FREE_FUNCTION) && !defined(TOML_EXPORTED_CLASS) && defined(TOML_API)
+#define TOML_EXPORTED_MEMBER_FUNCTION TOML_API
+#define TOML_EXPORTED_STATIC_FUNCTION TOML_API
+#define TOML_EXPORTED_FREE_FUNCTION TOML_API
+#endif
+
+// dll/shared lib exports
+#if TOML_SHARED_LIB
+#undef TOML_API
+#undef TOML_EXPORTED_CLASS
+#undef TOML_EXPORTED_MEMBER_FUNCTION
+#undef TOML_EXPORTED_STATIC_FUNCTION
+#undef TOML_EXPORTED_FREE_FUNCTION
+#if TOML_WINDOWS
+#if TOML_IMPLEMENTATION
+#define TOML_EXPORTED_CLASS __declspec(dllexport)
+#define TOML_EXPORTED_FREE_FUNCTION __declspec(dllexport)
+#else
+#define TOML_EXPORTED_CLASS __declspec(dllimport)
+#define TOML_EXPORTED_FREE_FUNCTION __declspec(dllimport)
+#endif
+#ifndef TOML_CALLCONV
+#define TOML_CALLCONV __cdecl
+#endif
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define TOML_EXPORTED_CLASS __attribute__((visibility("default")))
+#define TOML_EXPORTED_MEMBER_FUNCTION __attribute__((visibility("default")))
+#define TOML_EXPORTED_STATIC_FUNCTION __attribute__((visibility("default")))
+#define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default")))
+#endif
+#endif
+#ifndef TOML_EXPORTED_CLASS
+#define TOML_EXPORTED_CLASS
+#endif
+#ifndef TOML_EXPORTED_MEMBER_FUNCTION
+#define TOML_EXPORTED_MEMBER_FUNCTION
+#endif
+#ifndef TOML_EXPORTED_STATIC_FUNCTION
+#define TOML_EXPORTED_STATIC_FUNCTION
+#endif
+#ifndef TOML_EXPORTED_FREE_FUNCTION
+#define TOML_EXPORTED_FREE_FUNCTION
+#endif
+
+// experimental language features
+#if !defined(TOML_ENABLE_UNRELEASED_FEATURES) && defined(TOML_UNRELEASED_FEATURES) // was TOML_UNRELEASED_FEATURES
+ // pre-3.0
+#define TOML_ENABLE_UNRELEASED_FEATURES TOML_UNRELEASED_FEATURES
+#endif
+#if (defined(TOML_ENABLE_UNRELEASED_FEATURES) && TOML_ENABLE_UNRELEASED_FEATURES) || TOML_INTELLISENSE
+#undef TOML_ENABLE_UNRELEASED_FEATURES
+#define TOML_ENABLE_UNRELEASED_FEATURES 1
+#endif
+#ifndef TOML_ENABLE_UNRELEASED_FEATURES
+#define TOML_ENABLE_UNRELEASED_FEATURES 0
+#endif
+
+// parser
+#if !defined(TOML_ENABLE_PARSER) && defined(TOML_PARSER) // was TOML_PARSER pre-3.0
+#define TOML_ENABLE_PARSER TOML_PARSER
+#endif
+#if !defined(TOML_ENABLE_PARSER) || (defined(TOML_ENABLE_PARSER) && TOML_ENABLE_PARSER) || TOML_INTELLISENSE
+#undef TOML_ENABLE_PARSER
+#define TOML_ENABLE_PARSER 1
+#endif
+
+// formatters
+#if !defined(TOML_ENABLE_FORMATTERS) || (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) || TOML_INTELLISENSE
+#undef TOML_ENABLE_FORMATTERS
+#define TOML_ENABLE_FORMATTERS 1
+#endif
+
+// SIMD
+#if !defined(TOML_ENABLE_SIMD) || (defined(TOML_ENABLE_SIMD) && TOML_ENABLE_SIMD) || TOML_INTELLISENSE
+#undef TOML_ENABLE_SIMD
+#define TOML_ENABLE_SIMD 1
+#endif
+
+// windows compat
+#if !defined(TOML_ENABLE_WINDOWS_COMPAT) && defined(TOML_WINDOWS_COMPAT) // was TOML_WINDOWS_COMPAT pre-3.0
+#define TOML_ENABLE_WINDOWS_COMPAT TOML_WINDOWS_COMPAT
+#endif
+#if !defined(TOML_ENABLE_WINDOWS_COMPAT) || (defined(TOML_ENABLE_WINDOWS_COMPAT) && TOML_ENABLE_WINDOWS_COMPAT) \
+ || TOML_INTELLISENSE
+#undef TOML_ENABLE_WINDOWS_COMPAT
+#define TOML_ENABLE_WINDOWS_COMPAT 1
+#endif
+
+#if !TOML_WINDOWS
+#undef TOML_ENABLE_WINDOWS_COMPAT
+#define TOML_ENABLE_WINDOWS_COMPAT 0
+#endif
+
+#ifndef TOML_INCLUDE_WINDOWS_H
+#define TOML_INCLUDE_WINDOWS_H 0
+#endif
+
+// custom optional
+#ifdef TOML_OPTIONAL_TYPE
+#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 1
+#else
+#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
+#endif
+
+// exceptions (library use)
+#if TOML_COMPILER_HAS_EXCEPTIONS
+#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
+#undef TOML_EXCEPTIONS
+#define TOML_EXCEPTIONS 1
+#endif
+#else
+#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS
+#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler.
+#endif
+#undef TOML_EXCEPTIONS
+#define TOML_EXCEPTIONS 0
+#endif
+
+// calling convention for static/free/friend functions
+#ifndef TOML_CALLCONV
+#define TOML_CALLCONV
+#endif
+
+#ifndef TOML_UNDEF_MACROS
+#define TOML_UNDEF_MACROS 1
+#endif
+
+#ifndef TOML_MAX_NESTED_VALUES
+#define TOML_MAX_NESTED_VALUES 256
+// this refers to the depth of nested values, e.g. inline tables and arrays.
+// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job...
+#endif
+
+#ifdef TOML_CHAR_8_STRINGS
+#if TOML_CHAR_8_STRINGS
+#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; all value setters and getters now work with char8_t strings implicitly.
+#endif
+#endif
+
+#ifdef TOML_LARGE_FILES
+#if !TOML_LARGE_FILES
+#error Support for !TOML_LARGE_FILES (i.e. 'small files') was removed in toml++ 3.0.0.
+#endif
+#endif
+
+#ifndef TOML_LIFETIME_HOOKS
+#define TOML_LIFETIME_HOOKS 0
+#endif
+
+#ifdef NDEBUG
+#undef TOML_ASSERT
+#define TOML_ASSERT(expr) static_assert(true)
+#endif
+#ifndef TOML_ASSERT
+#ifndef assert
+TOML_DISABLE_WARNINGS;
+#include
+TOML_ENABLE_WARNINGS;
+#endif
+#define TOML_ASSERT(expr) assert(expr)
+#endif
+#ifdef NDEBUG
+#define TOML_ASSERT_ASSUME(expr) TOML_ASSUME(expr)
+#else
+#define TOML_ASSERT_ASSUME(expr) TOML_ASSERT(expr)
+#endif
+
+#ifndef TOML_ENABLE_FLOAT16
+#define TOML_ENABLE_FLOAT16 0
+#endif
+
+#if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL))
+// not supported by any version of GCC or Clang as of 26/11/2020
+// not supported by any version of ICC on Linux as of 11/01/2021
+#define TOML_FLOAT_CHARCONV 0
+#endif
+#if !defined(TOML_INT_CHARCONV) && (defined(__EMSCRIPTEN__) || defined(__APPLE__))
+// causes link errors on emscripten
+// causes Mac OS SDK version errors on some versions of Apple Clang
+#define TOML_INT_CHARCONV 0
+#endif
+#ifndef TOML_INT_CHARCONV
+#define TOML_INT_CHARCONV 1
+#endif
+#ifndef TOML_FLOAT_CHARCONV
+#define TOML_FLOAT_CHARCONV 1
+#endif
+#if (TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV) && !TOML_HAS_INCLUDE()
+#undef TOML_INT_CHARCONV
+#undef TOML_FLOAT_CHARCONV
+#define TOML_INT_CHARCONV 0
+#define TOML_FLOAT_CHARCONV 0
+#endif
+
+#if defined(__cpp_concepts) && __cpp_concepts >= 201907
+#define TOML_REQUIRES(...) requires(__VA_ARGS__)
+#else
+#define TOML_REQUIRES(...)
+#endif
+#define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0
+#define TOML_CONSTRAINED_TEMPLATE(condition, ...) \
+ template <__VA_ARGS__ TOML_ENABLE_IF(condition)> \
+ TOML_REQUIRES(condition)
+#define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__)
+
+#if defined(__SIZEOF_FLOAT128__) && defined(__FLT128_MANT_DIG__) && defined(__LDBL_MANT_DIG__) \
+ && __FLT128_MANT_DIG__ > __LDBL_MANT_DIG__
+#define TOML_FLOAT128 __float128
+#endif
+
+#ifdef __SIZEOF_INT128__
+#define TOML_INT128 __int128_t
+#define TOML_UINT128 __uint128_t
+#endif
+
+// clang-format off
+
+//******** impl/version.hpp ******************************************************************************************
+
+#define TOML_LIB_MAJOR 3
+#define TOML_LIB_MINOR 4
+#define TOML_LIB_PATCH 0
+
+#define TOML_LANG_MAJOR 1
+#define TOML_LANG_MINOR 0
+#define TOML_LANG_PATCH 0
+
+//******** impl/preprocessor.hpp *************************************************************************************
+
+#define TOML_LIB_SINGLE_HEADER 1
+
+#if TOML_ENABLE_UNRELEASED_FEATURES
+ #define TOML_LANG_EFFECTIVE_VERSION \
+ TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH+1)
+#else
+ #define TOML_LANG_EFFECTIVE_VERSION \
+ TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH)
+#endif
+
+#define TOML_LANG_HIGHER_THAN(major, minor, patch) \
+ (TOML_LANG_EFFECTIVE_VERSION > TOML_MAKE_VERSION(major, minor, patch))
+
+#define TOML_LANG_AT_LEAST(major, minor, patch) \
+ (TOML_LANG_EFFECTIVE_VERSION >= TOML_MAKE_VERSION(major, minor, patch))
+
+#define TOML_LANG_UNRELEASED \
+ TOML_LANG_HIGHER_THAN(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH)
+
+#ifndef TOML_ABI_NAMESPACES
+ #if TOML_DOXYGEN
+ #define TOML_ABI_NAMESPACES 0
+ #else
+ #define TOML_ABI_NAMESPACES 1
+ #endif
+#endif
+#if TOML_ABI_NAMESPACES
+ #define TOML_NAMESPACE_START namespace toml { inline namespace TOML_CONCAT(v, TOML_LIB_MAJOR)
+ #define TOML_NAMESPACE_END } static_assert(true)
+ #define TOML_NAMESPACE ::toml::TOML_CONCAT(v, TOML_LIB_MAJOR)
+ #define TOML_ABI_NAMESPACE_START(name) inline namespace name { static_assert(true)
+ #define TOML_ABI_NAMESPACE_BOOL(cond, T, F) TOML_ABI_NAMESPACE_START(TOML_CONCAT(TOML_EVAL_BOOL_, cond)(T, F))
+ #define TOML_ABI_NAMESPACE_END } static_assert(true)
+#else
+ #define TOML_NAMESPACE_START namespace toml
+ #define TOML_NAMESPACE_END static_assert(true)
+ #define TOML_NAMESPACE toml
+ #define TOML_ABI_NAMESPACE_START(...) static_assert(true)
+ #define TOML_ABI_NAMESPACE_BOOL(...) static_assert(true)
+ #define TOML_ABI_NAMESPACE_END static_assert(true)
+#endif
+#define TOML_IMPL_NAMESPACE_START TOML_NAMESPACE_START { namespace impl
+#define TOML_IMPL_NAMESPACE_END } TOML_NAMESPACE_END
+#if TOML_HEADER_ONLY
+ #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); TOML_IMPL_NAMESPACE_START
+ #define TOML_ANON_NAMESPACE_END TOML_IMPL_NAMESPACE_END
+ #define TOML_ANON_NAMESPACE TOML_NAMESPACE::impl
+ #define TOML_EXTERNAL_LINKAGE inline
+ #define TOML_INTERNAL_LINKAGE inline
+#else
+ #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); \
+ using namespace toml; \
+ namespace
+ #define TOML_ANON_NAMESPACE_END static_assert(true)
+ #define TOML_ANON_NAMESPACE
+ #define TOML_EXTERNAL_LINKAGE
+ #define TOML_INTERNAL_LINKAGE static
+#endif
+
+// clang-format on
+
+// clang-format off
+
+#if TOML_SIMPLE_STATIC_ASSERT_MESSAGES
+
+ #define TOML_SA_NEWLINE " "
+ #define TOML_SA_LIST_SEP ", "
+ #define TOML_SA_LIST_BEG " ("
+ #define TOML_SA_LIST_END ")"
+ #define TOML_SA_LIST_NEW " "
+ #define TOML_SA_LIST_NXT ", "
+
+#else
+
+ #define TOML_SA_NEWLINE "\n| "
+ #define TOML_SA_LIST_SEP TOML_SA_NEWLINE " - "
+ #define TOML_SA_LIST_BEG TOML_SA_LIST_SEP
+ #define TOML_SA_LIST_END
+ #define TOML_SA_LIST_NEW TOML_SA_NEWLINE TOML_SA_NEWLINE
+ #define TOML_SA_LIST_NXT TOML_SA_LIST_NEW
+
+#endif
+
+#define TOML_SA_NATIVE_VALUE_TYPE_LIST \
+ TOML_SA_LIST_BEG "std::string" \
+ TOML_SA_LIST_SEP "int64_t" \
+ TOML_SA_LIST_SEP "double" \
+ TOML_SA_LIST_SEP "bool" \
+ TOML_SA_LIST_SEP "toml::date" \
+ TOML_SA_LIST_SEP "toml::time" \
+ TOML_SA_LIST_SEP "toml::date_time" \
+ TOML_SA_LIST_END
+
+#define TOML_SA_NODE_TYPE_LIST \
+ TOML_SA_LIST_BEG "toml::table" \
+ TOML_SA_LIST_SEP "toml::array" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_SEP "toml::value" \
+ TOML_SA_LIST_END
+
+#define TOML_SA_UNWRAPPED_NODE_TYPE_LIST \
+ TOML_SA_LIST_NEW "A native TOML value type" \
+ TOML_SA_NATIVE_VALUE_TYPE_LIST \
+ \
+ TOML_SA_LIST_NXT "A TOML node type" \
+ TOML_SA_NODE_TYPE_LIST
+
+// clang-format on
+
+TOML_PUSH_WARNINGS;
+TOML_DISABLE_SPAM_WARNINGS;
+TOML_DISABLE_SWITCH_WARNINGS;
+TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
+
+// misc warning false-positives
+#if TOML_MSVC
+#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch
+#if TOML_SHARED_LIB
+#pragma warning(disable : 4251) // dll exports for std lib types
+#endif
+#elif TOML_CLANG
+TOML_PRAGMA_CLANG(diagnostic ignored "-Wheader-hygiene")
+#if TOML_CLANG >= 12
+TOML_PRAGMA_CLANG(diagnostic ignored "-Wc++20-extensions")
+#endif
+#if TOML_CLANG == 13
+TOML_PRAGMA_CLANG(diagnostic ignored "-Wreserved-identifier")
+#endif
+#endif
+
+//******** impl/std_new.hpp ******************************************************************************************
+
+TOML_DISABLE_WARNINGS;
+#include
+TOML_ENABLE_WARNINGS;
+
+#if (!defined(__apple_build_version__) && TOML_CLANG >= 8) || TOML_GCC >= 7 || TOML_ICC >= 1910 || TOML_MSVC >= 1914
+#define TOML_LAUNDER(x) __builtin_launder(x)
+#elif defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+#define TOML_LAUNDER(x) std::launder(x)
+#else
+#define TOML_LAUNDER(x) x
+#endif
+
+//******** impl/std_string.hpp ***************************************************************************************
+
+TOML_DISABLE_WARNINGS;
+#include
+#include
+TOML_ENABLE_WARNINGS;
+
+#if TOML_DOXYGEN \
+ || (defined(__cpp_char8_t) && __cpp_char8_t >= 201811 && defined(__cpp_lib_char8_t) \
+ && __cpp_lib_char8_t >= 201907)
+#define TOML_HAS_CHAR8 1
+#else
+#define TOML_HAS_CHAR8 0
+#endif
+
+namespace toml // non-abi namespace; this is not an error
+{
+ using namespace std::string_literals;
+ using namespace std::string_view_literals;
+}
+
+#if TOML_ENABLE_WINDOWS_COMPAT
+
+TOML_IMPL_NAMESPACE_START
+{
+ TOML_NODISCARD
+ TOML_EXPORTED_FREE_FUNCTION
+ std::string narrow(std::wstring_view);
+
+ TOML_NODISCARD
+ TOML_EXPORTED_FREE_FUNCTION
+ std::wstring widen(std::string_view);
+
+#if TOML_HAS_CHAR8
+
+ TOML_NODISCARD
+ TOML_EXPORTED_FREE_FUNCTION
+ std::wstring widen(std::u8string_view);
+
+#endif
+}
+TOML_IMPL_NAMESPACE_END;
+
+#endif // TOML_ENABLE_WINDOWS_COMPAT
+
+//******** impl/std_optional.hpp *************************************************************************************
+
+TOML_DISABLE_WARNINGS;
+#if !TOML_HAS_CUSTOM_OPTIONAL_TYPE
+#include
+#endif
+TOML_ENABLE_WARNINGS;
+
+TOML_NAMESPACE_START
+{
+#if TOML_HAS_CUSTOM_OPTIONAL_TYPE
+
+ template
+ using optional = TOML_OPTIONAL_TYPE;
+
+#else
+
+ template
+ using optional = std::optional;
+
+#endif
+}
+TOML_NAMESPACE_END;
+
+//******** impl/forward_declarations.hpp *****************************************************************************
+
+TOML_DISABLE_WARNINGS;
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+TOML_ENABLE_WARNINGS;
+TOML_PUSH_WARNINGS;
+#ifdef _MSC_VER
+#ifndef __clang__
+#pragma inline_recursion(on)
+#endif
+#pragma push_macro("min")
+#pragma push_macro("max")
+#undef min
+#undef max
+#endif
+
+#ifndef TOML_DISABLE_ENVIRONMENT_CHECKS
+#define TOML_ENV_MESSAGE \
+ "If you're seeing this error it's because you're building toml++ for an environment that doesn't conform to " \
+ "one of the 'ground truths' assumed by the library. Essentially this just means that I don't have the " \
+ "resources to test on more platforms, but I wish I did! You can try disabling the checks by defining " \
+ "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue at " \
+ "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target environment. " \
+ "Thanks!"
+
+static_assert(CHAR_BIT == 8, TOML_ENV_MESSAGE);
+#ifdef FLT_RADIX
+static_assert(FLT_RADIX == 2, TOML_ENV_MESSAGE);
+#endif
+static_assert('A' == 65, TOML_ENV_MESSAGE);
+static_assert(sizeof(double) == 8, TOML_ENV_MESSAGE);
+static_assert(std::numeric_limits::is_iec559, TOML_ENV_MESSAGE);
+static_assert(std::numeric_limits::digits == 53, TOML_ENV_MESSAGE);
+static_assert(std::numeric_limits::digits10 == 15, TOML_ENV_MESSAGE);
+static_assert(std::numeric_limits::radix == 2, TOML_ENV_MESSAGE);
+
+#undef TOML_ENV_MESSAGE
+#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS
+
+// undocumented forward declarations are hidden from doxygen because they fuck it up =/
+
+namespace toml // non-abi namespace; this is not an error
+{
+ using ::std::size_t;
+ using ::std::intptr_t;
+ using ::std::uintptr_t;
+ using ::std::ptrdiff_t;
+ using ::std::nullptr_t;
+ using ::std::int8_t;
+ using ::std::int16_t;
+ using ::std::int32_t;
+ using ::std::int64_t;
+ using ::std::uint8_t;
+ using ::std::uint16_t;
+ using ::std::uint32_t;
+ using ::std::uint64_t;
+ using ::std::uint_least32_t;
+ using ::std::uint_least64_t;
+}
+
+TOML_NAMESPACE_START
+{
+ struct date;
+ struct time;
+ struct time_offset;
+
+ TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt);
+ struct date_time;
+ TOML_ABI_NAMESPACE_END;
+
+ struct source_position;
+ struct source_region;
+
+ class node;
+ template
+ class node_view;
+
+ class key;
+ class array;
+ class table;
+ template
+ class value;
+
+ class path;
+
+ class toml_formatter;
+ class json_formatter;
+ class yaml_formatter;
+
+ TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
+#if TOML_EXCEPTIONS
+ using parse_result = table;
+#else
+ class parse_result;
+#endif
+ TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
+}
+TOML_NAMESPACE_END;
+
+TOML_IMPL_NAMESPACE_START
+{
+ using node_ptr = std::unique_ptr;
+
+ TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex);
+ class parser;
+ TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
+
+ // clang-format off
+
+ inline constexpr std::string_view control_char_escapes[] =
+ {
+ "\\u0000"sv,
+ "\\u0001"sv,
+ "\\u0002"sv,
+ "\\u0003"sv,
+ "\\u0004"sv,
+ "\\u0005"sv,
+ "\\u0006"sv,
+ "\\u0007"sv,
+ "\\b"sv,
+ "\\t"sv,
+ "\\n"sv,
+ "\\u000B"sv,
+ "\\f"sv,
+ "\\r"sv,
+ "\\u000E"sv,
+ "\\u000F"sv,
+ "\\u0010"sv,
+ "\\u0011"sv,
+ "\\u0012"sv,
+ "\\u0013"sv,
+ "\\u0014"sv,
+ "\\u0015"sv,
+ "\\u0016"sv,
+ "\\u0017"sv,
+ "\\u0018"sv,
+ "\\u0019"sv,
+ "\\u001A"sv,
+ "\\u001B"sv,
+ "\\u001C"sv,
+ "\\u001D"sv,
+ "\\u001E"sv,
+ "\\u001F"sv,
+ };
+
+ inline constexpr std::string_view node_type_friendly_names[] =
+ {
+ "none"sv,
+ "table"sv,
+ "array"sv,
+ "string"sv,
+ "integer"sv,
+ "floating-point"sv,
+ "boolean"sv,
+ "date"sv,
+ "time"sv,
+ "date-time"sv
+ };
+
+ // clang-format on
+}
+TOML_IMPL_NAMESPACE_END;
+
+#if TOML_ABI_NAMESPACES
+#if TOML_EXCEPTIONS
+#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::impl_ex::parser
+#else
+#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::impl_noex::parser
+#endif
+#else
+#define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::parser
+#endif
+
+namespace toml
+{
+}
+
+TOML_NAMESPACE_START // abi namespace
+{
+ inline namespace literals
+ {
+ }
+
+ enum class TOML_CLOSED_ENUM node_type : uint8_t
+ {
+ none,
+ table,
+ array,
+ string,
+ integer,
+ floating_point,
+ boolean,
+ date,
+ time,
+ date_time
+ };
+
+ template
+ inline std::basic_ostream& operator<<(std::basic_ostream& lhs, node_type rhs)
+ {
+ const auto str = impl::node_type_friendly_names[static_cast>(rhs)];
+ using str_char_t = decltype(str)::value_type;
+ if constexpr (std::is_same_v)
+ return lhs << str;
+ else
+ {
+ if constexpr (sizeof(Char) == sizeof(str_char_t))
+ return lhs << std::basic_string_view{ reinterpret_cast(str.data()), str.length() };
+ else
+ return lhs << str.data();
+ }
+ }
+
+ enum class TOML_OPEN_FLAGS_ENUM value_flags : uint16_t // being an "OPEN" flags enum is not an error
+ {
+ none,
+ format_as_binary = 1,
+ format_as_octal = 2,
+ format_as_hexadecimal = 3,
+ };
+ TOML_MAKE_FLAGS(value_flags);
+
+ inline constexpr value_flags preserve_source_value_flags =
+ POXY_IMPLEMENTATION_DETAIL(value_flags{ static_cast>(-1) });
+
+ enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t
+ {
+ none,
+ quote_dates_and_times = (1ull << 0),
+ quote_infinities_and_nans = (1ull << 1),
+ allow_literal_strings = (1ull << 2),
+ allow_multi_line_strings = (1ull << 3),
+ allow_real_tabs_in_strings = (1ull << 4),
+ allow_unicode_strings = (1ull << 5),
+ allow_binary_integers = (1ull << 6),
+ allow_octal_integers = (1ull << 7),
+ allow_hexadecimal_integers = (1ull << 8),
+ indent_sub_tables = (1ull << 9),
+ indent_array_elements = (1ull << 10),
+ indentation = indent_sub_tables | indent_array_elements,
+ relaxed_float_precision = (1ull << 11),
+ terse_key_value_pairs = (1ull << 12),
+ };
+ TOML_MAKE_FLAGS(format_flags);
+
+ template
+ struct TOML_TRIVIAL_ABI inserter
+ {
+ static_assert(std::is_reference_v);
+
+ T value;
+ };
+ template
+ inserter(T&&) -> inserter;
+ template
+ inserter(T&) -> inserter;
+
+ using default_formatter = toml_formatter;
+}
+TOML_NAMESPACE_END;
+
+TOML_IMPL_NAMESPACE_START
+{
+ template
+ using remove_cvref = std::remove_cv_t>;
+
+ template
+ using common_signed_type = std::common_type_t...>;
+
+ template
+ inline constexpr bool is_one_of = (false || ... || std::is_same_v);
+
+ template
+ inline constexpr bool all_integral = (std::is_integral_v && ...);
+
+ template
+ inline constexpr bool is_cvref = std::is_reference_v || std::is_const_v || std::is_volatile_v;
+
+ template
+ inline constexpr bool is_wide_string =
+ is_one_of, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>;
+
+ template
+ inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string>
+#if TOML_HAS_CHAR8
+ && !std::is_same_v, std::u8string>
+#endif
+
+ && !is_wide_string;
+
+ template
+ struct copy_ref_;
+ template
+ using copy_ref = typename copy_ref_::type;
+
+ template
+ struct copy_ref_
+ {
+ using type = Dest;
+ };
+
+ template
+ struct copy_ref_
+ {
+ using type = std::add_lvalue_reference_t;
+ };
+
+ template
+ struct copy_ref_
+ {
+ using type = std::add_rvalue_reference_t;
+ };
+
+ template
+ struct copy_cv_;
+ template
+ using copy_cv = typename copy_cv_::type;
+
+ template
+ struct copy_cv_
+ {
+ using type = Dest;
+ };
+
+ template
+ struct copy_cv_
+ {
+ using type = std::add_const_t;
+ };
+
+ template
+ struct copy_cv_
+ {
+ using type = std::add_volatile_t;
+ };
+
+ template
+ struct copy_cv_
+ {
+ using type = std::add_cv_t;
+ };
+
+ template
+ using copy_cvref =
+ copy_ref, std::remove_reference_t>, Dest>, Src>;
+
+ template
+ inline constexpr bool always_false = false;
+
+ template
+ inline constexpr bool first_is_same = false;
+ template
+ inline constexpr bool first_is_same = true;
+
+ template >
+ struct underlying_type_
+ {
+ using type = std::underlying_type_t;
+ };
+ template
+ struct underlying_type_
+ {
+ using type = T;
+ };
+ template
+ using underlying_type = typename underlying_type_::type;
+
+ // general value traits
+ // (as they relate to their equivalent native TOML type)
+ struct default_value_traits
+ {
+ using native_type = void;
+ static constexpr bool is_native = false;
+ static constexpr bool is_losslessly_convertible_to_native = false;
+ static constexpr bool can_represent_native = false;
+ static constexpr bool can_partially_represent_native = false;
+ static constexpr auto type = node_type::none;
+ };
+
+ template
+ struct value_traits;
+
+ template >
+ struct value_traits_base_selector
+ {
+ static_assert(!is_cvref);
+
+ using type = default_value_traits;
+ };
+ template
+ struct value_traits_base_selector
+ {
+ static_assert(!is_cvref);
+
+ using type = value_traits>;
+ };
+
+ template
+ struct value_traits : value_traits_base_selector::type
+ {};
+ template
+ struct value_traits : value_traits
+ {};
+ template
+ struct value_traits : value_traits
+ {};
+ template
+ struct value_traits : value_traits
+ {};
+ template
+ struct value_traits : value_traits
+ {};
+ template
+ struct value_traits : value_traits
+ {};
+
+ // integer value_traits specializations - standard types
+ template
+ struct integer_limits
+ {
+ static constexpr T min = T{ (std::numeric_limits>::min)() };
+ static constexpr T max = T{ (std::numeric_limits>::max)() };
+ };
+ template
+ struct integer_traits_base : integer_limits
+ {
+ using native_type = int64_t;
+ static constexpr bool is_native = std::is_same_v, native_type>;
+ static constexpr bool is_signed = static_cast>(-1) < underlying_type{};
+ static constexpr auto type = node_type::integer;
+ static constexpr bool can_partially_represent_native = true;
+ };
+ template
+ struct unsigned_integer_traits : integer_traits_base
+ {
+ static constexpr bool is_losslessly_convertible_to_native =
+ integer_limits>::max <= 9223372036854775807ULL;
+ static constexpr bool can_represent_native = false;
+ };
+ template
+ struct signed_integer_traits : integer_traits_base
+ {
+ using native_type = int64_t;
+ static constexpr bool is_losslessly_convertible_to_native =
+ integer_limits>::min >= (-9223372036854775807LL - 1LL)
+ && integer_limits>::max <= 9223372036854775807LL;
+ static constexpr bool can_represent_native =
+ integer_limits>::min <= (-9223372036854775807LL - 1LL)
+ && integer_limits>::max >= 9223372036854775807LL;
+ };
+ template ::is_signed>
+ struct integer_traits : signed_integer_traits
+ {};
+ template
+ struct integer_traits : unsigned_integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+ static_assert(value_traits::is_native);
+ static_assert(value_traits::is_signed);
+ static_assert(value_traits::is_losslessly_convertible_to_native);
+ static_assert(value_traits::can_represent_native);
+ static_assert(value_traits::can_partially_represent_native);
+
+ // integer value_traits specializations - non-standard types
+#ifdef TOML_INT128
+ template <>
+ struct integer_limits
+ {
+ static constexpr TOML_INT128 max =
+ static_cast((TOML_UINT128{ 1u } << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1);
+ static constexpr TOML_INT128 min = -max - TOML_INT128{ 1 };
+ };
+ template <>
+ struct integer_limits
+ {
+ static constexpr TOML_UINT128 min = TOML_UINT128{};
+ static constexpr TOML_UINT128 max = (2u * static_cast(integer_limits::max)) + 1u;
+ };
+ template <>
+ struct value_traits : integer_traits
+ {};
+ template <>
+ struct value_traits : integer_traits
+ {};
+#endif
+#ifdef TOML_SMALL_INT_TYPE
+ template <>
+ struct value_traits : signed_integer_traits
+ {};
+#endif
+
+ // floating-point traits base
+ template
+ struct float_traits_base
+ {
+ static constexpr auto type = node_type::floating_point;
+ using native_type = double;
+ static constexpr bool is_native = std::is_same_v;
+ static constexpr bool is_signed = true;
+
+ static constexpr int bits = static_cast(sizeof(T) * CHAR_BIT);
+ static constexpr int digits = MantissaDigits;
+ static constexpr int digits10 = DecimalDigits;
+
+ static constexpr bool is_losslessly_convertible_to_native = bits <= 64 //
+ && digits <= 53 // DBL_MANT_DIG
+ && digits10 <= 15; // DBL_DIG
+
+ static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG
+ && digits10 >= 15; // DBL_DIG
+
+ static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0;
+ };
+ template
+ struct float_traits : float_traits_base::digits, std::numeric_limits::digits10>
+ {};
+#if TOML_ENABLE_FLOAT16
+ template <>
+ struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__>
+ {};
+#endif
+#ifdef TOML_FLOAT128
+ template <>
+ struct float_traits : float_traits_base
+ {};
+#endif
+
+ // floating-point traits
+ template <>
+ struct value_traits : float_traits
+ {};
+ template <>
+ struct value_traits : float_traits
+ {};
+ template <>
+ struct value_traits : float_traits
+ {};
+#if TOML_ENABLE_FLOAT16
+ template <>
+ struct value_traits<_Float16> : float_traits<_Float16>
+ {};
+#endif
+#ifdef TOML_FLOAT128
+ template <>
+ struct value_traits : float_traits
+ {};
+#endif
+#ifdef TOML_SMALL_FLOAT_TYPE
+ template <>
+ struct value_traits : float_traits
+ {};
+#endif
+ static_assert(value_traits::is_native);
+ static_assert(value_traits::is_losslessly_convertible_to_native);
+ static_assert(value_traits::can_represent_native);
+ static_assert(value_traits::can_partially_represent_native);
+
+ // string value_traits specializations - char-based strings
+ template
+ struct string_traits
+ {
+ using native_type = std::string;
+ static constexpr bool is_native = std::is_same_v;
+ static constexpr bool is_losslessly_convertible_to_native = true;
+ static constexpr bool can_represent_native =
+ !std::is_array_v && (!std::is_pointer_v || std::is_const_v>);
+ static constexpr bool can_partially_represent_native = can_represent_native;
+ static constexpr auto type = node_type::string;
+ };
+ template <>
+ struct value_traits : string_traits
+ {};
+ template <>
+ struct value_traits : string_traits
+ {};
+ template <>
+ struct value_traits : string_traits
+ {};
+ template
+ struct value_traits : string_traits
+ {};
+ template <>
+ struct value_traits : string_traits
+ {};
+ template
+ struct value_traits