From 40a456e54a6d3a1ee496dc637132edbded36db9b Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 1 Jan 2025 19:29:41 -0600 Subject: [PATCH] [ox/std] Add Vector::shrink_to_fit --- deps/ox/src/ox/std/test/CMakeLists.txt | 1 + deps/ox/src/ox/std/test/tests.cpp | 30 ++++++++++++++++++++++++++ deps/ox/src/ox/std/vector.hpp | 20 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/deps/ox/src/ox/std/test/CMakeLists.txt b/deps/ox/src/ox/std/test/CMakeLists.txt index 9c395b9c..1ecad4ed 100644 --- a/deps/ox/src/ox/std/test/CMakeLists.txt +++ b/deps/ox/src/ox/std/test/CMakeLists.txt @@ -17,6 +17,7 @@ add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String") add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap") add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2") add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector") +add_test("[ox/std] Vector::shrink_to_fit" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector::shrink_to_fit") add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap") add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc) add_test("[ox/std] Serialize-Int" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Serialize-Int") diff --git a/deps/ox/src/ox/std/test/tests.cpp b/deps/ox/src/ox/std/test/tests.cpp index ede7e60a..6325d151 100644 --- a/deps/ox/src/ox/std/test/tests.cpp +++ b/deps/ox/src/ox/std/test/tests.cpp @@ -237,6 +237,36 @@ OX_CLANG_NOWARN_END return ox::Error(0); } }, + { + "Vector::shrink_to_fit", + [] { + { + ox::Vector> v; + v.reserve(50); + v.emplace_back("asdf"); + v.emplace_back("aoeu"); + auto const origData = v.data(); + v.shrink_to_fit(); + oxExpect(v[0], "asdf"); + oxExpect(v[1], "aoeu"); + oxExpect(v.capacity(), 2u); + oxAssert(origData != v.data(), "shrink_to_fit did not create a new allocation"); + } + { + ox::Vector> v; + v.reserve(2); + v.emplace_back("asdf"); + v.emplace_back("aoeu"); + auto const origData = v.data(); + v.shrink_to_fit(); + oxExpect(v[0], "asdf"); + oxExpect(v[1], "aoeu"); + oxExpect(v.capacity(), 2u); + oxAssert(origData == v.data(), "shrink_to_fit inappropriately created a new allocation"); + } + return ox::Error{}; + } + }, { "SmallMap", [] { diff --git a/deps/ox/src/ox/std/vector.hpp b/deps/ox/src/ox/std/vector.hpp index 7c8b5e33..c60c3bdd 100644 --- a/deps/ox/src/ox/std/vector.hpp +++ b/deps/ox/src/ox/std/vector.hpp @@ -313,6 +313,8 @@ class Vector: detail::VectorAllocator { constexpr void reserve(std::size_t cap) noexcept(useNoexcept); + constexpr void shrink_to_fit() noexcept(useNoexcept); + private: constexpr void reserveInsert( std::size_t cap, std::size_t pos, std::size_t offset = 1) noexcept(useNoexcept); @@ -675,6 +677,24 @@ constexpr void Vector::reserve(std::size_t cap) n } } +template +constexpr void Vector::shrink_to_fit() noexcept(useNoexcept) { + if (m_size == m_cap) { + return; + } + const auto oldItems = m_items; + const auto oldCap = m_cap; + m_cap = m_size; + this->allocate(&m_items, m_size); + if (oldItems) { // move over old items + for (std::size_t i = 0; i < m_size; ++i) { + std::construct_at(&m_items[i], std::move(oldItems[i])); + oldItems[i].~T(); + } + this->deallocate(oldItems, oldCap); + } +} + template constexpr void Vector::reserveInsert( std::size_t cap,