mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-13 21:02:43 +08:00

With gcc 14 some C++ Standard Library headers have been changed to no longer include other headers that were being used internally by the library. In logiops's case it is the <algorithm> header. Downstream Gentoo bug: https://bugs.gentoo.org/917002 GCC 14 porting guide: https://gcc.gnu.org/gcc-14/porting_to.html Signed-off-by: Kostadin Shishmanov <kocelfc@tutanota.com>
204 lines
6.8 KiB
C++
204 lines
6.8 KiB
C++
/*
|
|
* Copyright 2022 PixlOne
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
#ifndef LOGID_CONFIG_GROUP_H
|
|
#define LOGID_CONFIG_GROUP_H
|
|
|
|
#include <libconfig.h++>
|
|
#include <type_traits>
|
|
#include <functional>
|
|
#include <utility>
|
|
#include <algorithm>
|
|
|
|
namespace logid::config {
|
|
template<typename T>
|
|
void set(libconfig::Setting& parent,
|
|
const std::string& name,
|
|
const T& t);
|
|
|
|
template<typename T>
|
|
void set(libconfig::Setting& parent, const T& t);
|
|
|
|
template<typename T>
|
|
auto get(const libconfig::Setting& parent, const std::string& name);
|
|
|
|
template<typename T>
|
|
void append(libconfig::Setting& list, const T& t);
|
|
|
|
template<typename T, typename... M>
|
|
struct group_io {
|
|
};
|
|
|
|
template<typename T>
|
|
struct group_io<T> {
|
|
static void get(const libconfig::Setting&, T*,
|
|
const std::vector<std::string>&, const std::size_t) {}
|
|
|
|
static void set(libconfig::Setting&, const T*,
|
|
const std::vector<std::string>&, const std::size_t) {}
|
|
};
|
|
|
|
template<typename T, typename A, typename... M>
|
|
struct group_io<T, A, M...> {
|
|
static void get(const libconfig::Setting& s, T* t,
|
|
const std::vector<std::string>& names,
|
|
const std::size_t index, A T::* arg, M T::*... rest) {
|
|
auto& x = t->*(arg);
|
|
A old{x};
|
|
try {
|
|
x = config::get<A>(s, names[index]);
|
|
group_io<T, M...>::get(s, t, names, index + 1, rest...);
|
|
} catch (libconfig::SettingTypeException& e) {
|
|
x = old;
|
|
throw;
|
|
} catch (libconfig::SettingException& e) {
|
|
x = old;
|
|
throw libconfig::SettingTypeException(s);
|
|
}
|
|
}
|
|
|
|
static void set(libconfig::Setting& s, const T* t,
|
|
const std::vector<std::string>& names,
|
|
const std::size_t index, A T::* arg, M T::*... rest) {
|
|
config::set(s, names[index], t->*(arg));
|
|
group_io<T, M...>::set(s, t, names, index + 1, rest...);
|
|
}
|
|
};
|
|
|
|
template<typename Sign>
|
|
struct signed_group;
|
|
|
|
struct group {
|
|
private:
|
|
const std::vector<std::string> _names;
|
|
const std::function<void(const libconfig::Setting&, group*,
|
|
const std::vector<std::string>&)> _getter;
|
|
const std::function<void(libconfig::Setting&, const group*,
|
|
const std::vector<std::string>&)> _setter;
|
|
|
|
template<typename Sign>
|
|
friend
|
|
struct signed_group;
|
|
protected:
|
|
template<typename T, typename... M>
|
|
explicit group(const std::array<std::string, sizeof...(M)>& names,
|
|
M T::*... args) :
|
|
_names(names.begin(), names.end()),
|
|
_getter([args...](const libconfig::Setting& s, group* g,
|
|
const std::vector<std::string>& names) {
|
|
T* t = dynamic_cast<T*>(g);
|
|
group_io<T, M...>::get(s, t, names, 0, args...);
|
|
}),
|
|
_setter([args...](libconfig::Setting& s, const group* g,
|
|
const std::vector<std::string>& names) {
|
|
const T* t = dynamic_cast<const T*>(g);
|
|
group_io<T, M...>::set(s, t, names, 0, args...);
|
|
}) {
|
|
static_assert(std::is_base_of<group, T>::value);
|
|
}
|
|
|
|
group() : _getter([](const libconfig::Setting&, group*,
|
|
const std::vector<std::string>&) {}),
|
|
_setter([](libconfig::Setting&, const group*,
|
|
const std::vector<std::string>&) {}) {}
|
|
|
|
public:
|
|
group(const group& o) = default;
|
|
|
|
group(group&& o) noexcept = default;
|
|
|
|
group& operator=(const group&) {
|
|
return *this;
|
|
}
|
|
|
|
group& operator=(group&&) noexcept {
|
|
return *this;
|
|
}
|
|
|
|
virtual ~group() = default;
|
|
|
|
virtual void _save(libconfig::Setting& setting) const {
|
|
_setter(setting, this, _names);
|
|
}
|
|
|
|
virtual void _load(const libconfig::Setting& setting) {
|
|
_getter(setting, this, _names);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct normalize_signature {
|
|
static const T& make(const T& ret) { return ret; }
|
|
};
|
|
|
|
template<>
|
|
struct normalize_signature<std::string> {
|
|
static std::string make(const std::string& data) {
|
|
std::string ret = data;
|
|
std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
template<typename Sign>
|
|
struct signed_group : public group {
|
|
private:
|
|
const std::string _sig_field;
|
|
const Sign _signature;
|
|
protected:
|
|
signed_group(std::string sign_name, const Sign& sign_data) :
|
|
group(), _sig_field(std::move(sign_name)),
|
|
_signature(normalize_signature<Sign>::make(sign_data)) {}
|
|
|
|
template<typename T, typename... M>
|
|
signed_group(
|
|
std::string sign_name, const Sign& sign_data,
|
|
const std::array<std::string, sizeof...(M)>& names,
|
|
M T::*... args) : group(names, args...),
|
|
_sig_field(std::move(sign_name)),
|
|
_signature(normalize_signature<Sign>::make(sign_data)) {}
|
|
|
|
public:
|
|
signed_group(const signed_group& o) = default;
|
|
|
|
signed_group(signed_group&& o) noexcept = default;
|
|
|
|
signed_group& operator=(const signed_group&) {
|
|
return *this;
|
|
}
|
|
|
|
signed_group& operator=(signed_group&&) noexcept {
|
|
return *this;
|
|
}
|
|
|
|
void _save(libconfig::Setting& setting) const override {
|
|
set(setting, _sig_field, _signature);
|
|
_setter(setting, this, _names);
|
|
}
|
|
|
|
void _load(const libconfig::Setting& setting) override {
|
|
if (normalize_signature<Sign>::make(get<Sign>(setting, _sig_field))
|
|
!= _signature)
|
|
throw libconfig::SettingTypeException(setting);
|
|
_getter(setting, this, _names);
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif //LOGID_CONFIG_GROUP_H
|