diff --git a/include/toml++/impl/array.h b/include/toml++/impl/array.h index 07de3c6..b99c1af 100644 --- a/include/toml++/impl/array.h +++ b/include/toml++/impl/array.h @@ -632,6 +632,84 @@ TOML_NAMESPACE_START /// \name Array operations /// @{ + /// \brief Gets a pointer to the element at a specific index. + /// + /// \detail \cpp + /// auto arr = toml::array{ 99, "bottles of beer on the wall" }; + /// std::cout << "element [0] exists: "sv << !!arr.get(0) << "\n"; + /// std::cout << "element [1] exists: "sv << !!arr.get(1) << "\n"; + /// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n"; + /// if (toml::node* val = arr.get(0)) + /// std::cout << "element [0] is an "sv << val->type() << "\n"; + /// + /// \ecpp + /// + /// \out + /// element [0] exists: true + /// element [1] exists: true + /// element [2] exists: false + /// element [0] is an integer + /// \eout + /// + /// \param index The element's index. + /// + /// \returns A pointer to the element at the specified index if one existed, or nullptr. + TOML_PURE_INLINE_GETTER + node* get(size_t index) noexcept + { + return index < elems_.size() ? elems_[index].get() : nullptr; + } + + /// \brief Gets a pointer to the element at a specific index (const overload). + /// + /// \param index The element's index. + /// + /// \returns A pointer to the element at the specified index if one existed, or nullptr. + TOML_PURE_INLINE_GETTER + const node* get(size_t index) const noexcept + { + return const_cast(*this).get(index); + } + + /// \brief Gets a pointer to the element at a specific index if it is a particular type. + /// + /// \detail \cpp + /// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv }; + /// if (toml::value* val = arr.get_as(0)) + /// std::cout << "element [0] is an integer with value "sv << *val << "\n"; + /// + /// \ecpp + /// + /// \out + /// element [0] is an integer with value 42 + /// \eout + /// + /// \tparam ElemType toml::table, toml::array, or a native TOML value type + /// \param index The element's index. + /// + /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. + template + TOML_NODISCARD + impl::wrap_node* get_as(size_t index) noexcept + { + if (auto val = get(index)) + return val->template as(); + return nullptr; + } + + /// \brief Gets a pointer to the element at a specific index if it is a particular type (const overload). + /// + /// \tparam ElemType toml::table, toml::array, or a native TOML value type + /// \param index The element's index. + /// + /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. + template + TOML_NODISCARD + const impl::wrap_node* get_as(size_t index) const noexcept + { + return const_cast(*this).template get_as(index); + } + /// \brief Gets a reference to the element at a specific index. TOML_NODISCARD node& operator[](size_t index) noexcept @@ -646,28 +724,18 @@ TOML_NAMESPACE_START return *elems_[index]; } -#if TOML_COMPILER_EXCEPTIONS - /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if none existed. - /// - /// \availability This function is only available if you compile with exceptions enabled. TOML_NODISCARD - node& at(size_t index) - { - return *elems_.at(index); - } + TOML_API + node& at(size_t index); /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if none existed. - /// - /// \availability This function is only available if you compile with exceptions enabled. TOML_NODISCARD const node& at(size_t index) const { - return *elems_.at(index); + return const_cast(*this).at(index); } -#endif // TOML_COMPILER_EXCEPTIONS - /// \brief Returns a reference to the first element in the array. TOML_NODISCARD node& front() noexcept @@ -1228,86 +1296,6 @@ TOML_NAMESPACE_START elems_.pop_back(); } - /// \brief Gets the element at a specific index. - /// - /// \detail \cpp - /// auto arr = toml::array{ 99, "bottles of beer on the wall" }; - /// std::cout << "element [0] exists: "sv << !!arr.get(0) << "\n"; - /// std::cout << "element [1] exists: "sv << !!arr.get(1) << "\n"; - /// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n"; - /// if (toml::node* val = arr.get(0)) - /// std::cout << "element [0] is an "sv << val->type() << "\n"; - /// - /// \ecpp - /// - /// \out - /// element [0] exists: true - /// element [1] exists: true - /// element [2] exists: false - /// element [0] is an integer - /// \eout - /// - /// \param index The element's index. - /// - /// \returns A pointer to the element at the specified index if one existed, or nullptr. - TOML_NODISCARD - node* get(size_t index) noexcept - { - return index < elems_.size() ? elems_[index].get() : nullptr; - } - - /// \brief Gets the element at a specific index (const overload). - /// - /// \param index The element's index. - /// - /// \returns A pointer to the element at the specified index if one existed, or nullptr. - TOML_NODISCARD - const node* get(size_t index) const noexcept - { - return index < elems_.size() ? elems_[index].get() : nullptr; - } - - /// \brief Gets the element at a specific index if it is a particular type. - /// - /// \detail \cpp - /// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv }; - /// if (toml::value* val = arr.get_as(0)) - /// std::cout << "element [0] is an integer with value "sv << *val << "\n"; - /// - /// \ecpp - /// - /// \out - /// element [0] is an integer with value 42 - /// \eout - /// - /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \param index The element's index. - /// - /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. - template - TOML_NODISCARD - impl::wrap_node* get_as(size_t index) noexcept - { - if (auto val = get(index)) - return val->as(); - return nullptr; - } - - /// \brief Gets the element at a specific index if it is a particular type (const overload). - /// - /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \param index The element's index. - /// - /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. - template - TOML_NODISCARD - const impl::wrap_node* get_as(size_t index) const noexcept - { - if (auto val = get(index)) - return val->as(); - return nullptr; - } - /// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself. /// /// \detail \cpp diff --git a/include/toml++/impl/array.inl b/include/toml++/impl/array.inl index 5e61e08..693f90b 100644 --- a/include/toml++/impl/array.inl +++ b/include/toml++/impl/array.inl @@ -14,32 +14,6 @@ #include "array.h" #include "header_start.h" -TOML_ANON_NAMESPACE_START -{ - template - TOML_INTERNAL_LINKAGE - bool array_is_homogeneous(T & elements, node_type ntype, U & first_nonmatch) noexcept - { - if (elements.empty()) - { - first_nonmatch = {}; - return false; - } - if (ntype == node_type::none) - ntype = elements[0]->type(); - for (const auto& val : elements) - { - if (val->type() != ntype) - { - first_nonmatch = val.get(); - return false; - } - } - return true; - } -} -TOML_ANON_NAMESPACE_END; - TOML_NAMESPACE_START { TOML_EXTERNAL_LINKAGE @@ -125,13 +99,47 @@ TOML_NAMESPACE_START TOML_EXTERNAL_LINKAGE bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept { - return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch); + if (elems_.empty()) + { + first_nonmatch = {}; + return false; + } + if (ntype == node_type::none) + ntype = elems_[0]->type(); + for (const auto& val : elems_) + { + if (val->type() != ntype) + { + first_nonmatch = val.get(); + return false; + } + } + return true; } TOML_EXTERNAL_LINKAGE bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept { - return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch); + node* fnm = nullptr; + const auto result = const_cast(*this).is_homogeneous(ntype, fnm); + first_nonmatch = fnm; + return result; + } + + TOML_EXTERNAL_LINKAGE + node& array::at(size_t index) + { +#if TOML_COMPILER_EXCEPTIONS + + return *elems_.at(index); + +#else + + auto n = get(index); + TOML_ASSERT(n && "element index not found in array!"); + return *n; + +#endif } TOML_EXTERNAL_LINKAGE diff --git a/include/toml++/impl/table.h b/include/toml++/impl/table.h index c00c4bd..4bb06ee 100644 --- a/include/toml++/impl/table.h +++ b/include/toml++/impl/table.h @@ -672,8 +672,10 @@ TOML_NAMESPACE_START /// /// \returns A pointer to the node at the specified key, or nullptr. TOML_NODISCARD - TOML_API - node* get(std::wstring_view key); + node* get(std::wstring_view key) + { + return get(impl::narrow(key)); + } /// \brief Gets the node at a specific key (const overload). /// @@ -765,18 +767,12 @@ TOML_NAMESPACE_START #endif // TOML_ENABLE_WINDOWS_COMPAT -#if TOML_COMPILER_EXCEPTIONS - /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - /// - /// \availability This function is only available if you compile with exceptions enabled. TOML_NODISCARD TOML_API node& at(std::string_view key); /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - /// - /// \availability This function is only available if you compile with exceptions enabled. TOML_NODISCARD const node& at(std::string_view key) const { @@ -787,14 +783,16 @@ TOML_NAMESPACE_START /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. /// - /// \availability This function is only available if you compile with exceptions and #TOML_ENABLE_WINDOWS_COMPAT enabled. + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. TOML_NODISCARD - TOML_API - node& at(std::wstring_view key); + node& at(std::wstring_view key) + { + return at(impl::narrow(key)); + } /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. /// - /// \availability This function is only available if you compile with exceptions and #TOML_ENABLE_WINDOWS_COMPAT enabled. + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. TOML_NODISCARD const node& at(std::wstring_view key) const { @@ -802,7 +800,6 @@ TOML_NAMESPACE_START } #endif // TOML_ENABLE_WINDOWS_COMPAT -#endif // TOML_COMPILER_EXCEPTIONS /// @} diff --git a/include/toml++/impl/table.inl b/include/toml++/impl/table.inl index 6efbd01..d31d06c 100644 --- a/include/toml++/impl/table.inl +++ b/include/toml++/impl/table.inl @@ -141,22 +141,13 @@ TOML_NAMESPACE_START return nullptr; } -#if TOML_ENABLE_WINDOWS_COMPAT - - TOML_EXTERNAL_LINKAGE - node* table::get(std::wstring_view key) - { - return get(impl::narrow(key)); - } - -#endif - -#if TOML_COMPILER_EXCEPTIONS - TOML_EXTERNAL_LINKAGE node& table::at(std::string_view key) { auto n = get(key); + +#if TOML_COMPILER_EXCEPTIONS + if (!n) { auto err = "key '"s; @@ -164,20 +155,16 @@ TOML_NAMESPACE_START err.append("' not found in table"sv); throw std::out_of_range{ err }; } + +#else + + TOML_ASSERT(n && "key not found in table!"); + +#endif + return *n; } -#if TOML_ENABLE_WINDOWS_COMPAT - - TOML_EXTERNAL_LINKAGE - node& table::at(std::wstring_view key) - { - return at(impl::narrow(key)); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT -#endif // TOML_COMPILER_EXCEPTIONS - TOML_EXTERNAL_LINKAGE bool table::equal(const table& lhs, const table& rhs) noexcept { diff --git a/include/toml++/toml.h b/include/toml++/toml.h index 4fcf540..c50885e 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -15,6 +15,7 @@ TOML_PUSH_WARNINGS; TOML_DISABLE_SPAM_WARNINGS; TOML_DISABLE_SWITCH_WARNINGS; +TOML_DISABLE_SUGGEST_ATTR_WARNINGS; #if TOML_MSVC #pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive) #elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION diff --git a/tests/manipulating_arrays.cpp b/tests/manipulating_arrays.cpp index 0ad5fa3..a2b217e 100644 --- a/tests/manipulating_arrays.cpp +++ b/tests/manipulating_arrays.cpp @@ -182,9 +182,7 @@ TEST_CASE("arrays - construction") CHECK(arr.is_homogeneous()); CHECK(arr.is_homogeneous()); CHECK(!arr.is_homogeneous()); -#if TOML_COMPILER_EXCEPTIONS CHECK(arr.get(0u) == &arr.at(0u)); -#endif const array& carr = arr; CHECK(carr.size() == 1u); @@ -197,9 +195,7 @@ TEST_CASE("arrays - construction") CHECK(carr.is_homogeneous()); CHECK(carr.is_homogeneous()); CHECK(!carr.is_homogeneous()); -#if TOML_COMPILER_EXCEPTIONS CHECK(carr.get(0u) == &carr.at(0u)); -#endif } { @@ -218,10 +214,8 @@ TEST_CASE("arrays - construction") REQUIRE(arr.get_as(4u)); CHECK(*arr.get_as(4u) == 3); CHECK(!arr.is_homogeneous()); -#if TOML_COMPILER_EXCEPTIONS CHECK(arr.get(0u) == &arr.at(0u)); CHECK(arr.get(1u) == &arr.at(1u)); -#endif } #if TOML_ENABLE_WINDOWS_COMPAT diff --git a/tests/manipulating_tables.cpp b/tests/manipulating_tables.cpp index 6a41f84..43bb6f4 100644 --- a/tests/manipulating_tables.cpp +++ b/tests/manipulating_tables.cpp @@ -20,9 +20,7 @@ TEST_CASE("tables - moving") CHECK(tbl["test"].as()->source().begin == source_position{ 1, 8 }); CHECK(tbl["test"].as
()->source().end == source_position{ 1, 24 }); CHECK(tbl["test"].node() == tbl.get("test"sv)); -#if TOML_COMPILER_EXCEPTIONS CHECK(tbl["test"].node() == &tbl.at("test"sv)); -#endif // sanity-check initial state of a freshly-parsed table (const) const table& ctbl = tbl; @@ -31,9 +29,7 @@ TEST_CASE("tables - moving") CHECK(ctbl["test"].as
()->source().begin == source_position{ 1, 8 }); CHECK(ctbl["test"].as
()->source().end == source_position{ 1, 24 }); CHECK(ctbl["test"].node() == ctbl.get("test"sv)); -#if TOML_COMPILER_EXCEPTIONS CHECK(ctbl["test"].node() == &ctbl.at("test"sv)); -#endif // sanity check the virtual type checks CHECK(tbl.type() == node_type::table); diff --git a/toml.hpp b/toml.hpp index 4b179ab..48a8d89 100644 --- a/toml.hpp +++ b/toml.hpp @@ -933,6 +933,7 @@ TOML_ENABLE_WARNINGS; TOML_PUSH_WARNINGS; TOML_DISABLE_SPAM_WARNINGS; TOML_DISABLE_SWITCH_WARNINGS; +TOML_DISABLE_SUGGEST_ATTR_WARNINGS; #if TOML_MSVC #pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive) #elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION @@ -5178,6 +5179,34 @@ TOML_NAMESPACE_START return nullptr; } + TOML_PURE_INLINE_GETTER + node* get(size_t index) noexcept + { + return index < elems_.size() ? elems_[index].get() : nullptr; + } + + TOML_PURE_INLINE_GETTER + const node* get(size_t index) const noexcept + { + return const_cast(*this).get(index); + } + + template + TOML_NODISCARD + impl::wrap_node* get_as(size_t index) noexcept + { + if (auto val = get(index)) + return val->template as(); + return nullptr; + } + + template + TOML_NODISCARD + const impl::wrap_node* get_as(size_t index) const noexcept + { + return const_cast(*this).template get_as(index); + } + TOML_NODISCARD node& operator[](size_t index) noexcept { @@ -5190,22 +5219,16 @@ TOML_NAMESPACE_START return *elems_[index]; } -#if TOML_COMPILER_EXCEPTIONS - TOML_NODISCARD - node& at(size_t index) - { - return *elems_.at(index); - } + TOML_API + node& at(size_t index); TOML_NODISCARD const node& at(size_t index) const { - return *elems_.at(index); + return const_cast(*this).at(index); } -#endif // TOML_COMPILER_EXCEPTIONS - TOML_NODISCARD node& front() noexcept { @@ -5471,36 +5494,6 @@ TOML_NAMESPACE_START elems_.pop_back(); } - TOML_NODISCARD - node* get(size_t index) noexcept - { - return index < elems_.size() ? elems_[index].get() : nullptr; - } - - TOML_NODISCARD - const node* get(size_t index) const noexcept - { - return index < elems_.size() ? elems_[index].get() : nullptr; - } - - template - TOML_NODISCARD - impl::wrap_node* get_as(size_t index) noexcept - { - if (auto val = get(index)) - return val->as(); - return nullptr; - } - - template - TOML_NODISCARD - const impl::wrap_node* get_as(size_t index) const noexcept - { - if (auto val = get(index)) - return val->as(); - return nullptr; - } - TOML_API array& flatten() &; @@ -6096,8 +6089,10 @@ TOML_NAMESPACE_START #if TOML_ENABLE_WINDOWS_COMPAT TOML_NODISCARD - TOML_API - node* get(std::wstring_view key); + node* get(std::wstring_view key) + { + return get(impl::narrow(key)); + } TOML_NODISCARD const node* get(std::wstring_view key) const @@ -6140,8 +6135,6 @@ TOML_NAMESPACE_START #endif // TOML_ENABLE_WINDOWS_COMPAT -#if TOML_COMPILER_EXCEPTIONS - TOML_NODISCARD TOML_API node& at(std::string_view key); @@ -6155,8 +6148,10 @@ TOML_NAMESPACE_START #if TOML_ENABLE_WINDOWS_COMPAT TOML_NODISCARD - TOML_API - node& at(std::wstring_view key); + node& at(std::wstring_view key) + { + return at(impl::narrow(key)); + } TOML_NODISCARD const node& at(std::wstring_view key) const @@ -6165,7 +6160,6 @@ TOML_NAMESPACE_START } #endif // TOML_ENABLE_WINDOWS_COMPAT -#endif // TOML_COMPILER_EXCEPTIONS TOML_NODISCARD iterator begin() noexcept @@ -9218,32 +9212,6 @@ TOML_PUSH_WARNINGS; #undef max #endif -TOML_ANON_NAMESPACE_START -{ - template - TOML_INTERNAL_LINKAGE - bool array_is_homogeneous(T & elements, node_type ntype, U & first_nonmatch) noexcept - { - if (elements.empty()) - { - first_nonmatch = {}; - return false; - } - if (ntype == node_type::none) - ntype = elements[0]->type(); - for (const auto& val : elements) - { - if (val->type() != ntype) - { - first_nonmatch = val.get(); - return false; - } - } - return true; - } -} -TOML_ANON_NAMESPACE_END; - TOML_NAMESPACE_START { TOML_EXTERNAL_LINKAGE @@ -9329,13 +9297,47 @@ TOML_NAMESPACE_START TOML_EXTERNAL_LINKAGE bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept { - return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch); + if (elems_.empty()) + { + first_nonmatch = {}; + return false; + } + if (ntype == node_type::none) + ntype = elems_[0]->type(); + for (const auto& val : elems_) + { + if (val->type() != ntype) + { + first_nonmatch = val.get(); + return false; + } + } + return true; } TOML_EXTERNAL_LINKAGE bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept { - return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch); + node* fnm = nullptr; + const auto result = const_cast(*this).is_homogeneous(ntype, fnm); + first_nonmatch = fnm; + return result; + } + + TOML_EXTERNAL_LINKAGE + node& array::at(size_t index) + { +#if TOML_COMPILER_EXCEPTIONS + + return *elems_.at(index); + +#else + + auto n = get(index); + TOML_ASSERT(n && "element index not found in array!"); + return *n; + +#endif } TOML_EXTERNAL_LINKAGE @@ -9584,22 +9586,13 @@ TOML_NAMESPACE_START return nullptr; } -#if TOML_ENABLE_WINDOWS_COMPAT - - TOML_EXTERNAL_LINKAGE - node* table::get(std::wstring_view key) - { - return get(impl::narrow(key)); - } - -#endif - -#if TOML_COMPILER_EXCEPTIONS - TOML_EXTERNAL_LINKAGE node& table::at(std::string_view key) { auto n = get(key); + +#if TOML_COMPILER_EXCEPTIONS + if (!n) { auto err = "key '"s; @@ -9607,20 +9600,16 @@ TOML_NAMESPACE_START err.append("' not found in table"sv); throw std::out_of_range{ err }; } + +#else + + TOML_ASSERT(n && "key not found in table!"); + +#endif + return *n; } -#if TOML_ENABLE_WINDOWS_COMPAT - - TOML_EXTERNAL_LINKAGE - node& table::at(std::wstring_view key) - { - return at(impl::narrow(key)); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT -#endif // TOML_COMPILER_EXCEPTIONS - TOML_EXTERNAL_LINKAGE bool table::equal(const table& lhs, const table& rhs) noexcept {