mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-14 05:12:34 +08:00
Fix compiler warnings on Ubuntu and code cleanup
Fixes some compiler warnings, avoids using anonymous namespaces as much and removes manual inlining for config.
This commit is contained in:
parent
5e436a2bdf
commit
a96036c97d
@ -1 +1 @@
|
|||||||
Subproject commit 745329ed9d41051ddb6e4010229d4b54d868e1a4
|
Subproject commit 4f22a43e3380dc1e9c0a490201f4d745390b623f
|
@ -38,24 +38,25 @@ namespace logid::backend::hidpp10 {
|
|||||||
namespace logid::backend::hidpp {
|
namespace logid::backend::hidpp {
|
||||||
struct DeviceConnectionEvent;
|
struct DeviceConnectionEvent;
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template <typename T>
|
class _deviceWrapper : public T {
|
||||||
class DeviceWrapper : public T {
|
friend class Device;
|
||||||
friend class Device;
|
|
||||||
public:
|
|
||||||
template <typename... Args>
|
|
||||||
explicit DeviceWrapper(Args... args) : T(std::forward<Args>(args)...) { }
|
|
||||||
|
|
||||||
template <typename... Args>
|
public:
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
template<typename... Args>
|
||||||
return std::make_shared<DeviceWrapper>(std::forward<Args>(args)...);
|
explicit _deviceWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||||
}
|
|
||||||
};
|
template<typename... Args>
|
||||||
}
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
|
return std::make_shared<_deviceWrapper>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Device {
|
class Device {
|
||||||
template <typename T>
|
template<typename T>
|
||||||
friend class DeviceWrapper;
|
friend
|
||||||
|
class _deviceWrapper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct EventHandler {
|
struct EventHandler {
|
||||||
std::function<bool(Report&)> condition;
|
std::function<bool(Report&)> condition;
|
||||||
@ -102,7 +103,9 @@ namespace logid::backend::hidpp {
|
|||||||
[[nodiscard]] const std::shared_ptr<raw::RawDevice>& rawDevice() const;
|
[[nodiscard]] const std::shared_ptr<raw::RawDevice>& rawDevice() const;
|
||||||
|
|
||||||
Device(const Device&) = delete;
|
Device(const Device&) = delete;
|
||||||
|
|
||||||
Device(Device&&) = delete;
|
Device(Device&&) = delete;
|
||||||
|
|
||||||
virtual ~Device() = default;
|
virtual ~Device() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -161,16 +164,16 @@ namespace logid::backend::hidpp {
|
|||||||
std::weak_ptr<Device> _self;
|
std::weak_ptr<Device> _self;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
static std::shared_ptr<T> makeDerived(Args... args) {
|
static std::shared_ptr<T> makeDerived(Args... args) {
|
||||||
auto device = DeviceWrapper<T>::make(std::forward<Args>(args)...);
|
auto device = _deviceWrapper<T>::make(std::forward<Args>(args)...);
|
||||||
device->_self = device;
|
device->_self = device;
|
||||||
device->_setupReportsAndInit();
|
device->_setupReportsAndInit();
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template<typename... Args>
|
||||||
static std::shared_ptr<Device> make(Args... args) {
|
static std::shared_ptr<Device> make(Args... args) {
|
||||||
return makeDerived<Device>(std::forward<Args>(args)...);
|
return makeDerived<Device>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@ -26,20 +26,19 @@
|
|||||||
|
|
||||||
namespace logid::backend::hidpp10 {
|
namespace logid::backend::hidpp10 {
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template <typename T>
|
class _receiverMonitorWrapper : public T {
|
||||||
class ReceiverMonitorWrapper : public T {
|
friend class ReceiverMonitor;
|
||||||
friend class ReceiverMonitor;
|
|
||||||
public:
|
|
||||||
template <typename... Args>
|
|
||||||
explicit ReceiverMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) { }
|
|
||||||
|
|
||||||
template <typename... Args>
|
public:
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
template<typename... Args>
|
||||||
return std::make_shared<ReceiverMonitorWrapper>(std::forward<Args>(args)...);
|
explicit _receiverMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||||
}
|
|
||||||
};
|
template<typename... Args>
|
||||||
}
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
|
return std::make_shared<_receiverMonitorWrapper>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr int max_tries = 5;
|
static constexpr int max_tries = 5;
|
||||||
static constexpr int ready_backoff = 250;
|
static constexpr int ready_backoff = 250;
|
||||||
@ -50,7 +49,9 @@ namespace logid::backend::hidpp10 {
|
|||||||
void enumerate();
|
void enumerate();
|
||||||
|
|
||||||
ReceiverMonitor(const ReceiverMonitor&) = delete;
|
ReceiverMonitor(const ReceiverMonitor&) = delete;
|
||||||
|
|
||||||
ReceiverMonitor(ReceiverMonitor&&) = delete;
|
ReceiverMonitor(ReceiverMonitor&&) = delete;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ReceiverMonitor(const std::string& path,
|
ReceiverMonitor(const std::string& path,
|
||||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
||||||
@ -101,9 +102,9 @@ namespace logid::backend::hidpp10 {
|
|||||||
std::weak_ptr<ReceiverMonitor> _self;
|
std::weak_ptr<ReceiverMonitor> _self;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
auto receiver_monitor = ReceiverMonitorWrapper<T>::make(std::forward<Args>(args)...);
|
auto receiver_monitor = _receiverMonitorWrapper<T>::make(std::forward<Args>(args)...);
|
||||||
receiver_monitor->_self = receiver_monitor;
|
receiver_monitor->_self = receiver_monitor;
|
||||||
receiver_monitor->_ready();
|
receiver_monitor->_ready();
|
||||||
return receiver_monitor;
|
return receiver_monitor;
|
||||||
|
@ -36,21 +36,19 @@ namespace logid::backend::raw {
|
|||||||
static constexpr int max_tries = 5;
|
static constexpr int max_tries = 5;
|
||||||
static constexpr int ready_backoff = 500;
|
static constexpr int ready_backoff = 500;
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template<typename T>
|
class _deviceMonitorWrapper : public T {
|
||||||
class DeviceMonitorWrapper : public T {
|
friend class Device;
|
||||||
friend class Device;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
explicit DeviceMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
explicit _deviceMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
return std::make_shared<DeviceMonitorWrapper>(std::forward<Args>(args)...);
|
return std::make_shared<_deviceMonitorWrapper>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
class DeviceMonitor {
|
class DeviceMonitor {
|
||||||
public:
|
public:
|
||||||
@ -62,7 +60,7 @@ namespace logid::backend::raw {
|
|||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
auto device_monitor = DeviceMonitorWrapper<T>::make(std::forward<Args>(args)...);
|
auto device_monitor = _deviceMonitorWrapper<T>::make(std::forward<Args>(args)...);
|
||||||
device_monitor->_self = device_monitor;
|
device_monitor->_self = device_monitor;
|
||||||
device_monitor->ready();
|
device_monitor->ready();
|
||||||
|
|
||||||
@ -79,7 +77,7 @@ namespace logid::backend::raw {
|
|||||||
|
|
||||||
virtual void removeDevice(std::string device) = 0;
|
virtual void removeDevice(std::string device) = 0;
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
[[nodiscard]] std::weak_ptr<T> self() const {
|
[[nodiscard]] std::weak_ptr<T> self() const {
|
||||||
return std::dynamic_pointer_cast<T>(_self.lock());
|
return std::dynamic_pointer_cast<T>(_self.lock());
|
||||||
}
|
}
|
||||||
|
@ -38,55 +38,45 @@ namespace logid::config {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void append(libconfig::Setting& list, const T& t);
|
void append(libconfig::Setting& list, const T& t);
|
||||||
|
|
||||||
namespace {
|
template<typename T, typename... M>
|
||||||
template<typename T, typename... M>
|
struct group_io {
|
||||||
struct group_io {
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct group_io<T> {
|
struct group_io<T> {
|
||||||
static inline void get(
|
static void get(const libconfig::Setting&, T*,
|
||||||
[[maybe_unused]] const libconfig::Setting& s,
|
const std::vector<std::string>&, const std::size_t) {}
|
||||||
[[maybe_unused]] T* t,
|
|
||||||
[[maybe_unused]] const std::vector<std::string>& names,
|
|
||||||
[[maybe_unused]] const std::size_t index) {}
|
|
||||||
|
|
||||||
static inline void set(
|
static void set(libconfig::Setting&, const T*,
|
||||||
[[maybe_unused]] libconfig::Setting& s,
|
const std::vector<std::string>&, const std::size_t) {}
|
||||||
[[maybe_unused]] const T* t,
|
};
|
||||||
[[maybe_unused]] const std::vector<std::string>& names,
|
|
||||||
[[maybe_unused]] const std::size_t index) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename A, typename... M>
|
template<typename T, typename A, typename... M>
|
||||||
struct group_io<T, A, M...> {
|
struct group_io<T, A, M...> {
|
||||||
static inline void get(
|
static void get(const libconfig::Setting& s, T* t,
|
||||||
const libconfig::Setting& s, T* t,
|
const std::vector<std::string>& names,
|
||||||
const std::vector<std::string>& names,
|
const std::size_t index, A T::* arg, M T::*... rest) {
|
||||||
const std::size_t index, A T::* arg, M T::*... rest) {
|
auto& x = t->*(arg);
|
||||||
auto& x = t->*(arg);
|
A old{x};
|
||||||
A old{x};
|
try {
|
||||||
try {
|
x = config::get<A>(s, names[index]);
|
||||||
x = config::get<A>(s, names[index]);
|
group_io<T, M...>::get(s, t, names, index + 1, rest...);
|
||||||
group_io<T, M...>::get(s, t, names, index + 1, rest...);
|
} catch (libconfig::SettingTypeException& e) {
|
||||||
} catch (libconfig::SettingTypeException& e) {
|
x = old;
|
||||||
x = old;
|
throw;
|
||||||
throw;
|
} catch (libconfig::SettingException& e) {
|
||||||
} catch (libconfig::SettingException& e) {
|
x = old;
|
||||||
x = old;
|
throw libconfig::SettingTypeException(s);
|
||||||
throw libconfig::SettingTypeException(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void set(
|
static void set(libconfig::Setting& s, const T* t,
|
||||||
libconfig::Setting& s, const T* t,
|
const std::vector<std::string>& names,
|
||||||
const std::vector<std::string>& names,
|
const std::size_t index, A T::* arg, M T::*... rest) {
|
||||||
const std::size_t index, A T::* arg, M T::*... rest) {
|
config::set(s, names[index], t->*(arg));
|
||||||
config::set(s, names[index], t->*(arg));
|
group_io<T, M...>::set(s, t, names, index + 1, rest...);
|
||||||
group_io<T, M...>::set(s, t, names, index + 1, rest...);
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Sign>
|
template<typename Sign>
|
||||||
struct signed_group;
|
struct signed_group;
|
||||||
@ -149,22 +139,19 @@ namespace logid::config {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template<typename T>
|
struct normalize_signature {
|
||||||
struct normalize_signature {
|
static const T& make(const T& ret) { return ret; }
|
||||||
static inline const T& make(const T& ret) { return ret; }
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct normalize_signature<std::string> {
|
struct normalize_signature<std::string> {
|
||||||
static inline std::string make(const std::string& data) {
|
static std::string make(const std::string& data) {
|
||||||
std::string ret = data;
|
std::string ret = data;
|
||||||
std::transform(ret.begin(), ret.end(),
|
std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
|
||||||
ret.begin(), ::tolower);
|
return ret;
|
||||||
return ret;
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Sign>
|
template<typename Sign>
|
||||||
struct signed_group : public group {
|
struct signed_group : public group {
|
||||||
|
@ -33,416 +33,402 @@
|
|||||||
namespace logid::config {
|
namespace logid::config {
|
||||||
void logError(const libconfig::Setting& setting, std::exception& e);
|
void logError(const libconfig::Setting& setting, std::exception& e);
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template<typename T>
|
struct config_io {
|
||||||
struct config_io {
|
static_assert(std::is_base_of<group, T>::value);
|
||||||
static_assert(std::is_base_of<group, T>::value);
|
|
||||||
|
|
||||||
static inline T get(const libconfig::Setting& parent,
|
static T get(const libconfig::Setting& parent,
|
||||||
const std::string& name) {
|
const std::string& name) {
|
||||||
T t{};
|
T t{};
|
||||||
t._load(parent.lookup(name));
|
t._load(parent.lookup(name));
|
||||||
return t;
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static T get(const libconfig::Setting& setting) {
|
||||||
|
T t{};
|
||||||
|
t._load(setting);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const T& t) {
|
||||||
|
if (!parent.exists(name)) {
|
||||||
|
parent.add(name, libconfig::Setting::TypeGroup);
|
||||||
|
} else if (parent.lookup(name).getType()
|
||||||
|
!= libconfig::Setting::TypeGroup) {
|
||||||
|
parent.remove(name);
|
||||||
|
parent.add(name, libconfig::Setting::TypeGroup);
|
||||||
}
|
}
|
||||||
|
t._save(parent.lookup(name));
|
||||||
|
}
|
||||||
|
|
||||||
static inline T get(const libconfig::Setting& setting) {
|
static void set(libconfig::Setting& setting, const T& t) {
|
||||||
T t{};
|
t._save(setting);
|
||||||
t._load(setting);
|
}
|
||||||
return t;
|
|
||||||
|
static void append(libconfig::Setting& list, const T& t) {
|
||||||
|
auto& x = list.add(libconfig::Setting::TypeGroup);
|
||||||
|
set(x, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct config_io<ipcgull::property<T>> : public config_io<T> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, libconfig::Setting::Type TypeEnum>
|
||||||
|
struct primitive_io {
|
||||||
|
static T get(const libconfig::Setting& parent,
|
||||||
|
const std::string& name) {
|
||||||
|
return parent.lookup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static T get(const libconfig::Setting& setting) {
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const T& t) {
|
||||||
|
if (!parent.exists(name)) {
|
||||||
|
parent.add(name, TypeEnum);
|
||||||
|
} else if (parent.lookup(name).getType() != TypeEnum) {
|
||||||
|
parent.remove(name);
|
||||||
|
parent.add(name, TypeEnum);
|
||||||
}
|
}
|
||||||
|
set(parent.lookup(name), t);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
static void set(libconfig::Setting& setting, const T& t) {
|
||||||
const std::string& name,
|
setting = t;
|
||||||
const T& t) {
|
}
|
||||||
if (!parent.exists(name)) {
|
|
||||||
parent.add(name, libconfig::Setting::TypeGroup);
|
static void append(libconfig::Setting& list, const T& t) {
|
||||||
} else if (parent.lookup(name).getType()
|
auto& x = list.add(TypeEnum);
|
||||||
!= libconfig::Setting::TypeGroup) {
|
set(x, t);
|
||||||
parent.remove(name);
|
}
|
||||||
parent.add(name, libconfig::Setting::TypeGroup);
|
};
|
||||||
}
|
|
||||||
t._save(parent.lookup(name));
|
template<typename T, typename O, libconfig::Setting::Type TypeEnum>
|
||||||
|
struct reinterpret_io {
|
||||||
|
static T get(const libconfig::Setting& parent,
|
||||||
|
const std::string& name) {
|
||||||
|
return static_cast<T>(primitive_io<O, TypeEnum>::get(parent, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static T get(const libconfig::Setting& setting) {
|
||||||
|
return static_cast<T>(primitive_io<O, TypeEnum>::get(setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const T& t) {
|
||||||
|
primitive_io<O, TypeEnum>::set(parent, name,
|
||||||
|
static_cast<O>(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& setting, const T& t) {
|
||||||
|
primitive_io<O, TypeEnum>::set(setting,
|
||||||
|
static_cast<O>(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]]
|
||||||
|
static void append(libconfig::Setting& list, const T& t) {
|
||||||
|
primitive_io<O, TypeEnum>::append(list,
|
||||||
|
static_cast<O>(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct config_io<bool> : public primitive_io<bool,
|
||||||
|
libconfig::Setting::TypeBoolean> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<int8_t> : public reinterpret_io<int8_t, int,
|
||||||
|
libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<uint8_t> : public reinterpret_io<uint8_t, int,
|
||||||
|
libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<short> : public reinterpret_io<short, int,
|
||||||
|
libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<unsigned short> : public reinterpret_io<unsigned short,
|
||||||
|
int, libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<int> : public primitive_io<int,
|
||||||
|
libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<unsigned int> : public reinterpret_io<unsigned int,
|
||||||
|
int, libconfig::Setting::TypeInt> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<long> : public reinterpret_io<long, long long,
|
||||||
|
libconfig::Setting::TypeInt64> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<unsigned long> : public reinterpret_io<unsigned long,
|
||||||
|
long long, libconfig::Setting::TypeInt64> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<long long> : public primitive_io<long long,
|
||||||
|
libconfig::Setting::TypeInt64> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<unsigned long long> :
|
||||||
|
public reinterpret_io<unsigned long long, long long,
|
||||||
|
libconfig::Setting::TypeInt64> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<float> : public primitive_io<float,
|
||||||
|
libconfig::Setting::TypeFloat> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<double> : public primitive_io<double,
|
||||||
|
libconfig::Setting::TypeFloat> {
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct config_io<std::string> : public primitive_io<std::string,
|
||||||
|
libconfig::Setting::TypeString> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
struct config_io<std::variant<T...>> {
|
||||||
|
private:
|
||||||
|
template<typename Singleton>
|
||||||
|
static std::variant<T...> try_each(const libconfig::Setting& setting) {
|
||||||
|
return config_io<Singleton>::get(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename First, typename Next, typename... Rest>
|
||||||
|
static std::variant<T...> try_each(const libconfig::Setting& setting) {
|
||||||
|
try {
|
||||||
|
return config_io<First>::get(setting);
|
||||||
|
} catch (libconfig::SettingException& e) {
|
||||||
|
return try_each<Next, Rest...>(setting);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting, const T& t) {
|
public:
|
||||||
t._save(setting);
|
static std::variant<T...> get(const libconfig::Setting& setting) {
|
||||||
}
|
return try_each<T...>(setting);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void append(libconfig::Setting& list, const T& t) {
|
static std::variant<T...> get(const libconfig::Setting& parent,
|
||||||
auto& x = list.add(libconfig::Setting::TypeGroup);
|
const std::string& name) {
|
||||||
set(x, t);
|
return get(parent.lookup(name));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
static void set(libconfig::Setting& setting,
|
||||||
struct config_io<ipcgull::property<T>> : public config_io<T> {
|
const std::variant<T...>& t) {
|
||||||
};
|
std::visit([&setting](auto&& arg) {
|
||||||
|
config::set(setting, arg);
|
||||||
|
}, t);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, libconfig::Setting::Type TypeEnum>
|
static void set(libconfig::Setting& parent,
|
||||||
struct primitive_io {
|
const std::string& name,
|
||||||
static inline T get(const libconfig::Setting& parent,
|
const std::variant<T...>& t) {
|
||||||
const std::string& name) {
|
std::visit([&parent, &name](auto&& arg) {
|
||||||
return parent.lookup(name);
|
config::set(parent, name, arg);
|
||||||
}
|
}, t);
|
||||||
|
}
|
||||||
|
|
||||||
static inline T get(const libconfig::Setting& setting) {
|
[[maybe_unused]]
|
||||||
return setting;
|
static void append(libconfig::Setting& list, const std::variant<T...>& t) {
|
||||||
}
|
std::visit([&list](auto&& arg) {
|
||||||
|
config::append(list, arg);
|
||||||
|
}, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
template<typename T>
|
||||||
const std::string& name,
|
struct config_io<std::list<T>> {
|
||||||
const T& t) {
|
static std::list<T> get(const libconfig::Setting& setting) {
|
||||||
if (!parent.exists(name)) {
|
const auto size = setting.getLength();
|
||||||
parent.add(name, TypeEnum);
|
std::list<T> t{};
|
||||||
} else if (parent.lookup(name).getType() != TypeEnum) {
|
for (int i = 0; i < size; ++i) {
|
||||||
parent.remove(name);
|
|
||||||
parent.add(name, TypeEnum);
|
|
||||||
}
|
|
||||||
set(parent.lookup(name), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting, const T& t) {
|
|
||||||
setting = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void append(libconfig::Setting& list, const T& t) {
|
|
||||||
auto& x = list.add(TypeEnum);
|
|
||||||
set(x, t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename O, libconfig::Setting::Type TypeEnum>
|
|
||||||
struct reinterpret_io {
|
|
||||||
static inline T get(const libconfig::Setting& parent,
|
|
||||||
const std::string& name) {
|
|
||||||
return static_cast<T>(primitive_io<O, TypeEnum>::get(parent, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline T get(const libconfig::Setting& setting) {
|
|
||||||
return static_cast<T>(primitive_io<O, TypeEnum>::get(setting));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
|
||||||
const std::string& name,
|
|
||||||
const T& t) {
|
|
||||||
primitive_io<O, TypeEnum>::set(parent, name,
|
|
||||||
static_cast<O>(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting, const T& t) {
|
|
||||||
primitive_io<O, TypeEnum>::set(setting,
|
|
||||||
static_cast<O>(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static inline void append(libconfig::Setting& list, const T& t) {
|
|
||||||
primitive_io<O, TypeEnum>::append(list,
|
|
||||||
static_cast<O>(t));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct config_io<bool> : public primitive_io<bool,
|
|
||||||
libconfig::Setting::TypeBoolean> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<int8_t> : public reinterpret_io<int8_t, int,
|
|
||||||
libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<uint8_t> : public reinterpret_io<uint8_t, int,
|
|
||||||
libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<short> : public reinterpret_io<short, int,
|
|
||||||
libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<unsigned short> : public reinterpret_io<unsigned short,
|
|
||||||
int, libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<int> : public primitive_io<int,
|
|
||||||
libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<unsigned int> : public reinterpret_io<unsigned int,
|
|
||||||
int, libconfig::Setting::TypeInt> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<long> : public reinterpret_io<long, long long,
|
|
||||||
libconfig::Setting::TypeInt64> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<unsigned long> : public reinterpret_io<unsigned long,
|
|
||||||
long long, libconfig::Setting::TypeInt64> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<long long> : public primitive_io<long long,
|
|
||||||
libconfig::Setting::TypeInt64> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<unsigned long long> :
|
|
||||||
public reinterpret_io<unsigned long long, long long,
|
|
||||||
libconfig::Setting::TypeInt64> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<float> : public primitive_io<float,
|
|
||||||
libconfig::Setting::TypeFloat> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<double> : public primitive_io<double,
|
|
||||||
libconfig::Setting::TypeFloat> {
|
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct config_io<std::string> : public primitive_io<std::string,
|
|
||||||
libconfig::Setting::TypeString> {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
struct config_io<std::variant<T...>> {
|
|
||||||
private:
|
|
||||||
template<typename Singleton>
|
|
||||||
static inline std::variant<T...> try_each(
|
|
||||||
const libconfig::Setting& setting) {
|
|
||||||
return config_io<Singleton>::get(setting);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename First, typename Next, typename... Rest>
|
|
||||||
static inline std::variant<T...> try_each(
|
|
||||||
const libconfig::Setting& setting) {
|
|
||||||
try {
|
try {
|
||||||
return config_io<First>::get(setting);
|
t.emplace_back(config_io<T>::get(setting[i]));
|
||||||
|
} catch (libconfig::SettingException& e) {}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::list<T> get(const libconfig::Setting& parent, const std::string& name) {
|
||||||
|
return get(parent.lookup(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& setting, const std::list<T>& t) {
|
||||||
|
while (setting.getLength() != 0)
|
||||||
|
setting.remove((int) 0);
|
||||||
|
for (auto& x: t) {
|
||||||
|
config_io<T>::append(setting, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const std::list<T>& t) {
|
||||||
|
if (!parent.exists(name)) {
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
} else if (!parent.lookup(name).isList()) {
|
||||||
|
parent.remove(name);
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
}
|
||||||
|
set(parent.lookup(name), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]]
|
||||||
|
static void append(libconfig::Setting& list, const std::list<T>& t) {
|
||||||
|
auto& s = list.add(libconfig::Setting::TypeList);
|
||||||
|
set(s, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct config_io<std::set<T>> {
|
||||||
|
static std::set<T> get(const libconfig::Setting& setting) {
|
||||||
|
const auto size = setting.getLength();
|
||||||
|
std::set<T> t;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
try {
|
||||||
|
t.emplace(config_io<T>::get(setting[i]));
|
||||||
|
} catch (libconfig::SettingException& e) {}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::set<T> get(const libconfig::Setting& parent, const std::string& name) {
|
||||||
|
return get(parent.lookup(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& setting, const std::set<T>& t) {
|
||||||
|
while (setting.getLength() != 0)
|
||||||
|
setting.remove((int) 0);
|
||||||
|
for (auto& x: t) {
|
||||||
|
auto& s = setting.add(libconfig::Setting::TypeGroup);
|
||||||
|
config_io<T>::set(s, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const std::set<T>& t) {
|
||||||
|
if (!parent.exists(name)) {
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
} else if (!parent.lookup(name).isArray()) {
|
||||||
|
parent.remove(name);
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
}
|
||||||
|
set(parent.lookup(name), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]]
|
||||||
|
static void append(libconfig::Setting& list,
|
||||||
|
const std::set<T>& t) {
|
||||||
|
auto& s = list.add(libconfig::Setting::TypeList);
|
||||||
|
set(s, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename K, typename V, typename KeyName,
|
||||||
|
typename Cmp, typename Alloc>
|
||||||
|
struct config_io<map<K, V, KeyName, Cmp, Alloc>> {
|
||||||
|
static map<K, V, KeyName, Cmp, Alloc> get(const libconfig::Setting& setting) {
|
||||||
|
const auto size = setting.getLength();
|
||||||
|
map<K, V, KeyName, Cmp, Alloc> t;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
auto& s = setting[i];
|
||||||
|
try {
|
||||||
|
t.emplace(config_io<K>::get(s.lookup(KeyName::value)),
|
||||||
|
config_io<V>::get(s));
|
||||||
|
} catch (libconfig::SettingException& e) {}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static map<K, V, KeyName, Cmp, Alloc> get(
|
||||||
|
const libconfig::Setting& parent, const std::string& name) {
|
||||||
|
return get(parent.lookup(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& setting,
|
||||||
|
const map<K, V, KeyName, Cmp, Alloc>& t) {
|
||||||
|
while (setting.getLength() != 0)
|
||||||
|
setting.remove((int) 0);
|
||||||
|
for (auto& x: t) {
|
||||||
|
auto& s = setting.add(libconfig::Setting::TypeGroup);
|
||||||
|
config_io<V>::set(s, x.second);
|
||||||
|
config_io<K>::set(s, KeyName::value, x.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set(libconfig::Setting& parent,
|
||||||
|
const std::string& name,
|
||||||
|
const map<K, V, KeyName, Cmp, Alloc>& t) {
|
||||||
|
if (!parent.exists(name)) {
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
} else if (!parent.lookup(name).isArray()) {
|
||||||
|
parent.remove(name);
|
||||||
|
parent.add(name, libconfig::Setting::TypeList);
|
||||||
|
}
|
||||||
|
set(parent.lookup(name), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]]
|
||||||
|
static void append(libconfig::Setting& list, const map<K, V, KeyName, Cmp, Alloc>& t) {
|
||||||
|
auto& s = list.add(libconfig::Setting::TypeList);
|
||||||
|
set(s, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct config_io<std::optional<T>> {
|
||||||
|
static std::optional<T> get(const libconfig::Setting& parent,
|
||||||
|
const std::string& name) {
|
||||||
|
if (parent.exists(name)) {
|
||||||
|
auto& setting = parent.lookup(name);
|
||||||
|
try {
|
||||||
|
return config_io<T>::get(setting);
|
||||||
} catch (libconfig::SettingException& e) {
|
} catch (libconfig::SettingException& e) {
|
||||||
return try_each<Next, Rest...>(setting);
|
logError(setting, e);
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
static void set(libconfig::Setting& parent,
|
||||||
static inline std::variant<T...> get(
|
const std::string& name,
|
||||||
const libconfig::Setting& setting) {
|
const std::optional<T>& t) {
|
||||||
return try_each<T...>(setting);
|
if (t.has_value())
|
||||||
}
|
config_io<T>::set(parent, name, t.value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static inline std::variant<T...> get(
|
// Optionals may not appear as part of a list or array
|
||||||
const libconfig::Setting& parent,
|
template<typename T, typename... Rest>
|
||||||
const std::string& name) {
|
struct config_io<std::variant<std::optional<T>, Rest...>> {
|
||||||
return get(parent.lookup(name));
|
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
||||||
}
|
};
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting,
|
template<typename T>
|
||||||
const std::variant<T...>& t) {
|
struct config_io<std::list<std::optional<T>>> {
|
||||||
std::visit([&setting](auto&& arg) {
|
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
||||||
config::set(setting, arg);
|
};
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
template<typename T>
|
||||||
const std::string& name,
|
struct config_io<std::optional<std::optional<T>>> {
|
||||||
const std::variant<T...>& t) {
|
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
||||||
std::visit([&parent, &name](auto&& arg) {
|
};
|
||||||
config::set(parent, name, arg);
|
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static inline void append(libconfig::Setting& list,
|
|
||||||
const std::variant<T...>& t) {
|
|
||||||
std::visit([&list](auto&& arg) {
|
|
||||||
config::append(list, arg);
|
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct config_io<std::list<T>> {
|
|
||||||
static inline std::list<T> get(const libconfig::Setting& setting) {
|
|
||||||
const auto size = setting.getLength();
|
|
||||||
std::list<T> t{};
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
try {
|
|
||||||
t.emplace_back(config_io<T>::get(setting[i]));
|
|
||||||
} catch (libconfig::SettingException& e) {}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline std::list<T> get(const libconfig::Setting& parent,
|
|
||||||
const std::string& name) {
|
|
||||||
return get(parent.lookup(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting,
|
|
||||||
const std::list<T>& t) {
|
|
||||||
while (setting.getLength() != 0)
|
|
||||||
setting.remove((int) 0);
|
|
||||||
for (auto& x: t) {
|
|
||||||
config_io<T>::append(setting, x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
|
||||||
const std::string& name,
|
|
||||||
const std::list<T>& t) {
|
|
||||||
if (!parent.exists(name)) {
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
} else if (!parent.lookup(name).isList()) {
|
|
||||||
parent.remove(name);
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
}
|
|
||||||
set(parent.lookup(name), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static inline void append(libconfig::Setting& list,
|
|
||||||
const std::list<T>& t) {
|
|
||||||
auto& s = list.add(libconfig::Setting::TypeList);
|
|
||||||
set(s, t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct config_io<std::set<T>> {
|
|
||||||
static inline std::set<T> get(const libconfig::Setting& setting) {
|
|
||||||
const auto size = setting.getLength();
|
|
||||||
std::set<T> t;
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
try {
|
|
||||||
t.emplace(config_io<T>::get(setting[i]));
|
|
||||||
} catch (libconfig::SettingException& e) {}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline std::set<T> get(const libconfig::Setting& parent,
|
|
||||||
const std::string& name) {
|
|
||||||
return get(parent.lookup(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting,
|
|
||||||
const std::set<T>& t) {
|
|
||||||
while (setting.getLength() != 0)
|
|
||||||
setting.remove((int) 0);
|
|
||||||
for (auto& x: t) {
|
|
||||||
auto& s = setting.add(libconfig::Setting::TypeGroup);
|
|
||||||
config_io<T>::set(s, x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
|
||||||
const std::string& name,
|
|
||||||
const std::set<T>& t) {
|
|
||||||
if (!parent.exists(name)) {
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
} else if (!parent.lookup(name).isArray()) {
|
|
||||||
parent.remove(name);
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
}
|
|
||||||
set(parent.lookup(name), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static inline void append(libconfig::Setting& list,
|
|
||||||
const std::set<T>& t) {
|
|
||||||
auto& s = list.add(libconfig::Setting::TypeList);
|
|
||||||
set(s, t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename K, typename V, typename KeyName,
|
|
||||||
typename Cmp, typename Alloc>
|
|
||||||
struct config_io<map<K, V, KeyName, Cmp, Alloc>> {
|
|
||||||
static inline map<K, V, KeyName, Cmp, Alloc> get(
|
|
||||||
const libconfig::Setting& setting) {
|
|
||||||
const auto size = setting.getLength();
|
|
||||||
map<K, V, KeyName, Cmp, Alloc> t;
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
auto& s = setting[i];
|
|
||||||
try {
|
|
||||||
t.emplace(config_io<K>::get(s.lookup(KeyName::value)),
|
|
||||||
config_io<V>::get(s));
|
|
||||||
} catch (libconfig::SettingException& e) {}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline map<K, V, KeyName, Cmp, Alloc> get(
|
|
||||||
const libconfig::Setting& parent, const std::string& name) {
|
|
||||||
return get(parent.lookup(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& setting,
|
|
||||||
const map<K, V, KeyName, Cmp, Alloc>& t) {
|
|
||||||
while (setting.getLength() != 0)
|
|
||||||
setting.remove((int) 0);
|
|
||||||
for (auto& x: t) {
|
|
||||||
auto& s = setting.add(libconfig::Setting::TypeGroup);
|
|
||||||
config_io<V>::set(s, x.second);
|
|
||||||
config_io<K>::set(s, KeyName::value, x.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
|
||||||
const std::string& name,
|
|
||||||
const map<K, V, KeyName, Cmp, Alloc>& t) {
|
|
||||||
if (!parent.exists(name)) {
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
} else if (!parent.lookup(name).isArray()) {
|
|
||||||
parent.remove(name);
|
|
||||||
parent.add(name, libconfig::Setting::TypeList);
|
|
||||||
}
|
|
||||||
set(parent.lookup(name), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
static inline void append(libconfig::Setting& list,
|
|
||||||
const map<K, V, KeyName, Cmp, Alloc>& t) {
|
|
||||||
auto& s = list.add(libconfig::Setting::TypeList);
|
|
||||||
set(s, t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct config_io<std::optional<T>> {
|
|
||||||
static inline std::optional<T> get(const libconfig::Setting& parent,
|
|
||||||
const std::string& name) {
|
|
||||||
if (parent.exists(name)) {
|
|
||||||
auto& setting = parent.lookup(name);
|
|
||||||
try {
|
|
||||||
return config_io<T>::get(setting);
|
|
||||||
} catch (libconfig::SettingException& e) {
|
|
||||||
logError(setting, e);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set(libconfig::Setting& parent,
|
|
||||||
const std::string& name,
|
|
||||||
const std::optional<T>& t) {
|
|
||||||
if (t.has_value())
|
|
||||||
config_io<T>::set(parent, name, t.value());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Optionals may not appear as part of a list or array
|
|
||||||
template<typename T, typename... Rest>
|
|
||||||
struct config_io<std::variant<std::optional<T>, Rest...>> {
|
|
||||||
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct config_io<std::list<std::optional<T>>> {
|
|
||||||
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct config_io<std::optional<std::optional<T>>> {
|
|
||||||
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(libconfig::Setting& parent,
|
void set(libconfig::Setting& parent,
|
||||||
|
@ -40,21 +40,19 @@ namespace logid::features {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
template<typename T>
|
||||||
template<typename T>
|
class _featureWrapper : public T {
|
||||||
class FeatureWrapper : public T {
|
friend class DeviceFeature;
|
||||||
friend class DeviceFeature;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
explicit FeatureWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
explicit _featureWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
return std::make_shared<FeatureWrapper>(std::forward<Args>(args)...);
|
return std::make_shared<_featureWrapper>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
class DeviceFeature {
|
class DeviceFeature {
|
||||||
std::weak_ptr<DeviceFeature> _self;
|
std::weak_ptr<DeviceFeature> _self;
|
||||||
@ -68,7 +66,9 @@ namespace logid::features {
|
|||||||
virtual ~DeviceFeature() = default;
|
virtual ~DeviceFeature() = default;
|
||||||
|
|
||||||
DeviceFeature(const DeviceFeature&) = delete;
|
DeviceFeature(const DeviceFeature&) = delete;
|
||||||
|
|
||||||
DeviceFeature(DeviceFeature&&) = delete;
|
DeviceFeature(DeviceFeature&&) = delete;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit DeviceFeature(Device* dev) : _device(dev) {}
|
explicit DeviceFeature(Device* dev) : _device(dev) {}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ namespace logid::features {
|
|||||||
public:
|
public:
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
static std::shared_ptr<T> make(Args... args) {
|
static std::shared_ptr<T> make(Args... args) {
|
||||||
auto feature = FeatureWrapper<T>::make(std::forward<Args>(args)...);
|
auto feature = _featureWrapper<T>::make(std::forward<Args>(args)...);
|
||||||
feature->_self = feature;
|
feature->_self = feature;
|
||||||
|
|
||||||
return feature;
|
return feature;
|
||||||
|
Loading…
Reference in New Issue
Block a user