diff --git a/examples/parse_benchmark.cpp b/examples/parse_benchmark.cpp index e190a6a..b484a43 100644 --- a/examples/parse_benchmark.cpp +++ b/examples/parse_benchmark.cpp @@ -68,7 +68,7 @@ int main(int argc, char** argv) const auto start = std::chrono::steady_clock::now(); for (size_t i = 0; i < iterations; i++) - std::ignore = toml::parse_file(file_path); + std::ignore = toml::parse(file_content, file_path); const auto cumulative_sec = std::chrono::duration_cast>(std::chrono::steady_clock::now() - start).count(); const auto mean_sec = cumulative_sec / static_cast(iterations); diff --git a/include/toml++/impl/array.h b/include/toml++/impl/array.h index 5b2fbe7..d12b1fb 100644 --- a/include/toml++/impl/array.h +++ b/include/toml++/impl/array.h @@ -20,24 +20,12 @@ TOML_IMPL_NAMESPACE_START private: template friend class array_iterator; - friend class TOML_NAMESPACE::array; using raw_mutable_iterator = std::vector::iterator; using raw_const_iterator = std::vector::const_iterator; using raw_iterator = std::conditional_t; - mutable raw_iterator raw_; - - TOML_NODISCARD_CTOR - array_iterator(raw_mutable_iterator raw) noexcept // - : raw_{ raw } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - array_iterator(raw_const_iterator raw) noexcept // - : raw_{ raw } - {} + mutable raw_iterator iter_; public: using value_type = std::conditional_t; @@ -49,6 +37,23 @@ TOML_IMPL_NAMESPACE_START TOML_NODISCARD_CTOR array_iterator() noexcept = default; + TOML_NODISCARD_CTOR + array_iterator(raw_mutable_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(raw_const_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(const array_iterator& other) noexcept // + : iter_{ other.iter_ } + {} + TOML_NODISCARD_CTOR array_iterator(const array_iterator&) noexcept = default; @@ -56,130 +61,125 @@ TOML_IMPL_NAMESPACE_START array_iterator& operator++() noexcept // ++pre { - ++raw_; + ++iter_; return *this; } array_iterator operator++(int) noexcept // post++ { - array_iterator out{ raw_ }; - ++raw_; + array_iterator out{ iter_ }; + ++iter_; return out; } array_iterator& operator--() noexcept // --pre { - --raw_; + --iter_; return *this; } array_iterator operator--(int) noexcept // post-- { - array_iterator out{ raw_ }; - --raw_; + array_iterator out{ iter_ }; + --iter_; return out; } TOML_PURE_INLINE_GETTER reference operator*() const noexcept { - return *raw_->get(); + return *iter_->get(); } TOML_PURE_INLINE_GETTER pointer operator->() const noexcept { - return raw_->get(); + return iter_->get(); + } + + TOML_PURE_INLINE_GETTER + operator const raw_iterator&() const noexcept + { + return iter_; } array_iterator& operator+=(ptrdiff_t rhs) noexcept { - raw_ += rhs; + iter_ += rhs; return *this; } array_iterator& operator-=(ptrdiff_t rhs) noexcept { - raw_ -= rhs; + iter_ -= rhs; return *this; } TOML_NODISCARD friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept { - return { lhs.raw_ + rhs }; + return lhs.iter_ + rhs; } TOML_NODISCARD friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept { - return { rhs.raw_ + lhs }; + return rhs.iter_ + lhs; } TOML_NODISCARD friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept { - return { lhs.raw_ - rhs }; + return lhs.iter_ - rhs; } TOML_PURE_INLINE_GETTER friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ - rhs.raw_; + return lhs.iter_ - rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ == rhs.raw_; + return lhs.iter_ == rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ != rhs.raw_; + return lhs.iter_ != rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ < rhs.raw_; + return lhs.iter_ < rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ <= rhs.raw_; + return lhs.iter_ <= rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ > rhs.raw_; + return lhs.iter_ > rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ >= rhs.raw_; + return lhs.iter_ >= rhs.iter_; } TOML_PURE_INLINE_GETTER reference operator[](ptrdiff_t idx) const noexcept { - return *(raw_ + idx)->get(); + return *(iter_ + idx)->get(); } - - TOML_DISABLE_WARNINGS; - - TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) - TOML_NODISCARD - operator array_iterator() const noexcept - { - return array_iterator{ raw_ }; - } - - TOML_ENABLE_WARNINGS; }; } TOML_IMPL_NAMESPACE_END; @@ -249,7 +249,6 @@ TOML_NAMESPACE_START private: /// \cond - friend class TOML_PARSER_TYPENAME; std::vector elems_; TOML_API @@ -768,42 +767,42 @@ TOML_NAMESPACE_START TOML_NODISCARD iterator begin() noexcept { - return { elems_.begin() }; + return elems_.begin(); } /// \brief Returns an iterator to the first element. TOML_NODISCARD const_iterator begin() const noexcept { - return { elems_.cbegin() }; + return elems_.cbegin(); } /// \brief Returns an iterator to the first element. TOML_NODISCARD const_iterator cbegin() const noexcept { - return { elems_.cbegin() }; + return elems_.cbegin(); } /// \brief Returns an iterator to one-past-the-last element. TOML_NODISCARD iterator end() noexcept { - return { elems_.end() }; + return elems_.end(); } /// \brief Returns an iterator to one-past-the-last element. TOML_NODISCARD const_iterator end() const noexcept { - return { elems_.cend() }; + return elems_.cend(); } /// \brief Returns an iterator to one-past-the-last element. TOML_NODISCARD const_iterator cend() const noexcept { - return { elems_.cend() }; + return elems_.cend(); } /// \brief Returns true if the array is empty. @@ -887,7 +886,7 @@ TOML_NAMESPACE_START if (!val) return end(); } - return { elems_.emplace(pos.raw_, impl::make_node(static_cast(val), flags)) }; + return elems_.emplace(pos, impl::make_node(static_cast(val), flags)); } /// \brief Repeatedly inserts a new element starting at a specific position in the array. @@ -941,11 +940,11 @@ TOML_NAMESPACE_START } switch (count) { - case 0: return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + case 0: return elems_.begin() + (pos - elems_.cbegin()); case 1: return insert(pos, static_cast(val), flags); default: { - const auto start_idx = static_cast(pos.raw_ - elems_.cbegin()); + const auto start_idx = static_cast(pos - elems_.cbegin()); preinsertion_resize(start_idx, count); size_t i = start_idx; for (size_t e = start_idx + count - 1u; i < e; i++) @@ -953,7 +952,7 @@ TOML_NAMESPACE_START //# potentially move the initial value into the last element elems_[i] = impl::make_node(static_cast(val), flags); - return { elems_.begin() + static_cast(start_idx) }; + return elems_.begin() + static_cast(start_idx); } } } @@ -977,7 +976,7 @@ TOML_NAMESPACE_START { const auto distance = std::distance(first, last); if (distance <= 0) - return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + return elems_.begin() + (pos - elems_.cbegin()); else { auto count = distance; @@ -988,9 +987,9 @@ TOML_NAMESPACE_START if (!(*it)) count--; if (!count) - return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + return elems_.begin() + (pos - elems_.cbegin()); } - const auto start_idx = static_cast(pos.raw_ - elems_.cbegin()); + const auto start_idx = static_cast(pos - elems_.cbegin()); preinsertion_resize(start_idx, static_cast(count)); size_t i = start_idx; for (auto it = first; it != last; it++) @@ -1005,7 +1004,7 @@ TOML_NAMESPACE_START else elems_[i++] = impl::make_node(*it, flags); } - return { elems_.begin() + static_cast(start_idx) }; + return elems_.begin() + static_cast(start_idx); } } @@ -1062,7 +1061,7 @@ TOML_NAMESPACE_START static_assert((impl::is_native || impl::is_one_of)&&!impl::is_cvref, "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - return { elems_.emplace(pos.raw_, new impl::wrap_node{ static_cast(args)... }) }; + return elems_.emplace(pos, new impl::wrap_node{ static_cast(args)... }); } /// \brief Replaces the element at a specific position in the array with a different value. @@ -1103,9 +1102,9 @@ TOML_NAMESPACE_START return end(); } - const auto it = elems_.begin() + (pos.raw_ - elems_.cbegin()); + const auto it = elems_.begin() + (pos - elems_.cbegin()); *it = impl::make_node(static_cast(val), flags); - return iterator{ it }; + return it; } /// \brief Removes the specified element from the array. @@ -1129,7 +1128,7 @@ TOML_NAMESPACE_START /// \returns Iterator to the first element immediately following the removed element. iterator erase(const_iterator pos) noexcept { - return { elems_.erase(pos.raw_) }; + return elems_.erase(pos); } /// \brief Removes the elements in the range [first, last) from the array. @@ -1154,7 +1153,7 @@ TOML_NAMESPACE_START /// \returns Iterator to the first element immediately following the last removed element. iterator erase(const_iterator first, const_iterator last) noexcept { - return { elems_.erase(first.raw_, last.raw_) }; + return elems_.erase(first, last); } /// \brief Resizes the array. @@ -1271,23 +1270,41 @@ TOML_NAMESPACE_START /// \eout /// /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \tparam Args Value constructor argument types. - /// \param args Arguments to forward to the value's constructor. + /// \tparam ElemArgs Element constructor argument types. + /// \param args Arguments to forward to the elements's constructor. /// /// \returns A reference to the newly-constructed element. /// /// \remarks There is no difference between push_back() and emplace_back() /// For trivial value types (floats, ints, bools). - template - decltype(auto) emplace_back(Args&&... args) + template + decltype(auto) emplace_back(ElemArgs&&... args) { - using type = impl::unwrap_node; - static_assert((impl::is_native || impl::is_one_of)&&!impl::is_cvref, - "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + static_assert(!impl::is_cvref, "ElemType may not be const, volatile, or a reference."); - auto nde = new impl::wrap_node{ static_cast(args)... }; - elems_.emplace_back(nde); - return *nde; + static constexpr auto moving_node_ptr = std::is_same_v // + && sizeof...(ElemArgs) == 1u // + && impl::first_is_same; + + using unwrapped_type = impl::unwrap_node; + + static_assert( + moving_node_ptr // + || impl::is_native // + || impl::is_one_of, // + "ElemType argument of array::emplace_back() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (moving_node_ptr) + { + elems_.emplace_back(static_cast(args)...); + return *elems_.back(); + } + else + { + auto nde = new impl::wrap_node{ static_cast(args)... }; + elems_.emplace_back(nde); + return *nde; + } } /// \brief Removes the last element from the array. diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h index ab92994..bd8729a 100644 --- a/include/toml++/impl/forward_declarations.h +++ b/include/toml++/impl/forward_declarations.h @@ -389,7 +389,7 @@ TOML_IMPL_NAMESPACE_START is_one_of, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; template - static constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string> + inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string> #if TOML_HAS_CHAR8 && !std::is_same_v, std::u8string> #endif @@ -399,6 +399,11 @@ TOML_IMPL_NAMESPACE_START template inline constexpr bool dependent_false = false; + template + inline constexpr bool first_is_same = false; + template + inline constexpr bool first_is_same = true; + // general value traits // (as they relate to their equivalent native TOML type) template diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl index 1c5a2f2..c6fb0c1 100644 --- a/include/toml++/impl/parser.inl +++ b/include/toml++/impl/parser.inl @@ -777,7 +777,7 @@ TOML_ANON_NAMESPACE_START std::memcpy(write_pos, arg.data(), len); write_pos += len; } - else if constexpr (std::is_floating_point_v) + else if constexpr (std::is_same_v) { #if TOML_FLOAT_CHARCONV const auto result = std::to_chars(write_pos, buf_end, arg); @@ -785,12 +785,12 @@ TOML_ANON_NAMESPACE_START #else std::ostringstream ss; ss.imbue(std::locale::classic()); - ss.precision(std::numeric_limits::digits10 + 1); + ss.precision(std::numeric_limits::max_digits10); ss << arg; concatenate(write_pos, buf_end, to_sv(std::move(ss).str())); #endif } - else if constexpr (std::is_integral_v) + else if constexpr (impl::is_one_of) { #if TOML_INT_CHARCONV const auto result = std::to_chars(write_pos, buf_end, arg); @@ -803,6 +803,8 @@ TOML_ANON_NAMESPACE_START concatenate(write_pos, buf_end, to_sv(std::move(ss).str())); #endif } + else + static_assert(impl::dependent_false, "Evaluated unreachable branch!"); } struct error_builder @@ -1324,6 +1326,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE std::string_view parse_basic_string(bool multi_line) { return_if_error({}); @@ -1549,6 +1552,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE std::string_view parse_literal_string(bool multi_line) { return_if_error({}); @@ -1773,6 +1777,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE double parse_float() { return_if_error({}); @@ -1928,6 +1933,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE double parse_hex_float() { return_if_error({}); @@ -2104,6 +2110,7 @@ TOML_IMPL_NAMESPACE_START template TOML_NODISCARD + TOML_NEVER_INLINE int64_t parse_integer() { return_if_error({}); @@ -2223,6 +2230,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE date parse_date(bool part_of_datetime = false) { return_if_error({}); @@ -2277,6 +2285,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE time parse_time(bool part_of_datetime = false) { return_if_error({}); @@ -2368,6 +2377,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE date_time parse_date_time() { return_if_error({}); @@ -2444,6 +2454,7 @@ TOML_IMPL_NAMESPACE_START node_ptr parse_inline_table(); TOML_NODISCARD + TOML_NEVER_INLINE node_ptr parse_value_known_prefixes() { return_if_error({}); @@ -2457,32 +2468,32 @@ TOML_IMPL_NAMESPACE_START case U'[': return parse_array(); // inline tables - case U'{': - return parse_inline_table(); + case U'{': return parse_inline_table(); - // floats beginning with '.' - case U'.': - return node_ptr{ new value{ parse_float() } }; + // floats beginning with '.' + case U'.': return node_ptr{ new value{ parse_float() } }; - // strings + // strings case U'"': [[fallthrough]]; - case U'\'': - return node_ptr{ new value{ parse_string().value } }; + case U'\'': return node_ptr{ new value{ parse_string().value } }; + + default: + { + const auto cp_upper = static_cast(cp->value) & ~0x20u; // bools - case U't': [[fallthrough]]; - case U'f': [[fallthrough]]; - case U'T': [[fallthrough]]; - case U'F': - return node_ptr{ new value{ parse_boolean() } }; + if (cp_upper == 70u || cp_upper == 84u) // F or T + return node_ptr{ new value{ parse_boolean() } }; // inf/nan - case U'i': [[fallthrough]]; - case U'I': [[fallthrough]]; - case U'n': [[fallthrough]]; - case U'N': return node_ptr{ new value{ parse_inf_or_nan() } }; + else if (cp_upper == 73u || cp_upper == 78u) // I or N + return node_ptr{ new value{ parse_inf_or_nan() } }; + + else + return nullptr; + } } - return nullptr; + TOML_UNREACHABLE; } TOML_NODISCARD @@ -2569,7 +2580,7 @@ TOML_IMPL_NAMESPACE_START char32_t chars[utf8_buffered_reader::max_history_length]; size_t char_count = {}, advance_count = {}; bool eof_while_scanning = false; - const auto scan = [&]() + const auto scan = [&]() noexcept(!TOML_COMPILER_EXCEPTIONS) { if (is_eof()) return; @@ -2962,6 +2973,7 @@ TOML_IMPL_NAMESPACE_START return val; } + TOML_NEVER_INLINE bool parse_key() { return_if_error({}); @@ -3048,6 +3060,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE table* parse_table_header() { return_if_error({}); @@ -3135,8 +3148,8 @@ TOML_IMPL_NAMESPACE_START { // table arrays are a special case; // the spec dictates we select the most recently declared element in the array. - TOML_ASSERT(!arr->elems_.empty()); - TOML_ASSERT(arr->elems_.back()->is_table()); + TOML_ASSERT(!arr->empty()); + TOML_ASSERT(arr->back().is_table()); parent = &arr->back().ref_cast(); } else @@ -3249,6 +3262,7 @@ TOML_IMPL_NAMESPACE_START } } + TOML_NEVER_INLINE bool parse_key_value_pair_and_insert(table* tbl) { return_if_error({}); @@ -3341,7 +3355,7 @@ TOML_IMPL_NAMESPACE_START node_ptr val = parse_value(); return_if_error({}); - tbl->map_.emplace_hint(it.raw_, std::move(last_key), std::move(val)); + tbl->emplace_hint(it, std::move(last_key), std::move(val)); return true; } @@ -3404,23 +3418,24 @@ TOML_IMPL_NAMESPACE_START if (type == node_type::table) { auto& tbl = nde.ref_cast
(); - if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly terminated + if (tbl.is_inline()) // inline tables (and all their inline descendants) are already correctly + // terminated return; auto end = nde.source_.end; - for (auto& [k, v] : tbl.map_) + for (auto&& [k, v] : tbl) { (void)k; - update_region_ends(*v); - if (end < v->source_.end) - end = v->source_.end; + update_region_ends(v); + if (end < v.source_.end) + end = v.source_.end; } } else // arrays { auto& arr = nde.ref_cast(); auto end = nde.source_.end; - for (auto& v : arr) + for (auto&& v : arr) { update_region_ends(v); if (end < v.source_.end) @@ -3530,7 +3545,7 @@ TOML_IMPL_NAMESPACE_START prev = val; if (!arr.capacity()) arr.reserve(4u); - arr.elems_.emplace_back(parse_value()); + arr.emplace_back(parse_value()); } } @@ -3550,8 +3565,8 @@ TOML_IMPL_NAMESPACE_START advance_and_return_if_error_or_eof({}); node_ptr tbl_ptr{ new table{} }; - table& tbl = tbl_ptr->ref_cast
(); - tbl.inline_ = true; + table& tbl = tbl_ptr->ref_cast
(); + tbl.is_inline(true); enum TOML_CLOSED_ENUM parse_elem : int { none, diff --git a/include/toml++/impl/print_to_stream.inl b/include/toml++/impl/print_to_stream.inl index ef5a79b..e3d9397 100644 --- a/include/toml++/impl/print_to_stream.inl +++ b/include/toml++/impl/print_to_stream.inl @@ -178,7 +178,7 @@ TOML_ANON_NAMESPACE_START std::ostringstream ss; ss.imbue(std::locale::classic()); - ss.precision(std::numeric_limits::digits10 + 1); + ss.precision(std::numeric_limits::max_digits10); if (!!(format & value_flags::format_as_hexadecimal)) ss << std::hexfloat; ss << val; diff --git a/include/toml++/impl/table.h b/include/toml++/impl/table.h index 350646f..605e383 100644 --- a/include/toml++/impl/table.h +++ b/include/toml++/impl/table.h @@ -30,55 +30,59 @@ TOML_IMPL_NAMESPACE_START private: template friend class table_iterator; - friend class TOML_NAMESPACE::table; - friend class TOML_PARSER_TYPENAME; using proxy_type = table_proxy_pair; using raw_mutable_iterator = std::map>::iterator; using raw_const_iterator = std::map>::const_iterator; using raw_iterator = std::conditional_t; - mutable raw_iterator raw_; - mutable std::aligned_storage_t proxy; - mutable bool proxy_instantiated = false; + mutable raw_iterator iter_; + mutable std::aligned_storage_t proxy_; + mutable bool proxy_instantiated_ = false; TOML_NODISCARD proxy_type* get_proxy() const noexcept { - if (!proxy_instantiated) + if (!proxy_instantiated_) { - auto p = ::new (static_cast(&proxy)) proxy_type{ raw_->first, *raw_->second.get() }; - proxy_instantiated = true; + auto p = ::new (static_cast(&proxy_)) proxy_type{ iter_->first, *iter_->second.get() }; + proxy_instantiated_ = true; return p; } else - return TOML_LAUNDER(reinterpret_cast(&proxy)); + return TOML_LAUNDER(reinterpret_cast(&proxy_)); } - TOML_NODISCARD_CTOR - table_iterator(raw_mutable_iterator raw) noexcept // - : raw_{ raw } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - table_iterator(raw_const_iterator raw) noexcept // - : raw_{ raw } - {} - public: TOML_NODISCARD_CTOR table_iterator() noexcept = default; + TOML_NODISCARD_CTOR + table_iterator(raw_mutable_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + table_iterator(raw_const_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + table_iterator(const table_iterator& other) noexcept // + : iter_{ other.iter_ } + {} + TOML_NODISCARD_CTOR table_iterator(const table_iterator& other) noexcept // - : raw_{ other.raw_ } + : iter_{ other.iter_ } {} table_iterator& operator=(const table_iterator& rhs) noexcept { - raw_ = rhs.raw_; - proxy_instantiated = false; + iter_ = rhs.iter_; + proxy_instantiated_ = false; return *this; } @@ -90,31 +94,31 @@ TOML_IMPL_NAMESPACE_START table_iterator& operator++() noexcept // ++pre { - ++raw_; - proxy_instantiated = false; + ++iter_; + proxy_instantiated_ = false; return *this; } table_iterator operator++(int) noexcept // post++ { - table_iterator out{ raw_ }; - ++raw_; - proxy_instantiated = false; + table_iterator out{ iter_ }; + ++iter_; + proxy_instantiated_ = false; return out; } table_iterator& operator--() noexcept // --pre { - --raw_; - proxy_instantiated = false; + --iter_; + proxy_instantiated_ = false; return *this; } table_iterator operator--(int) noexcept // post-- { - table_iterator out{ raw_ }; - --raw_; - proxy_instantiated = false; + table_iterator out{ iter_ }; + --iter_; + proxy_instantiated_ = false; return out; } @@ -130,28 +134,23 @@ TOML_IMPL_NAMESPACE_START return get_proxy(); } + TOML_PURE_INLINE_GETTER + operator const raw_iterator&() const noexcept + { + return iter_; + } + TOML_PURE_INLINE_GETTER friend bool operator==(const table_iterator& lhs, const table_iterator& rhs) noexcept { - return lhs.raw_ == rhs.raw_; + return lhs.iter_ == rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator!=(const table_iterator& lhs, const table_iterator& rhs) noexcept { - return lhs.raw_ != rhs.raw_; + return lhs.iter_ != rhs.iter_; } - - TOML_DISABLE_WARNINGS; - - TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) - TOML_NODISCARD - operator table_iterator() const noexcept - { - return table_iterator{ raw_ }; - } - - TOML_ENABLE_WARNINGS; }; struct table_init_pair @@ -189,8 +188,6 @@ TOML_NAMESPACE_START private: /// \cond - friend class TOML_PARSER_TYPENAME; - std::map> map_; bool inline_ = false; @@ -773,42 +770,42 @@ TOML_NAMESPACE_START TOML_PURE_INLINE_GETTER iterator begin() noexcept { - return iterator{ map_.begin() }; + return map_.begin(); } /// \brief Returns an iterator to the first key-value pair. TOML_PURE_INLINE_GETTER const_iterator begin() const noexcept { - return const_iterator{ map_.cbegin() }; + return map_.cbegin(); } /// \brief Returns an iterator to the first key-value pair. TOML_PURE_INLINE_GETTER const_iterator cbegin() const noexcept { - return const_iterator{ map_.cbegin() }; + return map_.cbegin(); } /// \brief Returns an iterator to one-past-the-last key-value pair. TOML_PURE_INLINE_GETTER iterator end() noexcept { - return iterator{ map_.end() }; + return map_.end(); } /// \brief Returns an iterator to one-past-the-last key-value pair. TOML_PURE_INLINE_GETTER const_iterator end() const noexcept { - return const_iterator{ map_.cend() }; + return map_.cend(); } /// \brief Returns an iterator to one-past-the-last key-value pair. TOML_PURE_INLINE_GETTER const_iterator cend() const noexcept { - return const_iterator{ map_.cend() }; + return map_.cend(); } /// \brief Returns true if the table is empty. @@ -1152,30 +1149,42 @@ TOML_NAMESPACE_START } else { + static constexpr auto moving_node_ptr = std::is_same_v // + && sizeof...(ValueArgs) == 1u // + && impl::first_is_same; using unwrapped_type = impl::unwrap_node; - static_assert((impl::is_native || impl::is_one_of), + + static_assert(moving_node_ptr // + || impl::is_native // + || impl::is_one_of, // "ValueType argument of table::emplace_hint() must be one " "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - auto ipos = map_.emplace_hint(hint.raw_, static_cast(key), nullptr); + auto ipos = map_.emplace_hint(hint, static_cast(key), nullptr); // if second is nullptr then we successully claimed the key and inserted the empty sentinel, // so now we have to construct the actual value if (!ipos->second) { + if constexpr (moving_node_ptr) + ipos->second = std::move(static_cast(args)...); + else + { #if TOML_COMPILER_EXCEPTIONS - try - { - ipos->second.reset(new impl::wrap_node{ static_cast(args)... }); - } - catch (...) - { - map_.erase(ipos); // strong exception guarantee - throw; - } -#else - ipos->second.reset(new impl::wrap_node{ static_cast(args)... }); + try + { #endif + ipos->second.reset( + new impl::wrap_node{ static_cast(args)... }); +#if TOML_COMPILER_EXCEPTIONS + } + catch (...) + { + map_.erase(ipos); // strong exception guarantee + throw; + } +#endif + } } return ipos; } @@ -1284,7 +1293,7 @@ TOML_NAMESPACE_START /// \returns Iterator to the first key-value pair immediately following the removed key-value pair. iterator erase(iterator pos) noexcept { - return { map_.erase(pos.raw_) }; + return map_.erase(pos); } /// \brief Removes the specified key-value pair from the table (const iterator overload). @@ -1312,7 +1321,7 @@ TOML_NAMESPACE_START /// \returns Iterator to the first key-value pair immediately following the removed key-value pair. iterator erase(const_iterator pos) noexcept { - return { map_.erase(pos.raw_) }; + return map_.erase(pos); } /// \brief Removes the key-value pairs in the range [first, last) from the table. @@ -1342,7 +1351,7 @@ TOML_NAMESPACE_START /// \returns Iterator to the first key-value pair immediately following the last removed key-value pair. iterator erase(const_iterator first, const_iterator last) noexcept { - return { map_.erase(first.raw_, last.raw_) }; + return map_.erase(first, last); } /// \brief Removes the value with the given key from the table. @@ -1405,7 +1414,7 @@ TOML_NAMESPACE_START TOML_NODISCARD iterator find(std::string_view key) noexcept { - return { map_.find(key) }; + return map_.find(key); } /// \brief Gets an iterator to the node at a specific key (const overload) @@ -1416,7 +1425,7 @@ TOML_NAMESPACE_START TOML_NODISCARD const_iterator find(std::string_view key) const noexcept { - return { map_.find(key) }; + return map_.find(key); } /// \brief Returns true if the table contains a node at the given key. diff --git a/toml.hpp b/toml.hpp index d55bffd..739f851 100644 --- a/toml.hpp +++ b/toml.hpp @@ -1305,7 +1305,7 @@ TOML_IMPL_NAMESPACE_START is_one_of, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; template - static constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string> + inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v, std::string> #if TOML_HAS_CHAR8 && !std::is_same_v, std::u8string> #endif @@ -1315,6 +1315,11 @@ TOML_IMPL_NAMESPACE_START template inline constexpr bool dependent_false = false; + template + inline constexpr bool first_is_same = false; + template + inline constexpr bool first_is_same = true; + // general value traits // (as they relate to their equivalent native TOML type) template @@ -4729,24 +4734,12 @@ TOML_IMPL_NAMESPACE_START private: template friend class array_iterator; - friend class TOML_NAMESPACE::array; using raw_mutable_iterator = std::vector::iterator; using raw_const_iterator = std::vector::const_iterator; using raw_iterator = std::conditional_t; - mutable raw_iterator raw_; - - TOML_NODISCARD_CTOR - array_iterator(raw_mutable_iterator raw) noexcept // - : raw_{ raw } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - array_iterator(raw_const_iterator raw) noexcept // - : raw_{ raw } - {} + mutable raw_iterator iter_; public: using value_type = std::conditional_t; @@ -4758,6 +4751,23 @@ TOML_IMPL_NAMESPACE_START TOML_NODISCARD_CTOR array_iterator() noexcept = default; + TOML_NODISCARD_CTOR + array_iterator(raw_mutable_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(raw_const_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(const array_iterator& other) noexcept // + : iter_{ other.iter_ } + {} + TOML_NODISCARD_CTOR array_iterator(const array_iterator&) noexcept = default; @@ -4765,130 +4775,125 @@ TOML_IMPL_NAMESPACE_START array_iterator& operator++() noexcept // ++pre { - ++raw_; + ++iter_; return *this; } array_iterator operator++(int) noexcept // post++ { - array_iterator out{ raw_ }; - ++raw_; + array_iterator out{ iter_ }; + ++iter_; return out; } array_iterator& operator--() noexcept // --pre { - --raw_; + --iter_; return *this; } array_iterator operator--(int) noexcept // post-- { - array_iterator out{ raw_ }; - --raw_; + array_iterator out{ iter_ }; + --iter_; return out; } TOML_PURE_INLINE_GETTER reference operator*() const noexcept { - return *raw_->get(); + return *iter_->get(); } TOML_PURE_INLINE_GETTER pointer operator->() const noexcept { - return raw_->get(); + return iter_->get(); + } + + TOML_PURE_INLINE_GETTER + operator const raw_iterator&() const noexcept + { + return iter_; } array_iterator& operator+=(ptrdiff_t rhs) noexcept { - raw_ += rhs; + iter_ += rhs; return *this; } array_iterator& operator-=(ptrdiff_t rhs) noexcept { - raw_ -= rhs; + iter_ -= rhs; return *this; } TOML_NODISCARD friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept { - return { lhs.raw_ + rhs }; + return lhs.iter_ + rhs; } TOML_NODISCARD friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept { - return { rhs.raw_ + lhs }; + return rhs.iter_ + lhs; } TOML_NODISCARD friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept { - return { lhs.raw_ - rhs }; + return lhs.iter_ - rhs; } TOML_PURE_INLINE_GETTER friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ - rhs.raw_; + return lhs.iter_ - rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ == rhs.raw_; + return lhs.iter_ == rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ != rhs.raw_; + return lhs.iter_ != rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ < rhs.raw_; + return lhs.iter_ < rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ <= rhs.raw_; + return lhs.iter_ <= rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ > rhs.raw_; + return lhs.iter_ > rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept { - return lhs.raw_ >= rhs.raw_; + return lhs.iter_ >= rhs.iter_; } TOML_PURE_INLINE_GETTER reference operator[](ptrdiff_t idx) const noexcept { - return *(raw_ + idx)->get(); + return *(iter_ + idx)->get(); } - - TOML_DISABLE_WARNINGS; - - TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) - TOML_NODISCARD - operator array_iterator() const noexcept - { - return array_iterator{ raw_ }; - } - - TOML_ENABLE_WARNINGS; }; } TOML_IMPL_NAMESPACE_END; @@ -4903,7 +4908,6 @@ TOML_NAMESPACE_START { private: - friend class TOML_PARSER_TYPENAME; std::vector elems_; TOML_API @@ -5277,37 +5281,37 @@ TOML_NAMESPACE_START TOML_NODISCARD iterator begin() noexcept { - return { elems_.begin() }; + return elems_.begin(); } TOML_NODISCARD const_iterator begin() const noexcept { - return { elems_.cbegin() }; + return elems_.cbegin(); } TOML_NODISCARD const_iterator cbegin() const noexcept { - return { elems_.cbegin() }; + return elems_.cbegin(); } TOML_NODISCARD iterator end() noexcept { - return { elems_.end() }; + return elems_.end(); } TOML_NODISCARD const_iterator end() const noexcept { - return { elems_.cend() }; + return elems_.cend(); } TOML_NODISCARD const_iterator cend() const noexcept { - return { elems_.cend() }; + return elems_.cend(); } TOML_NODISCARD @@ -5357,7 +5361,7 @@ TOML_NAMESPACE_START if (!val) return end(); } - return { elems_.emplace(pos.raw_, impl::make_node(static_cast(val), flags)) }; + return elems_.emplace(pos, impl::make_node(static_cast(val), flags)); } template @@ -5373,18 +5377,18 @@ TOML_NAMESPACE_START } switch (count) { - case 0: return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + case 0: return elems_.begin() + (pos - elems_.cbegin()); case 1: return insert(pos, static_cast(val), flags); default: { - const auto start_idx = static_cast(pos.raw_ - elems_.cbegin()); + const auto start_idx = static_cast(pos - elems_.cbegin()); preinsertion_resize(start_idx, count); size_t i = start_idx; for (size_t e = start_idx + count - 1u; i < e; i++) elems_[i] = impl::make_node(val, flags); elems_[i] = impl::make_node(static_cast(val), flags); - return { elems_.begin() + static_cast(start_idx) }; + return elems_.begin() + static_cast(start_idx); } } } @@ -5394,7 +5398,7 @@ TOML_NAMESPACE_START { const auto distance = std::distance(first, last); if (distance <= 0) - return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + return elems_.begin() + (pos - elems_.cbegin()); else { auto count = distance; @@ -5405,9 +5409,9 @@ TOML_NAMESPACE_START if (!(*it)) count--; if (!count) - return { elems_.begin() + (pos.raw_ - elems_.cbegin()) }; + return elems_.begin() + (pos - elems_.cbegin()); } - const auto start_idx = static_cast(pos.raw_ - elems_.cbegin()); + const auto start_idx = static_cast(pos - elems_.cbegin()); preinsertion_resize(start_idx, static_cast(count)); size_t i = start_idx; for (auto it = first; it != last; it++) @@ -5422,7 +5426,7 @@ TOML_NAMESPACE_START else elems_[i++] = impl::make_node(*it, flags); } - return { elems_.begin() + static_cast(start_idx) }; + return elems_.begin() + static_cast(start_idx); } } @@ -5441,7 +5445,7 @@ TOML_NAMESPACE_START static_assert((impl::is_native || impl::is_one_of)&&!impl::is_cvref, "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - return { elems_.emplace(pos.raw_, new impl::wrap_node{ static_cast(args)... }) }; + return elems_.emplace(pos, new impl::wrap_node{ static_cast(args)... }); } template @@ -5455,19 +5459,19 @@ TOML_NAMESPACE_START return end(); } - const auto it = elems_.begin() + (pos.raw_ - elems_.cbegin()); + const auto it = elems_.begin() + (pos - elems_.cbegin()); *it = impl::make_node(static_cast(val), flags); - return iterator{ it }; + return it; } iterator erase(const_iterator pos) noexcept { - return { elems_.erase(pos.raw_) }; + return elems_.erase(pos); } iterator erase(const_iterator first, const_iterator last) noexcept { - return { elems_.erase(first.raw_, last.raw_) }; + return elems_.erase(first, last); } template @@ -5498,16 +5502,34 @@ TOML_NAMESPACE_START emplace_back_if_not_empty_view(static_cast(val), flags); } - template - decltype(auto) emplace_back(Args&&... args) + template + decltype(auto) emplace_back(ElemArgs&&... args) { - using type = impl::unwrap_node; - static_assert((impl::is_native || impl::is_one_of)&&!impl::is_cvref, - "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + static_assert(!impl::is_cvref, "ElemType may not be const, volatile, or a reference."); - auto nde = new impl::wrap_node{ static_cast(args)... }; - elems_.emplace_back(nde); - return *nde; + static constexpr auto moving_node_ptr = std::is_same_v // + && sizeof...(ElemArgs) == 1u // + && impl::first_is_same; + + using unwrapped_type = impl::unwrap_node; + + static_assert( + moving_node_ptr // + || impl::is_native // + || impl::is_one_of, // + "ElemType argument of array::emplace_back() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (moving_node_ptr) + { + elems_.emplace_back(static_cast(args)...); + return *elems_.back(); + } + else + { + auto nde = new impl::wrap_node{ static_cast(args)... }; + elems_.emplace_back(nde); + return *nde; + } } void pop_back() noexcept @@ -5866,55 +5888,59 @@ TOML_IMPL_NAMESPACE_START private: template friend class table_iterator; - friend class TOML_NAMESPACE::table; - friend class TOML_PARSER_TYPENAME; using proxy_type = table_proxy_pair; using raw_mutable_iterator = std::map>::iterator; using raw_const_iterator = std::map>::const_iterator; using raw_iterator = std::conditional_t; - mutable raw_iterator raw_; - mutable std::aligned_storage_t proxy; - mutable bool proxy_instantiated = false; + mutable raw_iterator iter_; + mutable std::aligned_storage_t proxy_; + mutable bool proxy_instantiated_ = false; TOML_NODISCARD proxy_type* get_proxy() const noexcept { - if (!proxy_instantiated) + if (!proxy_instantiated_) { - auto p = ::new (static_cast(&proxy)) proxy_type{ raw_->first, *raw_->second.get() }; - proxy_instantiated = true; + auto p = ::new (static_cast(&proxy_)) proxy_type{ iter_->first, *iter_->second.get() }; + proxy_instantiated_ = true; return p; } else - return TOML_LAUNDER(reinterpret_cast(&proxy)); + return TOML_LAUNDER(reinterpret_cast(&proxy_)); } - TOML_NODISCARD_CTOR - table_iterator(raw_mutable_iterator raw) noexcept // - : raw_{ raw } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - table_iterator(raw_const_iterator raw) noexcept // - : raw_{ raw } - {} - public: TOML_NODISCARD_CTOR table_iterator() noexcept = default; + TOML_NODISCARD_CTOR + table_iterator(raw_mutable_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + table_iterator(raw_const_iterator raw) noexcept // + : iter_{ raw } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + table_iterator(const table_iterator& other) noexcept // + : iter_{ other.iter_ } + {} + TOML_NODISCARD_CTOR table_iterator(const table_iterator& other) noexcept // - : raw_{ other.raw_ } + : iter_{ other.iter_ } {} table_iterator& operator=(const table_iterator& rhs) noexcept { - raw_ = rhs.raw_; - proxy_instantiated = false; + iter_ = rhs.iter_; + proxy_instantiated_ = false; return *this; } @@ -5926,31 +5952,31 @@ TOML_IMPL_NAMESPACE_START table_iterator& operator++() noexcept // ++pre { - ++raw_; - proxy_instantiated = false; + ++iter_; + proxy_instantiated_ = false; return *this; } table_iterator operator++(int) noexcept // post++ { - table_iterator out{ raw_ }; - ++raw_; - proxy_instantiated = false; + table_iterator out{ iter_ }; + ++iter_; + proxy_instantiated_ = false; return out; } table_iterator& operator--() noexcept // --pre { - --raw_; - proxy_instantiated = false; + --iter_; + proxy_instantiated_ = false; return *this; } table_iterator operator--(int) noexcept // post-- { - table_iterator out{ raw_ }; - --raw_; - proxy_instantiated = false; + table_iterator out{ iter_ }; + --iter_; + proxy_instantiated_ = false; return out; } @@ -5966,28 +5992,23 @@ TOML_IMPL_NAMESPACE_START return get_proxy(); } + TOML_PURE_INLINE_GETTER + operator const raw_iterator&() const noexcept + { + return iter_; + } + TOML_PURE_INLINE_GETTER friend bool operator==(const table_iterator& lhs, const table_iterator& rhs) noexcept { - return lhs.raw_ == rhs.raw_; + return lhs.iter_ == rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator!=(const table_iterator& lhs, const table_iterator& rhs) noexcept { - return lhs.raw_ != rhs.raw_; + return lhs.iter_ != rhs.iter_; } - - TOML_DISABLE_WARNINGS; - - TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) - TOML_NODISCARD - operator table_iterator() const noexcept - { - return table_iterator{ raw_ }; - } - - TOML_ENABLE_WARNINGS; }; struct table_init_pair @@ -6015,8 +6036,6 @@ TOML_NAMESPACE_START { private: - friend class TOML_PARSER_TYPENAME; - std::map> map_; bool inline_ = false; @@ -6379,37 +6398,37 @@ TOML_NAMESPACE_START TOML_PURE_INLINE_GETTER iterator begin() noexcept { - return iterator{ map_.begin() }; + return map_.begin(); } TOML_PURE_INLINE_GETTER const_iterator begin() const noexcept { - return const_iterator{ map_.cbegin() }; + return map_.cbegin(); } TOML_PURE_INLINE_GETTER const_iterator cbegin() const noexcept { - return const_iterator{ map_.cbegin() }; + return map_.cbegin(); } TOML_PURE_INLINE_GETTER iterator end() noexcept { - return iterator{ map_.end() }; + return map_.end(); } TOML_PURE_INLINE_GETTER const_iterator end() const noexcept { - return const_iterator{ map_.cend() }; + return map_.cend(); } TOML_PURE_INLINE_GETTER const_iterator cend() const noexcept { - return const_iterator{ map_.cend() }; + return map_.cend(); } TOML_PURE_INLINE_GETTER @@ -6577,30 +6596,42 @@ TOML_NAMESPACE_START } else { + static constexpr auto moving_node_ptr = std::is_same_v // + && sizeof...(ValueArgs) == 1u // + && impl::first_is_same; using unwrapped_type = impl::unwrap_node; - static_assert((impl::is_native || impl::is_one_of), + + static_assert(moving_node_ptr // + || impl::is_native // + || impl::is_one_of, // "ValueType argument of table::emplace_hint() must be one " "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - auto ipos = map_.emplace_hint(hint.raw_, static_cast(key), nullptr); + auto ipos = map_.emplace_hint(hint, static_cast(key), nullptr); // if second is nullptr then we successully claimed the key and inserted the empty sentinel, // so now we have to construct the actual value if (!ipos->second) { + if constexpr (moving_node_ptr) + ipos->second = std::move(static_cast(args)...); + else + { #if TOML_COMPILER_EXCEPTIONS - try - { - ipos->second.reset(new impl::wrap_node{ static_cast(args)... }); - } - catch (...) - { - map_.erase(ipos); // strong exception guarantee - throw; - } -#else - ipos->second.reset(new impl::wrap_node{ static_cast(args)... }); + try + { #endif + ipos->second.reset( + new impl::wrap_node{ static_cast(args)... }); +#if TOML_COMPILER_EXCEPTIONS + } + catch (...) + { + map_.erase(ipos); // strong exception guarantee + throw; + } +#endif + } } return ipos; } @@ -6648,17 +6679,17 @@ TOML_NAMESPACE_START iterator erase(iterator pos) noexcept { - return { map_.erase(pos.raw_) }; + return map_.erase(pos); } iterator erase(const_iterator pos) noexcept { - return { map_.erase(pos.raw_) }; + return map_.erase(pos); } iterator erase(const_iterator first, const_iterator last) noexcept { - return { map_.erase(first.raw_, last.raw_) }; + return map_.erase(first, last); } bool erase(std::string_view key) noexcept @@ -6683,13 +6714,13 @@ TOML_NAMESPACE_START TOML_NODISCARD iterator find(std::string_view key) noexcept { - return { map_.find(key) }; + return map_.find(key); } TOML_NODISCARD const_iterator find(std::string_view key) const noexcept { - return { map_.find(key) }; + return map_.find(key); } TOML_NODISCARD @@ -8981,7 +9012,7 @@ TOML_ANON_NAMESPACE_START std::ostringstream ss; ss.imbue(std::locale::classic()); - ss.precision(std::numeric_limits::digits10 + 1); + ss.precision(std::numeric_limits::max_digits10); if (!!(format & value_flags::format_as_hexadecimal)) ss << std::hexfloat; ss << val; @@ -10742,7 +10773,7 @@ TOML_ANON_NAMESPACE_START std::memcpy(write_pos, arg.data(), len); write_pos += len; } - else if constexpr (std::is_floating_point_v) + else if constexpr (std::is_same_v) { #if TOML_FLOAT_CHARCONV const auto result = std::to_chars(write_pos, buf_end, arg); @@ -10750,12 +10781,12 @@ TOML_ANON_NAMESPACE_START #else std::ostringstream ss; ss.imbue(std::locale::classic()); - ss.precision(std::numeric_limits::digits10 + 1); + ss.precision(std::numeric_limits::max_digits10); ss << arg; concatenate(write_pos, buf_end, to_sv(std::move(ss).str())); #endif } - else if constexpr (std::is_integral_v) + else if constexpr (impl::is_one_of) { #if TOML_INT_CHARCONV const auto result = std::to_chars(write_pos, buf_end, arg); @@ -10768,6 +10799,8 @@ TOML_ANON_NAMESPACE_START concatenate(write_pos, buf_end, to_sv(std::move(ss).str())); #endif } + else + static_assert(impl::dependent_false, "Evaluated unreachable branch!"); } struct error_builder @@ -11289,6 +11322,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE std::string_view parse_basic_string(bool multi_line) { return_if_error({}); @@ -11514,6 +11548,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE std::string_view parse_literal_string(bool multi_line) { return_if_error({}); @@ -11738,6 +11773,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE double parse_float() { return_if_error({}); @@ -11893,6 +11929,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE double parse_hex_float() { return_if_error({}); @@ -12069,6 +12106,7 @@ TOML_IMPL_NAMESPACE_START template TOML_NODISCARD + TOML_NEVER_INLINE int64_t parse_integer() { return_if_error({}); @@ -12188,6 +12226,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE date parse_date(bool part_of_datetime = false) { return_if_error({}); @@ -12242,6 +12281,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE time parse_time(bool part_of_datetime = false) { return_if_error({}); @@ -12333,6 +12373,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE date_time parse_date_time() { return_if_error({}); @@ -12409,6 +12450,7 @@ TOML_IMPL_NAMESPACE_START node_ptr parse_inline_table(); TOML_NODISCARD + TOML_NEVER_INLINE node_ptr parse_value_known_prefixes() { return_if_error({}); @@ -12422,32 +12464,32 @@ TOML_IMPL_NAMESPACE_START case U'[': return parse_array(); // inline tables - case U'{': - return parse_inline_table(); + case U'{': return parse_inline_table(); - // floats beginning with '.' - case U'.': - return node_ptr{ new value{ parse_float() } }; + // floats beginning with '.' + case U'.': return node_ptr{ new value{ parse_float() } }; - // strings + // strings case U'"': [[fallthrough]]; - case U'\'': - return node_ptr{ new value{ parse_string().value } }; + case U'\'': return node_ptr{ new value{ parse_string().value } }; + + default: + { + const auto cp_upper = static_cast(cp->value) & ~0x20u; // bools - case U't': [[fallthrough]]; - case U'f': [[fallthrough]]; - case U'T': [[fallthrough]]; - case U'F': - return node_ptr{ new value{ parse_boolean() } }; + if (cp_upper == 70u || cp_upper == 84u) // F or T + return node_ptr{ new value{ parse_boolean() } }; // inf/nan - case U'i': [[fallthrough]]; - case U'I': [[fallthrough]]; - case U'n': [[fallthrough]]; - case U'N': return node_ptr{ new value{ parse_inf_or_nan() } }; + else if (cp_upper == 73u || cp_upper == 78u) // I or N + return node_ptr{ new value{ parse_inf_or_nan() } }; + + else + return nullptr; + } } - return nullptr; + TOML_UNREACHABLE; } TOML_NODISCARD @@ -12533,7 +12575,7 @@ TOML_IMPL_NAMESPACE_START char32_t chars[utf8_buffered_reader::max_history_length]; size_t char_count = {}, advance_count = {}; bool eof_while_scanning = false; - const auto scan = [&]() + const auto scan = [&]() noexcept(!TOML_COMPILER_EXCEPTIONS) { if (is_eof()) return; @@ -12926,6 +12968,7 @@ TOML_IMPL_NAMESPACE_START return val; } + TOML_NEVER_INLINE bool parse_key() { return_if_error({}); @@ -13012,6 +13055,7 @@ TOML_IMPL_NAMESPACE_START } TOML_NODISCARD + TOML_NEVER_INLINE table* parse_table_header() { return_if_error({}); @@ -13099,8 +13143,8 @@ TOML_IMPL_NAMESPACE_START { // table arrays are a special case; // the spec dictates we select the most recently declared element in the array. - TOML_ASSERT(!arr->elems_.empty()); - TOML_ASSERT(arr->elems_.back()->is_table()); + TOML_ASSERT(!arr->empty()); + TOML_ASSERT(arr->back().is_table()); parent = &arr->back().ref_cast
(); } else @@ -13213,6 +13257,7 @@ TOML_IMPL_NAMESPACE_START } } + TOML_NEVER_INLINE bool parse_key_value_pair_and_insert(table* tbl) { return_if_error({}); @@ -13305,7 +13350,7 @@ TOML_IMPL_NAMESPACE_START node_ptr val = parse_value(); return_if_error({}); - tbl->map_.emplace_hint(it.raw_, std::move(last_key), std::move(val)); + tbl->emplace_hint(it, std::move(last_key), std::move(val)); return true; } @@ -13368,23 +13413,24 @@ TOML_IMPL_NAMESPACE_START if (type == node_type::table) { auto& tbl = nde.ref_cast
(); - if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly terminated + if (tbl.is_inline()) // inline tables (and all their inline descendants) are already correctly + // terminated return; auto end = nde.source_.end; - for (auto& [k, v] : tbl.map_) + for (auto&& [k, v] : tbl) { (void)k; - update_region_ends(*v); - if (end < v->source_.end) - end = v->source_.end; + update_region_ends(v); + if (end < v.source_.end) + end = v.source_.end; } } else // arrays { auto& arr = nde.ref_cast(); auto end = nde.source_.end; - for (auto& v : arr) + for (auto&& v : arr) { update_region_ends(v); if (end < v.source_.end) @@ -13494,7 +13540,7 @@ TOML_IMPL_NAMESPACE_START prev = val; if (!arr.capacity()) arr.reserve(4u); - arr.elems_.emplace_back(parse_value()); + arr.emplace_back(parse_value()); } } @@ -13514,8 +13560,8 @@ TOML_IMPL_NAMESPACE_START advance_and_return_if_error_or_eof({}); node_ptr tbl_ptr{ new table{} }; - table& tbl = tbl_ptr->ref_cast
(); - tbl.inline_ = true; + table& tbl = tbl_ptr->ref_cast
(); + tbl.is_inline(true); enum TOML_CLOSED_ENUM parse_elem : int { none,