feat: add find_or(table, key, fallback)

get_or(value, fallback) is still ok, but get_or(table, key, fallback)
is now deprecated.
This commit is contained in:
ToruNiina
2019-03-18 17:44:03 +09:00
parent aade704411
commit 7a0ecf977d
2 changed files with 322 additions and 23 deletions

View File

@@ -546,56 +546,237 @@ T get_or(const toml::value& v, T&& opt)
}
}
// ===========================================================================
// get_or(table, key, fallback)
//
// DEPRECATED: use find_or instead.
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
auto get_or(const toml::table& tab, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
{
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
auto get_or(toml::table& tab, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
{
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(tab[ky], std::forward<T>(opt));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
auto get_or(toml::table&& tab, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
{
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
auto get_or(const toml::value& v, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
{
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
if(!v.is_table()) {return opt;}
const auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
auto get_or(toml::value& v, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
{
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
if(!v.is_table()) {return opt;}
auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(tab[ky], std::forward<T>(opt));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
auto get_or(toml::value&& v, const toml::key& ky, T&& opt)
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
{
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
if(!v.is_table()) {return opt;}
auto tab = toml::get<toml::table>(std::move(v));
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
if(tab.count(ky) == 0) {return opt;}
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
}
// ===========================================================================
// find_or(value, key, fallback)
// ---------------------------------------------------------------------------
// exact types (return type can be a reference)
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T const& find_or(const toml::value& v, const toml::key& ky, const T& opt)
{
if(!v.is_table()) {return opt;}
const auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), opt);
}
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T& find_or(toml::value& v, const toml::key& ky, T& opt)
{
if(!v.is_table()) {return opt;}
auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return opt;}
return get_or(tab[ky], opt);
}
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T&& find_or(toml::value&& v, const toml::key& ky, T&& opt)
{
if(!v.is_table()) {return opt;}
auto tab = toml::get<toml::table>(std::move(v));
if(tab.count(ky) == 0) {return opt;}
return get_or(std::move(tab[ky]), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// std::string (return type can be a reference)
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string const& find_or(const toml::value& v, const toml::key& ky, const T& opt)
{
if(!v.is_table()) {return opt;}
const auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), opt);
}
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string& find_or(toml::value& v, const toml::key& ky, T& opt)
{
if(!v.is_table()) {return opt;}
auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return opt;}
return get_or(tab[ky], opt);
}
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string find_or(toml::value&& v, const toml::key& ky, T&& opt)
{
if(!v.is_table()) {return opt;}
auto tab = toml::get<toml::table>(std::move(v));
if(tab.count(ky) == 0) {return opt;}
return get_or(std::move(tab[ky]), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// string literal (deduced as std::string)
template<typename T, typename std::enable_if<
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
std::nullptr_t>::type = nullptr>
std::string find_or(const toml::value& v, const toml::key& ky, T&& opt)
{
if(!v.is_table()) {return opt;}
const auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return std::string(opt);}
return get_or(tab.at(ky), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// others (require type conversion and return type cannot be lvalue reference)
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>,
detail::negation<std::is_same<T, std::string>>,
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
>::value, std::nullptr_t>::type = nullptr>
T find_or(const toml::value& v, const toml::key& ky, T&& opt)
{
if(!v.is_table()) {return opt;}
const auto& tab = toml::get<toml::table>(v);
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), std::forward<T>(opt));
}
// ===========================================================================
// find_or(table, key, opt)
// ---------------------------------------------------------------------------
// exact types (return type can be a reference)
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T const& find_or(const toml::table& tab, const toml::key& ky, const T& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), opt);
}
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T& find_or(toml::table& tab, const toml::key& ky, T& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(tab[ky], opt);
}
template<typename T, typename std::enable_if<
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
T&& find_or(toml::table&& tab, const toml::key& ky, T&& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(std::move(tab[ky]), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// std::string (return type can be a reference)
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string const& find_or(const toml::table& tab, const toml::key& ky, const T& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), opt);
}
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string& find_or(toml::table& tab, const toml::key& ky, T& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(tab[ky], opt);
}
template<typename T, typename std::enable_if<
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
std::string find_or(toml::table&& tab, const toml::key& ky, T&& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(std::move(tab[ky]), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// string literal (deduced as std::string)
template<typename T, typename std::enable_if<
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
std::nullptr_t>::type = nullptr>
std::string find_or(const toml::table& tab, const toml::key& ky, T&& opt)
{
if(tab.count(ky) == 0) {return std::string(opt);}
return get_or(tab.at(ky), std::forward<T>(opt));
}
// ---------------------------------------------------------------------------
// others (require type conversion and return type cannot be lvalue reference)
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>,
detail::negation<std::is_same<T, std::string>>,
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
>::value, std::nullptr_t>::type = nullptr>
T find_or(const toml::table& tab, const toml::key& ky, T&& opt)
{
if(tab.count(ky) == 0) {return opt;}
return get_or(tab.at(ky), std::forward<T>(opt));
}
// ============================================================================
// expect