82 lines
3.0 KiB
C++
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
|