diff --git a/wpiutil/src/main/native/include/wpi/UidVector.h b/wpiutil/src/main/native/include/wpi/UidVector.h index cf635094e3..ead1246e30 100644 --- a/wpiutil/src/main/native/include/wpi/UidVector.h +++ b/wpiutil/src/main/native/include/wpi/UidVector.h @@ -8,11 +8,59 @@ #ifndef WPIUTIL_WPI_UIDVECTOR_H_ #define WPIUTIL_WPI_UIDVECTOR_H_ +#include #include #include namespace wpi { +namespace impl { +template +class UidVectorIterator { + public: + using iterator_type = std::forward_iterator_tag; + using value_type = typename It::value_type; + using difference_type = typename It::difference_type; + using reference = typename It::reference; + using pointer = typename It::pointer; + + UidVectorIterator() = default; + explicit UidVectorIterator(It it, It end) : m_it(it), m_end(end) { + // advance to first non-empty element + while (m_it != m_end && !*m_it) ++m_it; + } + + reference operator*() const noexcept { return *m_it; } + pointer operator->() const noexcept { return m_it.operator->(); } + + UidVectorIterator& operator++() noexcept { + // advance past empty elements + do { + ++m_it; + } while (m_it != m_end && !*m_it); + return *this; + } + + UidVectorIterator operator++(int)noexcept { + UidVectorIterator it = *this; + ++it; + return it; + } + + bool operator==(const UidVectorIterator& oth) const noexcept { + return m_it == oth.m_it; + } + + bool operator!=(const UidVectorIterator& oth) const noexcept { + return m_it != oth.m_it; + } + + private: + It m_it; + It m_end; +}; +} // namespace impl + // Vector which provides an integrated freelist for removal and reuse of // individual elements. // @tparam T element type; must be default-constructible and evaluate in @@ -22,7 +70,16 @@ namespace wpi { template ::size_type reuse_threshold> class UidVector { public: - typedef typename std::vector::size_type size_type; + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using size_type = typename std::vector::size_type; + using difference_type = typename std::vector::difference_type; + using iterator = impl::UidVectorIterator::iterator>; + using const_iterator = + impl::UidVectorIterator::const_iterator>; bool empty() const { return m_active_count == 0; } size_type size() const { return m_vector.size(); } @@ -56,6 +113,31 @@ class UidVector { --m_active_count; } + // Removes all elements. + void clear() { + m_vector.clear(); + m_free.clear(); + m_active_count = 0; + } + + // Iterator access + iterator begin() noexcept { + return iterator(m_vector.begin(), m_vector.end()); + } + const_iterator begin() const noexcept { + return const_iterator(m_vector.begin(), m_vector.end()); + } + const_iterator cbegin() const noexcept { + return const_iterator(m_vector.begin(), m_vector.end()); + } + iterator end() noexcept { return iterator(m_vector.end(), m_vector.end()); } + const_iterator end() const noexcept { + return const_iterator(m_vector.end(), m_vector.end()); + } + const_iterator cend() const noexcept { + return const_iterator(m_vector.end(), m_vector.end()); + } + private: std::vector m_vector; std::vector m_free; diff --git a/wpiutil/src/test/native/cpp/UidVectorTest.cpp b/wpiutil/src/test/native/cpp/UidVectorTest.cpp new file mode 100644 index 0000000000..e11c7b2438 --- /dev/null +++ b/wpiutil/src/test/native/cpp/UidVectorTest.cpp @@ -0,0 +1,48 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "wpi/UidVector.h" // NOLINT(build/include_order) + +#include "gtest/gtest.h" + +namespace wpi { + +TEST(UidVectorTest, Empty) { + UidVector v; + ASSERT_TRUE(v.empty()); + + v.emplace_back(1); + ASSERT_FALSE(v.empty()); +} + +TEST(UidVectorTest, Erase) { + UidVector v; + size_t uid = v.emplace_back(1); + v.erase(uid); + ASSERT_TRUE(v.empty()); +} + +TEST(UidVectorTest, Clear) { + UidVector v; + v.emplace_back(1); + v.emplace_back(2); + v.clear(); + ASSERT_TRUE(v.empty()); +} + +TEST(UidVectorTest, Iterate) { + UidVector v; + v.emplace_back(2); + v.emplace_back(1); + std::vector out; + for (auto&& val : v) out.push_back(val); + ASSERT_EQ(out.size(), 2u); + EXPECT_EQ(out[0], 2); + EXPECT_EQ(out[1], 1); +} + +} // namespace wpi