diff options
| -rw-r--r-- | CMakeLists.txt | 18 | ||||
| -rw-r--r-- | kernel/kapi/interrupts.cpp | 7 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/vector | 22 | ||||
| -rw-r--r-- | libs/kstd/tests/src/vector.cpp | 60 |
4 files changed, 96 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d785d4e..6cc8a2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,15 +18,17 @@ include("GenerateBootableIso") include("FetchContent") -FetchContent_Declare( - "Catch2" - URL "https://github.com/catchorg/Catch2/archive/refs/tags/v3.7.1.tar.gz" - URL_HASH "SHA256=c991b247a1a0d7bb9c39aa35faf0fe9e19764213f28ffba3109388e62ee0269c" - EXCLUDE_FROM_ALL - FIND_PACKAGE_ARGS -) +if (NOT CMAKE_CROSSCOMPILING) + FetchContent_Declare( + "Catch2" + URL "https://github.com/catchorg/Catch2/archive/refs/tags/v3.7.1.tar.gz" + URL_HASH "SHA256=c991b247a1a0d7bb9c39aa35faf0fe9e19764213f28ffba3109388e62ee0269c" + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS + ) -FetchContent_MakeAvailable("Catch2") + FetchContent_MakeAvailable("Catch2") +endif() #[============================================================================[ # Global Build System Options diff --git a/kernel/kapi/interrupts.cpp b/kernel/kapi/interrupts.cpp index 27427bb..e172e70 100644 --- a/kernel/kapi/interrupts.cpp +++ b/kernel/kapi/interrupts.cpp @@ -3,6 +3,7 @@ #include <kstd/print> #include <kstd/vector> +#include <algorithm> #include <array> #include <cstdint> @@ -22,9 +23,9 @@ namespace kapi::interrupts auto unregister_handler(std::uint32_t irq_number, handler & handler) -> void { - static_cast<void>(irq_number); - static_cast<void>(handler); - kstd::println("[OS:interrupts] TODO: support erasure from vector."); + auto & handler_list = handlers.at(irq_number); + auto [first, last] = std::ranges::remove(handler_list, &handler); + handler_list.erase(first, last); } auto dispatch(std::uint32_t irq_number) -> status diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector index 771fc87..9e41cb6 100644 --- a/libs/kstd/include/kstd/vector +++ b/libs/kstd/include/kstd/vector @@ -711,6 +711,28 @@ namespace kstd return begin() + prefix_size; } + //! Erase a range of elements from this vector. + //! + //! @param first The start of the range to erase. + //! @param last The end of the range to erase. + //! @return An iterator pointing to the element after the last deleted element. + constexpr auto erase(const_iterator first, const_iterator last) -> iterator + { + if (first == last) + { + return begin() + std::ranges::distance(cbegin(), first); + } + + auto prefix_size = std::ranges::distance(cbegin(), first); + auto element_count = std::ranges::distance(first, last); + + std::ranges::move(begin() + prefix_size + element_count, end(), begin() + prefix_size); + destroy_n(end() - element_count, element_count); + m_size -= element_count; + + return begin() + prefix_size; + } + //! Append a given element to this vector via copy construction. constexpr auto push_back(value_type const & value) -> void { diff --git a/libs/kstd/tests/src/vector.cpp b/libs/kstd/tests/src/vector.cpp index 913427c..b7971f4 100644 --- a/libs/kstd/tests/src/vector.cpp +++ b/libs/kstd/tests/src/vector.cpp @@ -760,6 +760,33 @@ SCENARIO("Vector modifiers", "[vector]") REQUIRE_THROWS_AS(v.erase(v.end()), kstd::tests::os_panic); } } + + WHEN("erasing a range of elements") + { + auto it = v.erase(v.cbegin() + 1, v.cend() - 1); + + THEN("the specified range is removed and the size decreases") + { + REQUIRE(v.size() == 2); + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 30); + REQUIRE(it == v.begin() + 1); + } + } + + WHEN("erasing an empty range") + { + auto it = v.erase(v.cbegin() + 1, v.cbegin() + 1); + + THEN("the vector is unchanged") + { + REQUIRE(v.size() == 3); + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 20); + REQUIRE(v[2] == 30); + REQUIRE(it == v.begin() + 1); + } + } } } @@ -1031,6 +1058,39 @@ SCENARIO("Vector modifier move semantics", "[vector]") REQUIRE(it == v.end()); } } + + WHEN("erasing a range of elements in the middle") + { + v.emplace_back(40); + v.emplace_back(50); + + for (auto & elem : v) + { + elem.was_copied = false; + elem.was_moved = false; + } + + auto it = v.erase(v.cbegin() + 1, v.cbegin() + 3); + + THEN("the specified elements are destroyed and subsequent elements are move-assigned leftwards") + { + REQUIRE(v.size() == 3); + + REQUIRE(v[0].value == 10); + REQUIRE_FALSE(v[0].was_moved); + REQUIRE_FALSE(v[0].was_copied); + + REQUIRE(v[1].value == 40); + REQUIRE(v[1].was_moved); + REQUIRE_FALSE(v[1].was_copied); + + REQUIRE(v[2].value == 50); + REQUIRE(v[2].was_moved); + REQUIRE_FALSE(v[2].was_copied); + + REQUIRE(it == v.begin() + 1); + } + } } } |
