diff --git a/single_include/toml.hpp b/single_include/toml.hpp index a395291..a8894f1 100644 --- a/single_include/toml.hpp +++ b/single_include/toml.hpp @@ -1892,9 +1892,19 @@ using source_location = std::source_location; inline std::string to_string(const source_location& loc) { - return std::string(" at line ") + std::to_string(loc.line()) + - std::string(" in file ") + std::string(loc.file_name()); + const char* fname = loc.file_name(); + if(fname) + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in file ") + std::string(fname); + } + else + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in unknown file"); + } } + } // cxx } // toml #elif defined(TOML11_HAS_EXPERIMENTAL_SOURCE_LOCATION) @@ -1907,9 +1917,19 @@ using source_location = std::experimental::source_location; inline std::string to_string(const source_location& loc) { - return std::string(" at line ") + std::to_string(loc.line()) + - std::string(" in file ") + std::string(loc.file_name()); + const char* fname = loc.file_name(); + if(fname) + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in file ") + std::string(fname); + } + else + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in unknown file"); + } } + } // cxx } // toml #elif defined(TOML11_HAS_BUILTIN_FILE_LINE) @@ -1941,9 +1961,19 @@ struct source_location inline std::string to_string(const source_location& loc) { - return std::string(" at line ") + std::to_string(loc.line()) + - std::string(" in file ") + std::string(loc.file_name()); + const char* fname = loc.file_name(); + if(fname) + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in file ") + std::string(fname); + } + else + { + return std::string(" at line ") + std::to_string(loc.line()) + + std::string(" in unknown file"); + } } + } // cxx } // toml #else // no builtin @@ -3526,6 +3556,10 @@ struct from; #include #endif +#if defined(TOML11_HAS_OPTIONAL) +#include +#endif + namespace toml { template @@ -3670,6 +3704,16 @@ struct is_std_tuple_impl> : std::true_type{}; template using is_std_tuple = is_std_tuple_impl>; +#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE +# if __has_include() +template struct is_std_optional_impl : std::false_type{}; +template +struct is_std_optional_impl> : std::true_type{}; +template +using is_std_optional = is_std_optional_impl>; +# endif // +#endif // > C++17 + template struct is_std_array_impl : std::false_type{}; template struct is_std_array_impl> : std::true_type{}; @@ -9123,6 +9167,95 @@ find(basic_value&& v, const std::size_t idx) return basic_value(std::move(v.at(idx))); } +// -------------------------------------------------------------------------- +// find> + +#if defined(TOML11_HAS_OPTIONAL) +template +cxx::enable_if_t::value, T> +find(const basic_value& v, const typename basic_value::key_type& ky) +{ + if(v.contains(ky)) + { + return ::toml::get(v.at(ky)); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value, T> +find(basic_value& v, const typename basic_value::key_type& ky) +{ + if(v.contains(ky)) + { + return ::toml::get(v.at(ky)); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value, T> +find(basic_value&& v, const typename basic_value::key_type& ky) +{ + if(v.contains(ky)) + { + return ::toml::get(std::move(v.at(ky))); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(const basic_value& v, const K& k) +{ + if(static_cast(k) < v.size()) + { + return ::toml::get(v.at(static_cast(k))); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(basic_value& v, const K& k) +{ + if(static_cast(k) < v.size()) + { + return ::toml::get(v.at(static_cast(k))); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(basic_value&& v, const K& k) +{ + if(static_cast(k) < v.size()) + { + return ::toml::get(std::move(v.at(static_cast(k)))); + } + else + { + return std::nullopt; + } +} +#endif // optional + // -------------------------------------------------------------------------- // toml::find(toml::value, toml::key, Ts&& ... keys) @@ -9214,6 +9347,88 @@ find(basic_value&& v, const K1& k1, const K2& k2, const Ks& ... ks) return find(std::move(v.at(detail::key_cast(k1))), detail::key_cast(k2), ks...); } +#if defined(TOML11_HAS_OPTIONAL) +template +cxx::enable_if_t::value, T> +find(const basic_value& v, const typename basic_value::key_type& k1, const K2& k2, const Ks& ... ks) +{ + if(v.contains(k1)) + { + return find(v.at(k1), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} +template +cxx::enable_if_t::value, T> +find(basic_value& v, const typename basic_value::key_type& k1, const K2& k2, const Ks& ... ks) +{ + if(v.contains(k1)) + { + return find(v.at(k1), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} +template +cxx::enable_if_t::value, T> +find(basic_value&& v, const typename basic_value::key_type& k1, const K2& k2, const Ks& ... ks) +{ + if(v.contains(k1)) + { + return find(v.at(k1), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} + +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(const basic_value& v, const K1& k1, const K2& k2, const Ks& ... ks) +{ + if(static_cast(k1) < v.size()) + { + return find(v.at(static_cast(k1)), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(basic_value& v, const K1& k1, const K2& k2, const Ks& ... ks) +{ + if(static_cast(k1) < v.size()) + { + return find(v.at(static_cast(k1)), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} +template +cxx::enable_if_t::value && std::is_integral::value, T> +find(basic_value&& v, const K1& k1, const K2& k2, const Ks& ... ks) +{ + if(static_cast(k1) < v.size()) + { + return find(v.at(static_cast(k1)), detail::key_cast(k2), ks...); + } + else + { + return std::nullopt; + } +} +#endif // optional + // =========================================================================== // find_or(value, key, fallback)