// Copyright Toru Niina 2019. // Distributed under the MIT License. #ifndef TOML11_FIND_HPP #define TOML11_FIND_HPP #include "get.hpp" namespace toml { // ---------------------------------------------------------------------------- // these overloads do not require to set T. and returns value itself. template class M, template class V> basic_value const& find(const basic_value& v, const key& ky) { const auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return tab.at(ky); } template class M, template class V> basic_value& find(basic_value& v, const key& ky) { auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return tab.at(ky); } template class M, template class V> basic_value&& find(basic_value&& v, const key& ky) { auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return std::move(tab.at(ky)); } // ---------------------------------------------------------------------------- // find(value, key); template class M, template class V> decltype(::toml::get(std::declval const&>())) find(const basic_value& v, const key& ky) { const auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return ::toml::get(tab.at(ky)); } template class M, template class V> decltype(::toml::get(std::declval&>())) find(basic_value& v, const key& ky) { auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return ::toml::get(tab.at(ky)); } template class M, template class V> decltype(::toml::get(std::declval&&>())) find(basic_value&& v, const key& ky) { auto& tab = v.template cast(); if(tab.count(ky) == 0) { throw std::out_of_range(detail::format_underline(concat_to_string( "[error] key \"", ky, "\" not found"), { {std::addressof(detail::get_region(v)), "in this table"} })); } return ::toml::get(std::move(tab.at(ky))); } // -------------------------------------------------------------------------- // toml::find(toml::value, toml::key, Ts&& ... keys) template class M, template class V, typename ... Ts> const basic_value& find(const basic_value& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(v, ky), std::forward(keys)...); } template class M, template class V, typename ... Ts> basic_value& find(basic_value& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(v, ky), std::forward(keys)...); } template class M, template class V, typename ... Ts> basic_value&& find(basic_value&& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(std::move(v), ky), std::forward(keys)...); } template class M, template class V, typename ... Ts> decltype(::toml::get(std::declval&>())) find(const basic_value& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(v, ky), std::forward(keys)...); } template class M, template class V, typename ... Ts> decltype(::toml::get(std::declval&>())) find(basic_value& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(v, ky), std::forward(keys)...); } template class M, template class V, typename ... Ts> decltype(::toml::get(std::declval&&>())) find(basic_value&& v, const ::toml::key& ky, Ts&& ... keys) { return ::toml::find(::toml::find(std::move(v), ky), std::forward(keys)...); } // =========================================================================== // find_or(value, key, fallback) template class M, template class V> basic_value const& find_or(const basic_value& v, const key& ky, const basic_value& opt) { if(!v.is_table()) {return opt;} const auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return tab.at(ky); } template class M, template class V> basic_value& find_or(basic_value& v, const toml::key& ky, basic_value& opt) { if(!v.is_table()) {return opt;} auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return tab[ky]; } template class M, template class V> basic_value find_or(basic_value&& v, const toml::key& ky, basic_value&& opt) { if(!v.is_table()) {return opt;} auto tab = std::move(v).as_table(); if(tab.count(ky) == 0) {return opt;} return std::move(tab[ky]); } // --------------------------------------------------------------------------- // exact types (return type can be a reference) template class M, template class V> detail::enable_if_t< detail::is_exact_toml_type>::value, T> const& find_or(const basic_value& v, const key& ky, const T& opt) { if(!v.is_table()) {return opt;} const auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return get_or(tab.at(ky), opt); } template class M, template class V> detail::enable_if_t< detail::is_exact_toml_type>::value, T>& find_or(basic_value& v, const toml::key& ky, T& opt) { if(!v.is_table()) {return opt;} auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return get_or(tab[ky], opt); } template class M, template class V> detail::enable_if_t< detail::is_exact_toml_type>::value, T>&& find_or(basic_value&& v, const toml::key& ky, T&& opt) { if(!v.is_table()) {return opt;} auto tab = std::move(v).as_table(); if(tab.count(ky) == 0) {return opt;} return get_or(std::move(tab[ky]), std::forward(opt)); } // --------------------------------------------------------------------------- // std::string (return type can be a reference) template class M, template class V> detail::enable_if_t::value, std::string> const& find_or(const basic_value& v, const key& ky, const T& opt) { if(!v.is_table()) {return opt;} const auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return get_or(tab.at(ky), opt); } template class M, template class V> detail::enable_if_t::value, std::string>& find_or(basic_value& v, const toml::key& ky, T& opt) { if(!v.is_table()) {return opt;} auto& tab = v.as_table(); if(tab.count(ky) == 0) {return opt;} return get_or(tab.at(ky), opt); } template class M, template class V> detail::enable_if_t::value, std::string> find_or(basic_value&& v, const toml::key& ky, T&& opt) { if(!v.is_table()) {return std::forward(opt);} auto tab = std::move(v).as_table(); if(tab.count(ky) == 0) {return std::forward(opt);} return get_or(std::move(tab.at(ky)), std::forward(opt)); } // --------------------------------------------------------------------------- // string literal (deduced as std::string) template class M, template class V> detail::enable_if_t< detail::is_string_literal::type>::value, std::string> find_or(const basic_value& v, const toml::key& ky, T&& opt) { if(!v.is_table()) {return std::string(opt);} const auto& tab = v.as_table(); if(tab.count(ky) == 0) {return std::string(opt);} return get_or(tab.at(ky), std::forward(opt)); } // --------------------------------------------------------------------------- // others (require type conversion and return type cannot be lvalue reference) template class M, template class V> detail::enable_if_t::type>::type, basic_value>>, // T is not std::string detail::negation::type>::type>>, // T is not a string literal detail::negation::type>> >::value, typename std::remove_cv::type>::type> find_or(const basic_value& v, const toml::key& ky, T&& opt) { if(!v.is_table()) {return std::forward(opt);} const auto& tab = v.as_table(); if(tab.count(ky) == 0) {return std::forward(opt);} return get_or(tab.at(ky), std::forward(opt)); } // ============================================================================ // expect template class M, template class V> result expect(const basic_value& v) noexcept { try { return ok(get(v)); } catch(const std::exception& e) { return err(e.what()); } } template class M, template class V> result expect(const basic_value& v, const toml::key& k) noexcept { try { return ok(find(v, k)); } catch(const std::exception& e) { return err(e.what()); } } template detail::enable_if_t, detail::is_basic_value >::value, result> expect(const Table& t, const toml::key& k, std::string tablename = "unknown table") noexcept { try { return ok(find(t, k, std::move(tablename))); } catch(const std::exception& e) { return err(e.what()); } } } // toml #endif// TOML11_FIND_HPP