diff --git a/include/toml11/value.hpp b/include/toml11/value.hpp index fe1720d..c1434ec 100644 --- a/include/toml11/value.hpp +++ b/include/toml11/value.hpp @@ -50,6 +50,9 @@ error_info make_type_error(const basic_value&, const std::string&, const val template error_info make_not_found_error(const basic_value&, const std::string&, const std::string&); +template +error_info make_not_found_error(const basic_value&, const std::string&, const std::size_t); + template void change_region_of_value(basic_value&, const basic_value&); @@ -1613,6 +1616,44 @@ class basic_value assert(found->first == k); return found->second; } + + result, error_info> + try_at(const key_type& k) noexcept + { + if(!this->is_table()) + { + return err(detail::make_type_error(*this, + "toml::value::try_at(key_type)", value_t::table)); + } + auto& table = this->as_table(std::nothrow); + const auto found = table.find(k); + if(found == table.end()) + { + return err(detail::make_not_found_error(*this, + "toml::value::try_at(key_type)", k)); + } + assert(found->first == k); + return ok(std::ref(found->second)); + } + result, error_info> + try_at(const key_type& k) const noexcept + { + if(!this->is_table()) + { + return err(detail::make_type_error(*this, + "toml::value::try_at(key_type)", value_t::table)); + } + const auto& table = this->as_table(std::nothrow); + const auto found = table.find(k); + if(found == table.end()) + { + return err(detail::make_not_found_error(*this, + "toml::value::try_at(key_type)", k)); + } + assert(found->first == k); + return ok(std::cref(found->second)); + } + value_type& operator[](const key_type& k) { if(this->is_empty()) @@ -1688,6 +1729,41 @@ class basic_value return ar.at(idx); } + result, error_info> + try_at(const std::size_t& idx) noexcept + { + if(!this->is_array()) + { + return err(detail::make_type_error(*this, + "toml::value::try_at(key_type)", value_t::array)); + } + auto& ar = this->as_array(std::nothrow); + + if(ar.size() <= idx) + { + return err(detail::make_not_found_error(*this, + "toml::value::try_at(idx)", idx)); + } + return ok(std::ref(ar[idx])); + } + result, error_info> + try_at(const std::size_t idx) const noexcept + { + if(!this->is_array()) + { + return err(detail::make_type_error(*this, + "toml::value::try_at(key_type)", value_t::array)); + } + const auto& ar = this->as_array(std::nothrow); + + if(ar.size() <= idx) + { + return err(detail::make_not_found_error(*this, + "toml::value::try_at(idx)", idx)); + } + return ok(std::cref(ar[idx])); + } + value_type& operator[](const std::size_t idx) noexcept { // no check... @@ -2092,6 +2168,19 @@ error_info make_not_found_error(const basic_value& v, const std::string& fna } return error_info(title, locs); } +template +error_info make_not_found_error(const basic_value& v, const std::string& fname, const std::size_t idx) +{ + if( ! v.is_array()) + { + return make_type_error(v, fname, toml::value_t::array); + } + std::ostringstream oss; + oss << "actual length (" << v.as_array(std::nothrow).size() + << ") is shorter than the specified index (" << idx << ")."; + return make_error_info(fname + ": no element corresponding to the index", + v, oss.str()); +} #define TOML11_DETAIL_GENERATE_COMPTIME_GETTER(ty) \ template \