looper/options.hpp

130 lines
4.3 KiB
C++
Raw Normal View History

#pragma once
#include "thirdparty/toml.hpp"
#include "log.hpp"
#include <string>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <optional>
#define OPTIONS (*Looper::Options::options)
namespace Looper::Options {
extern toml::table *options;
void save_options();
void load_options();
2024-05-02 14:52:11 -07:00
extern std::optional<const char *> options_path_override;
std::string get_options_path();
inline bool option_set(std::string name) {
toml::path path(name);
auto *tmp = options;
std::vector<std::string> components;
for (auto component : path) {
components.push_back((std::string)component);
}
std::string last_component = components[components.size() - 1];
components.pop_back();
for (auto component : components) {
auto &cur_tmp = *tmp;
if (cur_tmp.contains(component)) {
if (!cur_tmp[component].is_table()) {
return false;
} else {
tmp = cur_tmp[component].as_table();
}
} else {
return false;
}
}
if (tmp->contains(last_component)) {
return true;
} else {
return false;
}
}
inline void delete_option(std::string name) {
toml::path path(name);
auto *tmp = &OPTIONS;
std::vector<std::string> components;
for (auto component : path) {
std::string component_str = (std::string)component;
components.push_back(component_str);
}
while (!path.empty()) {
if (option_set(path.str())) {
toml::path parent_path = path.parent();
auto &parent = OPTIONS.at(parent_path.str());
auto last_component = path[path.size() - 1];
if (parent.is_table()) {
auto &table = *parent.as_table();
table.erase((std::string)last_component);
if (!table.empty()) {
return;
}
} else if (parent.is_array()) {
auto &array = *parent.as_array();
array.erase(array.begin() + last_component.index());
if (!array.empty()) {
return;
}
}
path = parent_path;
2024-10-16 10:07:23 -07:00
} else {
break;
}
}
2024-05-01 09:07:08 -07:00
save_options();
}
template<class T>
void set_option(std::string name, T value) {
toml::path path(name);
auto *tmp = &OPTIONS;
std::vector<std::string> components;
for (auto component : path) {
std::string component_str = (std::string)component;
components.push_back(component_str);
}
auto last_component = components[components.size() - 1];
components.pop_back();
for (auto component : components) {
auto &cur_tmp = *tmp;
if (cur_tmp.contains(component)) {
if (cur_tmp[component].is_table()) {
tmp = cur_tmp[component].as_table();
} else {
return;
}
} else {
tmp->insert_or_assign(component, toml::table());
tmp = cur_tmp[component].as_table();
}
}
tmp->insert_or_assign(last_component, value);
2024-05-01 09:07:08 -07:00
save_options();
}
template<class T>
inline void init_option(std::string name, T value) {
if (!option_set(name)) {
set_option<T>(name, value);
}
}
template<class T>
T get_option(std::string name, std::optional<T> initial_value = {}) {
if (initial_value.has_value()) {
init_option<T>(name, initial_value.value());
}
2024-08-08 13:12:37 -07:00
auto option = OPTIONS.at_path(name);
return (**(option).as<T>());
}
template<>
inline bool get_option<bool>(std::string name, std::optional<bool> initial_value) {
if (initial_value.has_value()) {
init_option<bool>(name, initial_value.value());
}
auto option = OPTIONS.at_path(name).as<bool>();
if (option == nullptr) {
return false;
}
return (option->get());
}
}
2024-10-16 10:07:23 -07:00
#define UI_BACKEND() (Looper::Options::get_option<std::string>("ui.frontend", "imgui"))