mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-13 12:52:42 +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 {
|
||||
struct DeviceConnectionEvent;
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
class DeviceWrapper : public T {
|
||||
friend class Device;
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit DeviceWrapper(Args... args) : T(std::forward<Args>(args)...) { }
|
||||
template<typename T>
|
||||
class _deviceWrapper : public T {
|
||||
friend class Device;
|
||||
|
||||
template <typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<DeviceWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
public:
|
||||
template<typename... 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 {
|
||||
template <typename T>
|
||||
friend class DeviceWrapper;
|
||||
template<typename T>
|
||||
friend
|
||||
class _deviceWrapper;
|
||||
|
||||
public:
|
||||
struct EventHandler {
|
||||
std::function<bool(Report&)> condition;
|
||||
@ -102,7 +103,9 @@ namespace logid::backend::hidpp {
|
||||
[[nodiscard]] const std::shared_ptr<raw::RawDevice>& rawDevice() const;
|
||||
|
||||
Device(const Device&) = delete;
|
||||
|
||||
Device(Device&&) = delete;
|
||||
|
||||
virtual ~Device() = default;
|
||||
|
||||
protected:
|
||||
@ -161,16 +164,16 @@ namespace logid::backend::hidpp {
|
||||
std::weak_ptr<Device> _self;
|
||||
|
||||
protected:
|
||||
template <typename T, typename... Args>
|
||||
template<typename T, typename... 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->_setupReportsAndInit();
|
||||
return device;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Device> make(Args... args) {
|
||||
return makeDerived<Device>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
@ -26,20 +26,19 @@
|
||||
|
||||
namespace logid::backend::hidpp10 {
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
class ReceiverMonitorWrapper : public T {
|
||||
friend class ReceiverMonitor;
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit ReceiverMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) { }
|
||||
template<typename T>
|
||||
class _receiverMonitorWrapper : public T {
|
||||
friend class ReceiverMonitor;
|
||||
|
||||
template <typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<ReceiverMonitorWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
public:
|
||||
template<typename... 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 ready_backoff = 250;
|
||||
@ -50,7 +49,9 @@ namespace logid::backend::hidpp10 {
|
||||
void enumerate();
|
||||
|
||||
ReceiverMonitor(const ReceiverMonitor&) = delete;
|
||||
|
||||
ReceiverMonitor(ReceiverMonitor&&) = delete;
|
||||
|
||||
protected:
|
||||
ReceiverMonitor(const std::string& path,
|
||||
const std::shared_ptr<raw::DeviceMonitor>& monitor,
|
||||
@ -101,9 +102,9 @@ namespace logid::backend::hidpp10 {
|
||||
std::weak_ptr<ReceiverMonitor> _self;
|
||||
|
||||
public:
|
||||
template <typename T, typename... Args>
|
||||
template<typename T, typename... 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->_ready();
|
||||
return receiver_monitor;
|
||||
|
@ -36,21 +36,19 @@ namespace logid::backend::raw {
|
||||
static constexpr int max_tries = 5;
|
||||
static constexpr int ready_backoff = 500;
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
class DeviceMonitorWrapper : public T {
|
||||
friend class Device;
|
||||
template<typename T>
|
||||
class _deviceMonitorWrapper : public T {
|
||||
friend class Device;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
explicit DeviceMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||
public:
|
||||
template<typename... Args>
|
||||
explicit _deviceMonitorWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<DeviceMonitorWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<_deviceMonitorWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
class DeviceMonitor {
|
||||
public:
|
||||
@ -62,7 +60,7 @@ namespace logid::backend::raw {
|
||||
|
||||
template<typename T, typename... 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->ready();
|
||||
|
||||
@ -79,7 +77,7 @@ namespace logid::backend::raw {
|
||||
|
||||
virtual void removeDevice(std::string device) = 0;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
[[nodiscard]] std::weak_ptr<T> self() const {
|
||||
return std::dynamic_pointer_cast<T>(_self.lock());
|
||||
}
|
||||
|
@ -38,55 +38,45 @@ namespace logid::config {
|
||||
template<typename T>
|
||||
void append(libconfig::Setting& list, const T& t);
|
||||
|
||||
namespace {
|
||||
template<typename T, typename... M>
|
||||
struct group_io {
|
||||
};
|
||||
template<typename T, typename... M>
|
||||
struct group_io {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct group_io<T> {
|
||||
static inline void get(
|
||||
[[maybe_unused]] const libconfig::Setting& s,
|
||||
[[maybe_unused]] T* t,
|
||||
[[maybe_unused]] const std::vector<std::string>& names,
|
||||
[[maybe_unused]] const std::size_t index) {}
|
||||
template<typename T>
|
||||
struct group_io<T> {
|
||||
static void get(const libconfig::Setting&, T*,
|
||||
const std::vector<std::string>&, const std::size_t) {}
|
||||
|
||||
static inline void set(
|
||||
[[maybe_unused]] libconfig::Setting& s,
|
||||
[[maybe_unused]] const T* t,
|
||||
[[maybe_unused]] const std::vector<std::string>& names,
|
||||
[[maybe_unused]] const std::size_t index) {}
|
||||
};
|
||||
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 inline 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);
|
||||
}
|
||||
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 inline 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...);
|
||||
}
|
||||
};
|
||||
}
|
||||
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;
|
||||
@ -149,22 +139,19 @@ namespace logid::config {
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
struct normalize_signature {
|
||||
static inline const T& make(const T& ret) { return ret; }
|
||||
};
|
||||
template<typename T>
|
||||
struct normalize_signature {
|
||||
static const T& make(const T& ret) { return ret; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct normalize_signature<std::string> {
|
||||
static inline std::string make(const std::string& data) {
|
||||
std::string ret = data;
|
||||
std::transform(ret.begin(), ret.end(),
|
||||
ret.begin(), ::tolower);
|
||||
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 {
|
||||
|
@ -33,416 +33,402 @@
|
||||
namespace logid::config {
|
||||
void logError(const libconfig::Setting& setting, std::exception& e);
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
struct config_io {
|
||||
static_assert(std::is_base_of<group, T>::value);
|
||||
template<typename T>
|
||||
struct config_io {
|
||||
static_assert(std::is_base_of<group, T>::value);
|
||||
|
||||
static inline T get(const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
T t{};
|
||||
t._load(parent.lookup(name));
|
||||
return t;
|
||||
static T get(const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
T t{};
|
||||
t._load(parent.lookup(name));
|
||||
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) {
|
||||
T t{};
|
||||
t._load(setting);
|
||||
return t;
|
||||
static void set(libconfig::Setting& setting, const T& t) {
|
||||
t._save(setting);
|
||||
}
|
||||
|
||||
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,
|
||||
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 void set(libconfig::Setting& setting, const T& t) {
|
||||
setting = t;
|
||||
}
|
||||
|
||||
static 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 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) {
|
||||
t._save(setting);
|
||||
}
|
||||
public:
|
||||
static std::variant<T...> get(const libconfig::Setting& setting) {
|
||||
return try_each<T...>(setting);
|
||||
}
|
||||
|
||||
static inline void append(libconfig::Setting& list, const T& t) {
|
||||
auto& x = list.add(libconfig::Setting::TypeGroup);
|
||||
set(x, t);
|
||||
}
|
||||
};
|
||||
static std::variant<T...> get(const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
return get(parent.lookup(name));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct config_io<ipcgull::property<T>> : public config_io<T> {
|
||||
};
|
||||
static void set(libconfig::Setting& setting,
|
||||
const std::variant<T...>& t) {
|
||||
std::visit([&setting](auto&& arg) {
|
||||
config::set(setting, arg);
|
||||
}, t);
|
||||
}
|
||||
|
||||
template<typename T, libconfig::Setting::Type TypeEnum>
|
||||
struct primitive_io {
|
||||
static inline T get(const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
return parent.lookup(name);
|
||||
}
|
||||
static void set(libconfig::Setting& parent,
|
||||
const std::string& name,
|
||||
const std::variant<T...>& t) {
|
||||
std::visit([&parent, &name](auto&& arg) {
|
||||
config::set(parent, name, arg);
|
||||
}, t);
|
||||
}
|
||||
|
||||
static inline T get(const libconfig::Setting& setting) {
|
||||
return setting;
|
||||
}
|
||||
[[maybe_unused]]
|
||||
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,
|
||||
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& 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) {
|
||||
template<typename T>
|
||||
struct config_io<std::list<T>> {
|
||||
static 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 {
|
||||
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) {
|
||||
return try_each<Next, Rest...>(setting);
|
||||
logError(setting, e);
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static inline std::variant<T...> get(
|
||||
const libconfig::Setting& setting) {
|
||||
return try_each<T...>(setting);
|
||||
}
|
||||
static 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());
|
||||
}
|
||||
};
|
||||
|
||||
static inline std::variant<T...> get(
|
||||
const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
return get(parent.lookup(name));
|
||||
}
|
||||
// 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");
|
||||
};
|
||||
|
||||
static inline void set(libconfig::Setting& setting,
|
||||
const std::variant<T...>& t) {
|
||||
std::visit([&setting](auto&& arg) {
|
||||
config::set(setting, arg);
|
||||
}, t);
|
||||
}
|
||||
template<typename T>
|
||||
struct config_io<std::list<std::optional<T>>> {
|
||||
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
||||
};
|
||||
|
||||
static inline void set(libconfig::Setting& parent,
|
||||
const std::string& name,
|
||||
const std::variant<T...>& t) {
|
||||
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>
|
||||
struct config_io<std::optional<std::optional<T>>> {
|
||||
static_assert(!sizeof(std::optional<T>), "Invalid type");
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void set(libconfig::Setting& parent,
|
||||
|
@ -40,21 +40,19 @@ namespace logid::features {
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
class FeatureWrapper : public T {
|
||||
friend class DeviceFeature;
|
||||
template<typename T>
|
||||
class _featureWrapper : public T {
|
||||
friend class DeviceFeature;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
explicit FeatureWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||
public:
|
||||
template<typename... Args>
|
||||
explicit _featureWrapper(Args... args) : T(std::forward<Args>(args)...) {}
|
||||
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<FeatureWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<T> make(Args... args) {
|
||||
return std::make_shared<_featureWrapper>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
class DeviceFeature {
|
||||
std::weak_ptr<DeviceFeature> _self;
|
||||
@ -68,7 +66,9 @@ namespace logid::features {
|
||||
virtual ~DeviceFeature() = default;
|
||||
|
||||
DeviceFeature(const DeviceFeature&) = delete;
|
||||
|
||||
DeviceFeature(DeviceFeature&&) = delete;
|
||||
|
||||
protected:
|
||||
explicit DeviceFeature(Device* dev) : _device(dev) {}
|
||||
|
||||
@ -82,7 +82,7 @@ namespace logid::features {
|
||||
public:
|
||||
template<typename T, typename... 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;
|
||||
|
||||
return feature;
|
||||
|
Loading…
Reference in New Issue
Block a user