...
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)
|
set(ASIBFM700_LIB asibfm700mount)
|
||||||
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
|
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)
|
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