...
This commit is contained in:
parent
98c46c2b8c
commit
c5aa3dc495
@ -38,5 +38,6 @@ set(ASIBFM700_LIB_SRC asibfm700_common.h asibfm700_servocontroller.h asibfm700_s
|
||||
|
||||
set(ASIBFM700_LIB asibfm700mount)
|
||||
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
|
||||
asibfm700_mount.h asibfm700_mount.cpp)
|
||||
asibfm700_mount.h asibfm700_mount.cpp
|
||||
asibfm700_configfile.h)
|
||||
target_link_libraries(${ASIBFM700_LIB} PRIVATE mcc)
|
||||
|
||||
121
asibfm700/asibfm700_configfile.h
Normal file
121
asibfm700/asibfm700_configfile.h
Normal file
@ -0,0 +1,121 @@
|
||||
#pragma once
|
||||
|
||||
/**/
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <mcc_utils.h>
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
|
||||
// configuration record:
|
||||
// keyword
|
||||
// value
|
||||
// conversion function (deserializer)
|
||||
template <typename T>
|
||||
concept config_record_c = requires(T t) {
|
||||
requires std::same_as<decltype(t.key), std::string_view>; // keyword
|
||||
t.value; // value
|
||||
// method to convert from string to value
|
||||
{ t.cnv_func(std::declval<std::string_view>(), std::declval<decltype(t.value)&>()) } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
|
||||
// table of records (std::tuple<config_record_c...>)
|
||||
//
|
||||
template <typename T>
|
||||
concept config_table_c = requires(T t) { []<config_record_c... Ts>(std::tuple<Ts...>) {}(t); };
|
||||
|
||||
|
||||
template <config_table_c TabT>
|
||||
class ConfigTable
|
||||
{
|
||||
protected:
|
||||
TabT _cfgTable;
|
||||
|
||||
std::array<size_t, std::tuple_size_v<TabT>> _keyHashes{};
|
||||
|
||||
bool keyExists(size_t hash)
|
||||
{
|
||||
for (auto& h : _keyHashes) {
|
||||
if (h == hash) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr char COMMENT_SYMBOL = '#';
|
||||
static constexpr char KEY_VALUE_DELIM = '=';
|
||||
static constexpr char VALUE_VALUE_DELIM = ',';
|
||||
|
||||
ConfigTable(const TabT& init_cfg) : _cfgTable(init_cfg)
|
||||
{
|
||||
_keyHashes = [this]<size_t... Is>(std::index_sequence<Is...>) {
|
||||
return std::array{mcc::utils::FNV1aHash(std::get<Is>(_cfgTable).key)...};
|
||||
}(std::make_index_sequence<std::tuple_size_v<TabT>>());
|
||||
}
|
||||
|
||||
virtual ~ConfigTable() = default;
|
||||
|
||||
|
||||
std::error_code parse(std::ranges::contiguous_range auto const& buffer)
|
||||
requires std::same_as<std::remove_cvref_t<std::ranges::range_value_t<decltype(buffer)>>, char>
|
||||
{
|
||||
std::string_view sv, curr_buffer{buffer.begin(), buffer.end()};
|
||||
|
||||
do {
|
||||
auto r = std::ranges::find(curr_buffer, '\n');
|
||||
|
||||
sv = mcc::utils::trimSpaces(std::string_view(curr_buffer.begin(), r), mcc::utils::TrimType::TRIM_LEFT);
|
||||
|
||||
if (sv.size()) {
|
||||
if (sv[0] == COMMENT_SYMBOL) { // comment string
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = std::ranges::find(sv, KEY_VALUE_DELIM);
|
||||
if (it == sv.begin()) { // empty key! skip!
|
||||
continue;
|
||||
}
|
||||
|
||||
auto key = mcc::utils::trimSpaces(std::string_view{sv.begin(), it}, mcc::utils::TrimType::TRIM_RIGHT);
|
||||
if (!keyExists(mcc::utils::FNV1aHash(key))) {
|
||||
}
|
||||
|
||||
} // only spaces
|
||||
|
||||
curr_buffer = {++r, buffer.end()};
|
||||
} while (!curr_buffer.empty());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool value(mcc::traits::mcc_input_char_range auto const& key, T& val)
|
||||
{
|
||||
const auto* kptr = &key;
|
||||
const auto* vptr = &val;
|
||||
|
||||
return [kptr, vptr, this]<size_t... Is>(std::index_sequence<Is...>) {
|
||||
return ([&kptr, vptr, this]() {
|
||||
if constexpr (std::convertible_to<decltype(std::get<Is>(_cfgTable).value), T>) {
|
||||
if (keyExists(mcc::utils::FNV1aHash(*kptr))) {
|
||||
*vptr = std::get<Is>(_cfgTable).value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}() || ...);
|
||||
}(std::make_index_sequence<std::tuple_size_v<TabT>>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace asibfm700
|
||||
Loading…
x
Reference in New Issue
Block a user