feat: throw if multiple keys match to the key

This commit is contained in:
ToruNiina
2019-09-01 14:45:56 +09:00
parent 99e46813f4
commit 6d31cccc5b

View File

@@ -422,6 +422,39 @@ struct levenstein_matcher
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// toml::find_fuzzy<T>(v, "tablename", FuzzyMatcher); // toml::find_fuzzy<T>(v, "tablename", FuzzyMatcher);
namespace detail
{
template<typename Iterator, typename C,
template<typename ...> class M, template<typename ...> class V,
typename FuzzyMatcher>
Iterator find_unique(
Iterator iter, const Iterator end, const basic_value<C, M, V>& v,
const toml::key& k, const FuzzyMatcher& match)
{
Iterator found = end;
for(; iter != end; ++iter)
{
if(match(iter->first, k))
{
if(found != end)
{
throw std::out_of_range(detail::format_underline(
concat_to_string("[error] key \"", k, "\" not found."),
{
{std::addressof(detail::get_region(v)),"in this table"},
{std::addressof(detail::get_region(found->second)),
"did you mean this here?"},
{std::addressof(detail::get_region(iter->second)),
"or this?"}
}));
}
found = iter;
}
}
return found;
}
} // detail
template<typename T, typename C, template<typename T, typename C,
template<typename ...> class M, template<typename ...> class V, template<typename ...> class M, template<typename ...> class V,
typename FuzzyMatcher = levenstein_matcher> typename FuzzyMatcher = levenstein_matcher>
@@ -435,13 +468,11 @@ auto find_fuzzy(const basic_value<C, M, V>& v, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
const auto& tab = v.as_table(); const auto& t = v.as_table();
for(const auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return get<T>(found->second);
{
return get<T>(kv.second);
}
} }
throw; throw;
} }
@@ -459,13 +490,11 @@ auto find_fuzzy(basic_value<C, M, V>& v, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
auto& tab = v.as_table(); auto& t = v.as_table();
for(auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return get<T>(found->second);
{
return get<T>(kv.second);
}
} }
throw; throw;
} }
@@ -484,13 +513,11 @@ auto find_fuzzy(basic_value<C, M, V>&& v_, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
auto& tab = v.as_table(); // because v is used here auto& t = v.as_table(); // because v is used here
for(auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return get<T>(std::move(found->second));
{
return get<T>(std::move(kv.second));
}
} }
throw; throw;
} }
@@ -513,13 +540,11 @@ find_fuzzy(const basic_value<C, M, V>& v, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
const auto& tab = v.as_table(); const auto& t = v.as_table();
for(const auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return found->second;
{
return kv.second;
}
} }
throw; throw;
} }
@@ -537,13 +562,11 @@ find_fuzzy(basic_value<C, M, V>& v, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
auto& tab = v.as_table(); auto& t = v.as_table();
for(auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return found->second;
{
return kv.second;
}
} }
throw; throw;
} }
@@ -562,13 +585,11 @@ find_fuzzy(basic_value<C, M, V>&& v_, const key& ky,
} }
catch(const std::out_of_range& oor) catch(const std::out_of_range& oor)
{ {
auto& tab = v.as_table(); auto& t = v.as_table();
for(auto& kv : tab) const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
if(found != t.end())
{ {
if(match(kv.first, ky)) return std::move(found->second);
{
return std::move(kv.second);
}
} }
throw; throw;
} }