From 9b43171b653279a15b0422d1c875dd4c6f75b86f Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Sat, 31 Aug 2019 14:48:38 +0900 Subject: [PATCH] refactor: split get.hpp to get/find.hpp --- toml.hpp | 1 + toml/find.hpp | 356 ++++++++++++++++++++++++++++++++++++++++++++++++++ toml/get.hpp | 346 ------------------------------------------------ 3 files changed, 357 insertions(+), 346 deletions(-) create mode 100644 toml/find.hpp diff --git a/toml.hpp b/toml.hpp index 2182df1..ce22269 100644 --- a/toml.hpp +++ b/toml.hpp @@ -37,5 +37,6 @@ #include "toml/literal.hpp" #include "toml/serializer.hpp" #include "toml/get.hpp" +#include "toml/find.hpp" #endif// TOML_FOR_MODERN_CPP diff --git a/toml/find.hpp b/toml/find.hpp new file mode 100644 index 0000000..6399e2c --- /dev/null +++ b/toml/find.hpp @@ -0,0 +1,356 @@ +// 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 diff --git a/toml/get.hpp b/toml/get.hpp index 07b4b27..0afd862 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -420,158 +420,6 @@ T get(const basic_value& v) return ::toml::from::from_toml(v); } -// ============================================================================ -// find and get - -// ---------------------------------------------------------------------------- -// 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)...); -} - // ============================================================================ // get_or(value, fallback) @@ -745,199 +593,5 @@ get_or(const basic_value& v, T&& opt) } } -// =========================================================================== -// 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_GET