From 79dd2084ceb5e468a7398d216dfec23b2ff2e7f2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 14 Sep 2024 13:52:25 +0200 Subject: [PATCH] tl::list enhancement --- src/tl/tl/tlList.h | 297 ++++++++++++++++++++++--------- src/tl/tl/tlTimer.cc | 15 +- src/tl/unit_tests/tlListTests.cc | 67 +++++++ 3 files changed, 287 insertions(+), 92 deletions(-) diff --git a/src/tl/tl/tlList.h b/src/tl/tl/tlList.h index 2d5b572a0..3f5ba29dd 100644 --- a/src/tl/tl/tlList.h +++ b/src/tl/tl/tlList.h @@ -109,16 +109,130 @@ private: bool m_owned; }; +/** + * @brief An iterator for the linked list + */ +template +class list_iterator +{ +public: + typedef std::bidirectional_iterator_tag category; + typedef C value_type; + typedef C &reference; + typedef C *pointer; + + list_iterator (C *p = 0) : mp_p (p) { } + list_iterator operator++ () { mp_p = static_cast (mp_p->mp_next); return *this; } + list_iterator operator-- () { mp_p = static_cast (mp_p->mp_prev); return *this; } + + list_iterator operator++ (int) + { + list_iterator r = *this; + ++*this; + return r; + } + + list_iterator operator-- (int) + { + list_iterator r = *this; + --*this; + return r; + } + + C *operator-> () const + { + return mp_p; + } + + C &operator* () const + { + return *mp_p; + } + + bool operator== (list_iterator other) const { return mp_p == other.mp_p; } + bool operator!= (list_iterator other) const { return mp_p != other.mp_p; } + +private: + C *mp_p; +}; + +/** + * @brief A reverse iterator for the linked list + */ +template +class reverse_list_iterator +{ +public: + typedef std::bidirectional_iterator_tag category; + typedef C value_type; + typedef C &reference; + typedef C *pointer; + + reverse_list_iterator (C *p = 0) : mp_p (p) { } + reverse_list_iterator operator++ () { mp_p = static_cast (mp_p->mp_prev); return *this; } + reverse_list_iterator operator-- () { mp_p = static_cast (mp_p->mp_next); return *this; } + + reverse_list_iterator operator++ (int) + { + reverse_list_iterator r = *this; + ++*this; + return r; + } + + reverse_list_iterator operator-- (int) + { + reverse_list_iterator r = *this; + --*this; + return r; + } + + C *operator-> () const + { + return mp_p; + } + + C &operator* () const + { + return *mp_p; + } + + bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; } + bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; } + +private: + C *mp_p; +}; + template class list_impl { public: + typedef list_iterator iterator; + typedef list_iterator const_iterator; + typedef reverse_list_iterator reverse_iterator; + typedef reverse_list_iterator const_reverse_iterator; + + typedef C value_type; + list_impl () : m_head (), m_back () { m_head.mp_next = &m_back; m_back.mp_prev = &m_head; } + list_impl (const list_impl &&other) + { + swap (other); + } + + list_impl &operator= (const list_impl &&other) + { + if (&other != this) { + swap (other); + } + return *this; + } + list_impl (const list_impl &) { tl_assert (false); } list_impl &operator= (const list_impl &) { tl_assert (false); return *this; } @@ -143,6 +257,18 @@ public: } } + void erase (iterator i) + { + erase (i.operator-> ()); + } + + void erase (iterator from, iterator to) + { + while (from != to) { + erase (from++); + } + } + void swap (list_impl &other) { std::swap (m_head.mp_next, other.m_head.mp_next); @@ -196,14 +322,24 @@ public: delete first (); } - void insert (C *after, C *new_obj) + C *insert (C *after, C *new_obj) { - insert_impl (after, new_obj, true); + return insert_impl (after, new_obj, true); } - void insert_before (C *before, C *new_obj) + iterator insert (iterator after, C *new_obj) { - insert_before_impl (before, new_obj, true); + return iterator (insert (after.operator-> (), new_obj)); + } + + C *insert_before (C *before, C *new_obj) + { + return insert_before_impl (before, new_obj, true); + } + + iterator insert_before (iterator before, C *new_obj) + { + return iterator (insert_before_impl (before.operator-> (), new_obj, true)); } void push_back (C *new_obj) @@ -216,14 +352,24 @@ public: push_front_impl (new_obj, true); } - void insert (C *after, C &new_obj) + C *insert (C *after, C &new_obj) { - insert_impl (after, &new_obj, false); + return insert_impl (after, &new_obj, false); } - void insert_before (C *before, C &new_obj) + iterator insert (iterator after, C &new_obj) { - insert_before_impl (before, &new_obj, false); + return iterator (insert_impl (after.operator-> (), &new_obj, false)); + } + + C *insert_before (C *before, C &new_obj) + { + return insert_before_impl (before, &new_obj, false); + } + + iterator insert_before (iterator before, C &new_obj) + { + return iterator (insert_before_impl (before.operator-> (), &new_obj, false)); } void push_back (C &new_obj) @@ -269,7 +415,7 @@ protected: private: list_node m_head, m_back; - void insert_impl (C *after, C *new_obj, bool owned) + C *insert_impl (C *after, C *new_obj, bool owned) { list_node *after_node = after; if (! after) { @@ -281,9 +427,11 @@ private: after_node->mp_next = new_obj; new_obj->mp_prev = after_node; new_obj->mp_next->mp_prev = new_obj; + + return new_obj; } - void insert_before_impl (C *before, C *new_obj, bool owned) + C *insert_before_impl (C *before, C *new_obj, bool owned) { list_node *before_node = before; if (! before) { @@ -295,6 +443,8 @@ private: before_node->mp_prev = new_obj; new_obj->mp_next = before_node; new_obj->mp_prev->mp_next = new_obj; + + return new_obj; } void push_back_impl (C *new_obj, bool owned) @@ -313,6 +463,11 @@ class list_impl : public list_impl { public: + typedef typename list_impl::iterator iterator; + typedef typename list_impl::const_iterator const_iterator; + typedef typename list_impl::reverse_iterator reverse_iterator; + typedef typename list_impl::const_reverse_iterator const_reverse_iterator; + using list_impl::insert; using list_impl::push_back; using list_impl::pop_back; @@ -339,14 +494,52 @@ public: return *this; } - void insert (C *after, const C &obj) + C *insert (C *after, const C &obj) { - insert (after, new C (obj)); + return insert (after, new C (obj)); } - void insert_before (C *before, const C &obj) + iterator insert (iterator after, const C &obj) { - insert_before (before, new C (obj)); + return insert (after, new C (obj)); + } + + template + iterator insert (iterator after, Iter from, Iter to) + { + if (from == to) { + return after; + } else { + iterator first = this->insert (after, *from++); + for (iterator next = first; from != to; ++from) { + next = this->insert (next, *from); + } + return first; + } + } + + C *insert_before (C *before, const C &obj) + { + return insert_before (before, new C (obj)); + } + + iterator insert_before (iterator before, const C &obj) + { + return insert_before (before, new C (obj)); + } + + template + iterator insert_before (iterator before, Iter from, Iter to) + { + if (from == to) { + return before; + } else { + iterator first = this->insert_before (before, *from++); + for (iterator next = first; from != to; ++from) { + next = this->insert (next, *from); + } + return first; + } } void push_back (const C &obj) @@ -360,72 +553,6 @@ public: } }; -/** - * @brief An iterator for the linked list - */ -template -class list_iterator -{ -public: - typedef std::bidirectional_iterator_tag category; - typedef C value_type; - typedef C &reference; - typedef C *pointer; - - list_iterator (C *p = 0) : mp_p (p) { } - list_iterator operator++ () { mp_p = static_cast (mp_p->mp_next); return *this; } - list_iterator operator-- () { mp_p = static_cast (mp_p->mp_prev); return *this; } - - C *operator-> () const - { - return mp_p; - } - - C &operator* () const - { - return *mp_p; - } - - bool operator== (list_iterator other) const { return mp_p == other.mp_p; } - bool operator!= (list_iterator other) const { return mp_p != other.mp_p; } - -private: - C *mp_p; -}; - -/** - * @brief A reverse iterator for the linked list - */ -template -class reverse_list_iterator -{ -public: - typedef std::bidirectional_iterator_tag category; - typedef C value_type; - typedef C &reference; - typedef C *pointer; - - reverse_list_iterator (C *p = 0) : mp_p (p) { } - reverse_list_iterator operator++ () { mp_p = static_cast (mp_p->mp_prev); return *this; } - reverse_list_iterator operator-- () { mp_p = static_cast (mp_p->mp_next); return *this; } - - C *operator-> () const - { - return mp_p; - } - - C &operator* () const - { - return *mp_p; - } - - bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; } - bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; } - -private: - C *mp_p; -}; - /** * @brief A linked list * @@ -448,12 +575,10 @@ class list : public list_impl { public: - typedef list_iterator iterator; - typedef list_iterator const_iterator; - typedef reverse_list_iterator reverse_iterator; - typedef reverse_list_iterator const_reverse_iterator; - - typedef C value_type; + typedef typename list_impl::iterator iterator; + typedef typename list_impl::const_iterator const_iterator; + typedef typename list_impl::reverse_iterator reverse_iterator; + typedef typename list_impl::const_reverse_iterator const_reverse_iterator; using list_impl::first; using list_impl::last; diff --git a/src/tl/tl/tlTimer.cc b/src/tl/tl/tlTimer.cc index d2fa1ba4c..3f74bc4bd 100644 --- a/src/tl/tl/tlTimer.cc +++ b/src/tl/tl/tlTimer.cc @@ -98,14 +98,17 @@ static int64_t ns_time () #elif defined(_MSC_VER) - FILETIME ft; - GetSystemTimeAsFileTime (&ft); + static LARGE_INTEGER freq = { 0 }; - uint64_t t = (uint64_t (ft.dwHighDateTime) << (sizeof (ft.dwHighDateTime) * 8)) | uint64_t (ft.dwLowDateTime); - t -= ft_to_epoch_offset; + if (freq.QuadPart == 0) { + QueryPerformanceFrequency (&freq); + tl_assert (freq.QuadPart > 0); + } - // FILETIME uses 100ns resolution, hence multiply with 100 to get ns: - return int64_t (t) * 100; + LARGE_INTEGER qpc; + QueryPerformanceCounter (&qpc); + + return int64_t (double (qpc.QuadPart) / double (freq.QuadPart) * 1e9 + 0.5); #else diff --git a/src/tl/unit_tests/tlListTests.cc b/src/tl/unit_tests/tlListTests.cc index 06567205d..b0feeb12e 100644 --- a/src/tl/unit_tests/tlListTests.cc +++ b/src/tl/unit_tests/tlListTests.cc @@ -403,3 +403,70 @@ TEST(2_BasicNoCopy) EXPECT_EQ (obj_count, size_t (0)); // mc2 gone as well } + +TEST(3_Insert) +{ + obj_count = 0; + + tl::list l1; + tl::list::iterator i1; + + EXPECT_EQ (l1.empty (), true); + EXPECT_EQ (l1.size (), size_t (0)); + EXPECT_EQ (l2s (l1), ""); + + l1.push_back (MyClass1 (42)); + EXPECT_EQ (l2s (l1), "42"); + EXPECT_EQ (l1.size (), size_t (1)); + + i1 = l1.insert_before (l1.end (), MyClass1 (17)); + EXPECT_EQ (l2s (l1), "42,17"); + EXPECT_EQ (i1->n, 17); + EXPECT_EQ (l1.size (), size_t (2)); + + i1 = l1.insert_before (i1, MyClass1 (11)); + EXPECT_EQ (l2s (l1), "42,11,17"); + EXPECT_EQ (i1->n, 11); + EXPECT_EQ (l1.size (), size_t (3)); + + i1 = l1.insert (i1, MyClass1 (12)); + EXPECT_EQ (l2s (l1), "42,11,12,17"); + EXPECT_EQ (i1->n, 12); + EXPECT_EQ (l1.size (), size_t (4)); + + MyClass1 arr[3] = { MyClass1 (1), MyClass1 (2), MyClass1 (3) }; + + i1 = l1.insert (i1, arr + 0, arr + 0); + EXPECT_EQ (l2s (l1), "42,11,12,17"); + EXPECT_EQ (i1->n, 12); + EXPECT_EQ (l1.size (), size_t (4)); + + i1 = l1.insert (i1, arr + 0, arr + 3); + EXPECT_EQ (l2s (l1), "42,11,12,1,2,3,17"); + EXPECT_EQ (i1->n, 1); + EXPECT_EQ (l1.size (), size_t (7)); + + l1.clear (); + l1.push_back (MyClass1 (42)); + i1 = l1.insert_before (l1.end (), MyClass1 (17)); + EXPECT_EQ (l2s (l1), "42,17"); + EXPECT_EQ (i1->n, 17); + EXPECT_EQ (l1.size (), size_t (2)); + + i1 = l1.insert_before (i1, arr + 0, arr + 0); + EXPECT_EQ (l2s (l1), "42,17"); + EXPECT_EQ (i1->n, 17); + EXPECT_EQ (l1.size (), size_t (2)); + + i1 = l1.insert_before (i1, arr + 0, arr + 3); + EXPECT_EQ (l2s (l1), "42,1,2,3,17"); + EXPECT_EQ (i1->n, 1); + EXPECT_EQ (l1.size (), size_t (5)); + + // test erase range + l1.erase (i1, l1.end ()); + EXPECT_EQ (l2s (l1), "42"); + EXPECT_EQ (l1.size (), size_t (1)); +} + +