#ifndef TOML11_GET #define TOML11_GET #include "value.hpp" #include namespace toml { // ============================================================================ // exact toml::* type template::value, std::nullptr_t>::type = nullptr> inline T& get(value& v) { return v.cast::value>(); } template::value, std::nullptr_t>::type = nullptr> inline T const& get(const value& v) { return v.cast::value>(); } template::value, std::nullptr_t>::type = nullptr> inline T && get(value&& v) { return v.cast::value>(); } // ============================================================================ // integer convertible from toml::Integer template, // T is integral detail::negation>, // but not bool detail::negation> // but not toml::integer >::value, std::nullptr_t>::type = nullptr> inline T get(const value& v) { return static_cast(v.cast()); } // ============================================================================ // floating point convertible from toml::Float template, // T is floating_point detail::negation> // but not toml::Float >::value, std::nullptr_t>::type = nullptr> inline T get(const value& v) { return static_cast(v.cast()); } // ============================================================================ // std::string; toml uses its own toml::string, but it should be convertible to // std::string seamlessly template::value, std::nullptr_t>::type = nullptr> inline std::string& get(value& v) { return v.cast().str; } template::value, std::nullptr_t>::type = nullptr> inline std::string const& get(const value& v) { return v.cast().str; } template::value, std::nullptr_t>::type = nullptr> inline std::string get(value&& v) { return std::move(v.cast().str); } // ============================================================================ // std::chrono::duration from toml::local_time. template::value, std::nullptr_t>::type = nullptr> inline T get(value& v) { return std::chrono::duration_cast( std::chrono::microseconds(v.cast())); } // ============================================================================ // std::chrono::system_clock::time_point from toml::datetime variants template::value, std::nullptr_t>::type = nullptr> inline T get(value& v) { switch(v.type()) { case value_t::LocalDate: { return std::chrono::system_clock::time_point( v.cast()); } case value_t::LocalDatetime: { return std::chrono::system_clock::time_point( v.cast()); } default: { return std::chrono::system_clock::time_point( v.cast()); } } } // ============================================================================ // forward declaration to use this recursively. ignore this and go ahead. template, // T is container detail::has_resize_method, // T::resize(N) works detail::negation> // but not toml::array >::value, std::nullptr_t>::type = nullptr> T get(const value& v); template, // T is container detail::negation>, // no T::resize() exists detail::negation> // not toml::array >::value, std::nullptr_t>::type = nullptr> T get(const value& v); template::value, std::nullptr_t>::type = nullptr> T get(const value& v); template::value, std::nullptr_t>::type = nullptr> T get(const value& v); template, // T is map detail::negation> // but not toml::table >::value, std::nullptr_t>::type = nullptr> T get(const toml::value& v); // ============================================================================ // array-like types; most likely STL container, like std::vector, etc. template, // T is container detail::has_resize_method, // T::resize(N) works detail::negation> // but not toml::array >::value, std::nullptr_t>::type = nullptr> T get(const value& v) { using value_type = typename T::value_type; const auto& ar = v.cast(); T container; container.resize(ar.size()); std::transform(ar.cbegin(), ar.cend(), container.begin(), [](const value& x){return ::toml::get(x);}); return container; } // ============================================================================ // array-like types; but does not have resize(); most likely std::array. template, // T is container detail::negation>, // no T::resize() exists detail::negation> // not toml::array >::value, std::nullptr_t>::type = nullptr> T get(const value& v) { using value_type = typename T::value_type; const auto& ar = v.cast(); T container; if(ar.size() != container.size()) { throw std::out_of_range(detail::format_error_for_value(v, concat_to_string( "[erorr] toml::get specified container size is ", container.size(), " but there are ", ar.size(), " elements in toml array."), "here")); } std::transform(ar.cbegin(), ar.cend(), container.begin(), [](const value& x){return ::toml::get(x);}); return container; } // ============================================================================ // std::pair. template::value, std::nullptr_t>::type = nullptr> T get(const value& v) { using first_type = typename T::first_type; using second_type = typename T::second_type; const auto& ar = v.cast(); if(ar.size() != 2) { throw std::out_of_range(detail::format_error_for_value(v, concat_to_string( "[erorr] toml::get specified std::pair but there are ", ar.size(), " elements in toml array."), "here")); } return std::make_pair(::toml::get(ar.at(0)), ::toml::get(ar.at(1))); } // ============================================================================ // std::tuple. namespace detail { template T get_tuple_impl(const toml::Array& a, index_sequence) { return std::make_tuple( ::toml::get::type>(a.at(I))...); } } // detail template::value, std::nullptr_t>::type = nullptr> T get(const value& v) { const auto& ar = v.cast(); if(ar.size() != std::tuple_size::value) { throw std::out_of_range(detail::format_error_for_value(v, concat_to_string( "[erorr] toml::get specified std::tuple with ", std::tuple_size::value, "elements, but there are ", ar.size(), " elements in toml array."), "here")); } return detail::get_tuple_impl(ar, detail::make_index_sequence::value>{}); } // ============================================================================ // map-like types; most likely STL map, like std::map or std::unordered_map. template, // T is map detail::negation> // but not toml::table >::value, std::nullptr_t>::type = nullptr> T get(const toml::value& v) { using key_type = typename T::key_type; using mapped_type = typename T::mapped_type; static_assert(std::is_convertible::value, "toml::get only supports map type of which key_type is " "convertible from std::string."); T map; for(const auto& kv : v.cast()) { map[key_type(kv.first)] = ::toml::get(kv.second); } return map; } // ============================================================================ // get_or template inline typename std::remove_cv::type>::type get_or(const toml::Table& tab, const toml::key& ky, T&& opt) { if(tab.count(ky) == 0) {return std::forward(opt);} return get::type>::type>(tab.find(ky)->second); } // ============================================================================ // expect template auto expect(const toml::value& v) -> result(v)), std::string> { try { return ok(get(v)); } catch(const type_error& te) { return err(te.what()); } } template auto expect(toml::value& v) -> result(v)), std::string> { try { return ok(get(v)); } catch(const type_error& te) { return err(te.what()); } } template auto expect(toml::value&& v) -> result(std::move(v))), std::string> { try { return ok(get(std::move(v))); } catch(const type_error& te) { return err(te.what()); } } } // toml #endif// TOML11_GET