raid/public/raid/config.hpp

190 lines
5.6 KiB
C++

#pragma once
#if !defined(RAID_PUBLIC_RAID_CONFIG_HPP_INCLUDED)
#define RAID_PUBLIC_RAID_CONFIG_HPP_INCLUDED 1
#include <cstdint>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
#include <mijin/async/coroutine.hpp>
#include <mijin/container/vector_map.hpp>
#include <mijin/memory/dynamic_pointer.hpp>
#include <mijin/types/result.hpp>
#include <mijin/virtual_filesystem/filesystem.hpp>
namespace raid
{
class ConfigValue;
class ConfigArray
{
public:
using iterator = std::vector<ConfigValue>::iterator;
using const_iterator = std::vector<ConfigValue>::const_iterator;
private:
std::vector<ConfigValue> mValues;
public:
ConfigArray() noexcept = default;
ConfigArray(const ConfigArray&) = default;
ConfigArray(ConfigArray&&) noexcept = default;
explicit ConfigArray(std::vector<ConfigValue> values) noexcept : mValues(std::move(values)) {}
ConfigArray& operator=(const ConfigArray&) = default;
ConfigArray& operator=(ConfigArray&&) noexcept = default;
const ConfigValue& operator[](std::size_t idx) const noexcept { return mValues[idx]; }
[[nodiscard]]
const std::vector<ConfigValue>& getValues() const noexcept { return mValues; }
[[nodiscard]]
std::size_t getSize() const noexcept { return mValues.size(); }
void append(ConfigValue value);
void setAt(std::size_t idx, ConfigValue value);
void removeAt(std::size_t idx, std::size_t count = 1);
[[nodiscard]]
bool isEmpty() const noexcept { return mValues.empty(); }
[[nodiscard]]
iterator begin() noexcept { return mValues.begin(); }
[[nodiscard]]
iterator end() noexcept { return mValues.end(); }
[[nodiscard]]
const_iterator begin() const noexcept { return mValues.begin(); }
[[nodiscard]]
const_iterator end() const noexcept { return mValues.end(); }
};
class ConfigSection
{
private:
mijin::VectorMap<std::string, ConfigValue> mValues;
public:
ConfigSection() noexcept = default;
ConfigSection(const ConfigSection&) = default;
ConfigSection(ConfigSection&&) noexcept = default;
explicit ConfigSection(mijin::VectorMap<std::string, ConfigValue> values) noexcept : mValues(std::move(values)) {}
ConfigSection& operator=(const ConfigSection&) = default;
ConfigSection& operator=(ConfigSection&&) noexcept = default;
const ConfigValue& operator[](std::string_view key) const noexcept;
[[nodiscard]]
ConfigValue& getOrAdd(std::string_view key);
void set(std::string_view key, ConfigValue value);
[[nodiscard]]
mijin::VectorMap<std::string, ConfigValue>& getValues() noexcept { return mValues; }
[[nodiscard]]
const mijin::VectorMap<std::string, ConfigValue>& getValues() const noexcept { return mValues; }
};
using config_int_t = std::int64_t;
class ConfigValue
{
private:
std::variant<std::nullptr_t, bool, config_int_t, double, std::string, ConfigArray, ConfigSection> mContent;
public:
ConfigValue() noexcept : mContent(nullptr) {}
ConfigValue(const ConfigValue&) = default;
ConfigValue(ConfigValue&&) noexcept = default;
ConfigValue(bool content) noexcept : mContent(content) {}
ConfigValue(config_int_t content) noexcept : mContent(content) {}
ConfigValue(double content) noexcept : mContent(content) {}
ConfigValue(std::string content) noexcept : mContent(std::move(content)) {}
ConfigValue(const char* content) noexcept : mContent(std::string(content)) {}
ConfigValue(ConfigArray content) noexcept : mContent(std::move(content)) {}
ConfigValue(ConfigSection content) noexcept : mContent(std::move(content)) {}
ConfigValue& operator=(const ConfigValue&) = default;
ConfigValue& operator=(ConfigValue&&) noexcept = default;
[[nodiscard]]
bool isUndefined() const noexcept { return std::holds_alternative<std::nullptr_t>(mContent); }
[[nodiscard]]
bool isBool() const noexcept { return std::holds_alternative<bool>(mContent); }
[[nodiscard]]
bool isInt() const noexcept { return std::holds_alternative<config_int_t>(mContent); }
[[nodiscard]]
bool isDouble() const noexcept { return std::holds_alternative<double>(mContent); }
[[nodiscard]]
bool isString() const noexcept { return std::holds_alternative<std::string>(mContent); }
[[nodiscard]]
bool isArray() const noexcept { return std::holds_alternative<ConfigArray>(mContent); }
[[nodiscard]]
bool isSection() const noexcept { return std::holds_alternative<ConfigSection>(mContent); }
[[nodiscard]]
bool asBool() const noexcept;
[[nodiscard]]
config_int_t asInt() const noexcept;
[[nodiscard]]
double asDouble() const noexcept;
[[nodiscard]]
const std::string& asString() const noexcept;
[[nodiscard]]
const ConfigArray& asArray() const noexcept;
[[nodiscard]]
ConfigSection& asMutableSection() noexcept;
[[nodiscard]]
const ConfigSection& asSection() const noexcept;
template<typename TFunc>
decltype(auto) visit(TFunc&& func) const noexcept
{
return std::visit(std::forward<TFunc>(func), mContent);
}
};
class FileConfig
{
private:
ConfigSection mRoot;
mijin::PathReference mPath;
bool mDirty = false;
public:
[[nodiscard]]
const ConfigSection& getRoot() const noexcept { return mRoot; }
[[nodiscard]]
const ConfigValue& getValue(std::string_view path) const noexcept;
void setValue(std::string_view path, ConfigValue value) noexcept;
[[nodiscard]]
mijin::Result<> init(mijin::PathReference path);
[[nodiscard]]
mijin::Result<> load();
[[nodiscard]]
mijin::Result<> save(bool force = false);
};
}
#endif // !defined(RAID_PUBLIC_RAID_CONFIG_HPP_INCLUDED)