network-experiment/bmrshared/include/bmrshared/to_tuple.hpp

82 lines
3.0 KiB
C++

// GNU Lesser General Public License v3.0
// Copyright (c) 2023 Bart Beumer <bart@4beumer.nl>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License v3.0 as published by
// the Free Software Foundation.
//
#pragma once
#include "IDataSource.hpp"
#include "ToTupleException.hpp"
#include <array>
#include <cstddef>
#include <exception>
#include <string>
#include <tuple>
#include <utility>
namespace bmrshared
{
namespace detail
{
std::vector<std::string>
GetKeysMissing(const std::vector<std::string>& allKeys, const std::string* dataBegin, std::size_t arraySize);
std::vector<std::string>
GetKeysNotUsed(const std::vector<std::string>& allKeys, const std::string* dataBegin, std::size_t arraySize);
template<typename T>
T GetValueFromDataSource(const IDataSource& source,
std::string_view id,
std::vector<ToTupleException::ParamError>& outErrors)
{
T value;
try
{
source.Get(id, value);
}
catch (const std::exception&)
{
outErrors.push_back(ToTupleException::ParamError{std::string(id), "problem reading"});
}
return value;
}
template<typename... TParameters, std::size_t... IndexSeq>
std::tuple<TParameters...> to_tuple(const IDataSource& source,
const std::array<std::string, sizeof...(TParameters)>& names,
std::index_sequence<IndexSeq...>)
{
const auto allKeys = source.GetKeys();
const auto keysMissing = GetKeysMissing(allKeys, names.data(), sizeof...(TParameters));
const auto keysNotUsed = GetKeysNotUsed(allKeys, names.data(), sizeof...(TParameters));
// Constructing the tuple by expanding the parameter packs to retrieve each name for the specified type. in
// case of errors these are written to errorRecords
std::vector<ToTupleException::ParamError> errorRecords;
std::tuple<TParameters...> returnValue = {
GetValueFromDataSource<TParameters>(source, std::get<IndexSeq>(names), errorRecords)...};
if (!keysMissing.empty() || !keysNotUsed.empty() || !errorRecords.empty())
{
throw ToTupleException(keysMissing, keysNotUsed, errorRecords);
}
return returnValue;
}
} // namespace detail
template<typename... Types>
std::tuple<Types...> to_tuple(const IDataSource& source, const std::array<std::string, sizeof...(Types)>& names)
{
return detail::to_tuple<Types...>(source, names, std::make_index_sequence<sizeof...(Types)>());
}
template<typename... Types>
void to_tuple(const IDataSource& source,
const std::array<std::string, sizeof...(Types)>& names,
std::tuple<Types...>& outParameters)
{
outParameters = detail::to_tuple<Types...>(source, names, std::make_index_sequence<sizeof...(Types)>());
}
} // namespace bmrshared