diff --git a/.gitignore b/.gitignore index 4eda7252..2fb15355 100644 --- a/.gitignore +++ b/.gitignore @@ -377,3 +377,6 @@ test/syntax_check/c++11/bgcc test/syntax_check/c++17/bgcc test/syntax_check/c++20/bgcc test/vs2022/Debug MSVC C++17 +test/vs2022/Debug MSVC C++17 - No STL +test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 +test/vs2022/Release MSVC C++20 - Optimised O2 diff --git a/include/etl/intrusive_links.h b/include/etl/intrusive_links.h index 32551aec..cf17ff1e 100644 --- a/include/etl/intrusive_links.h +++ b/include/etl/intrusive_links.h @@ -91,56 +91,97 @@ namespace etl ID = ID_, }; + //*********************************** forward_link() : etl_next(ETL_NULLPTR) { } + //*********************************** forward_link(const forward_link& other) : etl_next(other.etl_next) { } - forward_link& operator =(const forward_link& rhs) + //*********************************** + forward_link& operator =(const forward_link& other) { - etl_next = rhs.etl_next; + etl_next = other.etl_next; + return *this; } + //*********************************** void clear() { etl_next = ETL_NULLPTR; } + //*********************************** + ETL_NODISCARD bool is_linked() const { return etl_next != ETL_NULLPTR; } + //*********************************** + ETL_NODISCARD + bool has_next() const + { + return etl_next != ETL_NULLPTR; + } + + //*********************************** + void set_next(forward_link* n) + { + etl_next = n; + } + + //*********************************** + void set_next(forward_link& n) + { + etl_next = &n; + } + + //*********************************** + ETL_NODISCARD + forward_link* get_next() const + { + return etl_next; + } + forward_link* etl_next; }; + //*********************************** + template + struct is_forward_link + { + static ETL_CONSTANT bool value = etl::is_same >::value; + }; + + //*********************************** +#if ETL_USING_CPP17 + template + inline constexpr bool is_forward_link_v = etl::is_forward_link::value; +#endif + + //*************************************************************************** + // link + //*************************************************************************** // Reference, Reference template - typename etl::enable_if >::value, void>::type - link(TLink& lhs, TLink& rhs) + typename etl::enable_if::value, void>::type + link(TLink& lhs, TLink& rhs) { lhs.etl_next = &rhs; } - // Reference, Reference - template - typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink& rhs) - { - rhs.etl_next = lhs.etl_next; - lhs.etl_next = &rhs; - } - + //*********************************** // Pointer, Pointer template - typename etl::enable_if >::value, void>::type - link(TLink* lhs, TLink* rhs) + typename etl::enable_if::value, void>::type + link(TLink* lhs, TLink* rhs) { if (lhs != ETL_NULLPTR) { @@ -148,42 +189,44 @@ namespace etl } } - // Reference + //*********************************** + // Reference, Pointer template - typename etl::enable_if >::value, void>::type - link_clear(TLink& node) + typename etl::enable_if::value, void>::type + link(TLink& lhs, TLink* rhs) { - node.clear(); + lhs.etl_next = rhs; } - // Pointer + //*********************************** + // Pointer, Reference template - typename etl::enable_if >::value, void>::type - link_clear(TLink* node) + typename etl::enable_if::value, void>::type + link(TLink* lhs, TLink& rhs) { - node->clear(); + if (lhs != ETL_NULLPTR) + { + lhs->etl_next = &rhs; + } } - // Reference + //*************************************************************************** + // link_splice + //*************************************************************************** + // Reference, Reference template - typename etl::enable_if >::value, bool>::type - link_is_linked(TLink& node) + typename etl::enable_if::value, void>::type + link_splice(TLink& lhs, TLink& rhs) { - return node.is_linked(); - } - - // Pointer - template - typename etl::enable_if >::value, bool>::type - link_is_linked(TLink* node) - { - return node.is_linked(); + rhs.etl_next = lhs.etl_next; + lhs.etl_next = &rhs; } + //*********************************** // Pointer, Pointer template - typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink* rhs) + typename etl::enable_if::value, void>::type + link_splice(TLink* lhs, TLink* rhs) { if (lhs != ETL_NULLPTR) { @@ -196,18 +239,11 @@ namespace etl } } + //*********************************** // Reference, Pointer template - typename etl::enable_if >::value, void>::type - link(TLink& lhs, TLink* rhs) - { - lhs.etl_next = rhs; - } - - // Reference, Pointer - template - typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink* rhs) + typename etl::enable_if::value, void>::type + link_splice(TLink& lhs, TLink* rhs) { if (rhs != ETL_NULLPTR) { @@ -217,21 +253,11 @@ namespace etl lhs.etl_next = rhs; } + //*********************************** // Pointer, Reference template - typename etl::enable_if >::value, void>::type - link(TLink* lhs, TLink& rhs) - { - if (lhs != ETL_NULLPTR) - { - lhs->etl_next = &rhs; - } - } - - // Pointer, Reference - template - typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink& rhs) + typename etl::enable_if::value, void>::type + link_splice(TLink* lhs, TLink& rhs) { if (lhs != ETL_NULLPTR) { @@ -240,19 +266,21 @@ namespace etl } } + //*********************************** // Reference, Reference, Reference template - typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink& first, TLink& last) + typename etl::enable_if::value, void>::type + link_splice(TLink& lhs, TLink& first, TLink& last) { last.etl_next = lhs.etl_next; lhs.etl_next = &first; } + //*********************************** // Pointer, Reference, Reference template - typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink& first, TLink& last) + typename etl::enable_if::value, void>::type + link_splice(TLink* lhs, TLink& first, TLink& last) { if (lhs != ETL_NULLPTR) { @@ -265,10 +293,13 @@ namespace etl } } + //*************************************************************************** + // unlink_after + //*************************************************************************** // Reference template - typename etl::enable_if >::value, void>::type - unlink_after(TLink& node) + typename etl::enable_if::value, void>::type + unlink_after(TLink& node) { if (node.etl_next != ETL_NULLPTR) { @@ -277,12 +308,47 @@ namespace etl } } + //*********************************** // Reference, Reference template - typename etl::enable_if >::value, void>::type - unlink_after(TLink& before, TLink& last) + typename etl::enable_if::value, TLink*>::type + unlink_after(TLink& before, TLink& last) { - before.etl_next = last.etl_next; + TLink* first = before.etl_next; + + if (&before != &last) + { + before.etl_next = last.etl_next; + } + + return first; + } + + //*************************************************************************** + // link_clear_range + //*************************************************************************** + // Reference + template + typename etl::enable_if::value, void>::type + link_clear_range(TLink& start) + { + TLink* current = &start; + + while (current != ETL_NULLPTR) + { + TLink* next = current->etl_next; + current->clear(); + current = next; + } + } + + //*********************************** + // Pointer + template + typename etl::enable_if::value, void>::type + link_clear_range(TLink* start) + { + etl::link_clear_range(*start); } //*************************************************************************** @@ -296,93 +362,154 @@ namespace etl ID = ID_, }; + //*********************************** bidirectional_link() : etl_previous(ETL_NULLPTR) , etl_next(ETL_NULLPTR) { } + //*********************************** bidirectional_link(const bidirectional_link& other) : etl_previous(other.etl_previous) , etl_next(other.etl_next) { } - bidirectional_link& operator =(const bidirectional_link& rhs) + //*********************************** + bidirectional_link& operator =(const bidirectional_link& other) { - etl_previous = rhs.etl_previous; - etl_next = rhs.etl_next; + etl_previous = other.etl_previous; + etl_next = other.etl_next; + return *this; } + //*********************************** void clear() { etl_previous = ETL_NULLPTR; etl_next = ETL_NULLPTR; } + //*********************************** + ETL_NODISCARD bool is_linked() const { return (etl_previous != ETL_NULLPTR) || (etl_next != ETL_NULLPTR); } + //*********************************** + ETL_NODISCARD + bool has_next() const + { + return etl_next != ETL_NULLPTR; + } + + //*********************************** + ETL_NODISCARD + bool has_previous() const + { + return etl_previous != ETL_NULLPTR; + } + + //*********************************** + void set_next(bidirectional_link* n) + { + etl_next = n; + } + + //*********************************** + void set_next(bidirectional_link& n) + { + etl_next = &n; + } + + //*********************************** + ETL_NODISCARD + bidirectional_link* get_next() const + { + return etl_next; + } + + //*********************************** + void set_previous(bidirectional_link* n) + { + etl_previous = n; + } + + //*********************************** + void set_previous(bidirectional_link& n) + { + etl_previous = &n; + } + + //*********************************** + ETL_NODISCARD + bidirectional_link* get_previous() const + { + return etl_previous; + } + + //*********************************** void reverse() { using ETL_OR_STD::swap; // Allow ADL - swap(etl_previous, etl_next); } + //*********************************** + void unlink() + { + // Connect the previous link with the next. + if (etl_previous != ETL_NULLPTR) + { + etl_previous->etl_next = etl_next; + } + + // Connect the next link with the previous. + if (etl_next != ETL_NULLPTR) + { + etl_next->etl_previous = etl_previous; + } + + clear(); + } + bidirectional_link* etl_previous; bidirectional_link* etl_next; - - void unlink() - { - // Connect the previous link with the next. - if (etl_previous != ETL_NULLPTR) - { - etl_previous->etl_next = etl_next; - } - - // Connect the next link with the previous. - if (etl_next != ETL_NULLPTR) - { - etl_next->etl_previous = etl_previous; - } - - clear(); - } }; + //*********************************** + template + struct is_bidirectional_link + { + static ETL_CONSTANT bool value = etl::is_same >::value; + }; + + //*********************************** +#if ETL_USING_CPP17 + template + inline constexpr bool is_bidirectional_link_v = etl::is_bidirectional_link::value; +#endif + + //*************************************************************************** + // link + //*************************************************************************** // Reference, Reference template typename etl::enable_if >::value, void>::type - link(TLink& lhs, TLink& rhs) + link(TLink& lhs, TLink& rhs) { lhs.etl_next = &rhs; rhs.etl_previous = &lhs; } - // Reference, Reference - template - typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink& rhs) - { - rhs.etl_next = lhs.etl_next; - rhs.etl_previous = &lhs; - - if (lhs.etl_next != ETL_NULLPTR) - { - lhs.etl_next->etl_previous = &rhs; - } - - lhs.etl_next = &rhs; - } - + //*********************************** // Pointer, Pointer template typename etl::enable_if >::value, void>::type - link(TLink* lhs, TLink* rhs) + link(TLink* lhs, TLink* rhs) { if (lhs != ETL_NULLPTR) { @@ -395,10 +522,58 @@ namespace etl } } + //*********************************** + // Reference, Pointer + template + typename etl::enable_if >::value, void>::type + link(TLink& lhs, TLink* rhs) + { + lhs.etl_next = rhs; + + if (rhs != ETL_NULLPTR) + { + rhs->etl_previous = &lhs; + } + } + + //*********************************** + // Pointer, Reference + template + typename etl::enable_if >::value, void>::type + link(TLink* lhs, TLink& rhs) + { + if (lhs != ETL_NULLPTR) + { + lhs->etl_next = &rhs; + } + + rhs.etl_previous = lhs; + } + + //*********************************** + // Reference, Reference + template + typename etl::enable_if >::value, void>::type + link_splice(TLink& lhs, TLink& rhs) + { + rhs.etl_next = lhs.etl_next; + rhs.etl_previous = &lhs; + + if (lhs.etl_next != ETL_NULLPTR) + { + lhs.etl_next->etl_previous = &rhs; + } + + lhs.etl_next = &rhs; + } + + //*************************************************************************** + // link_splice + //*************************************************************************** // Pointer, Pointer template typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink* rhs) + link_splice(TLink* lhs, TLink* rhs) { if (rhs != ETL_NULLPTR) { @@ -421,27 +596,15 @@ namespace etl } } + //*********************************** // Reference, Pointer template typename etl::enable_if >::value, void>::type - link(TLink& lhs, TLink* rhs) - { - lhs.etl_next = rhs; - - if (rhs != ETL_NULLPTR) - { - rhs->etl_previous = &lhs; - } - } - - // Reference, Pointer - template - typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink* rhs) + link_splice(TLink& lhs, TLink* rhs) { if (rhs != ETL_NULLPTR) { - rhs->etl_next = lhs.etl_next; + rhs->etl_next = lhs.etl_next; rhs->etl_previous = &lhs; } @@ -453,23 +616,11 @@ namespace etl lhs.etl_next = rhs; } + //*********************************** // Pointer, Reference template typename etl::enable_if >::value, void>::type - link(TLink* lhs, TLink& rhs) - { - if (lhs != ETL_NULLPTR) - { - lhs->etl_next = &rhs; - } - - rhs.etl_previous = lhs; - } - - // Pointer, Reference - template - typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink& rhs) + link_splice(TLink* lhs, TLink& rhs) { if (lhs != ETL_NULLPTR) { @@ -489,10 +640,11 @@ namespace etl } } + //*********************************** // Reference, Reference, Reference template typename etl::enable_if >::value, void>::type - link_splice(TLink& lhs, TLink& first, TLink& last) + link_splice(TLink& lhs, TLink& first, TLink& last) { last.etl_next = lhs.etl_next; first.etl_previous = &lhs; @@ -505,10 +657,11 @@ namespace etl lhs.etl_next = &first; } + //*********************************** // Pointer, Reference, Reference template typename etl::enable_if >::value, void>::type - link_splice(TLink* lhs, TLink& first, TLink& last) + link_splice(TLink* lhs, TLink& first, TLink& last) { if (lhs != ETL_NULLPTR) { @@ -532,50 +685,22 @@ namespace etl } } + //*************************************************************************** + // unlink + //*************************************************************************** // Reference template typename etl::enable_if >::value, void>::type - link_clear(TLink& node) - { - node.clear(); - } - - // Pointer - template - typename etl::enable_if >::value, void>::type - link_clear(TLink* node) - { - node->clear(); - } - - // Reference - template - typename etl::enable_if >::value, bool>::type - link_is_linked(TLink& node) - { - return node.is_linked(); - } - - // Pointer - template - typename etl::enable_if >::value, bool>::type - link_is_linked(TLink* node) - { - return node.is_linked(); - } - - // Reference - template - typename etl::enable_if >::value, void>::type - unlink(TLink& node) + unlink(TLink& node) { node.unlink(); } + //*********************************** // Reference Reference template - typename etl::enable_if >::value, void>::type - unlink(TLink& first, TLink& last) + typename etl::enable_if >::value, TLink&>::type + unlink(TLink& first, TLink& last) { if (&first == &last) { @@ -592,7 +717,39 @@ namespace etl { first.etl_previous->etl_next = last.etl_next; } + + first.etl_previous = ETL_NULLPTR; + last.etl_next = ETL_NULLPTR; } + + return first; + } + + //*************************************************************************** + // link_clear_range + //*************************************************************************** + // Reference + template + typename etl::enable_if >::value, void>::type + link_clear_range(TLink& start) + { + TLink* current = &start; + + while (current != ETL_NULLPTR) + { + TLink* next = current->etl_next; + current->clear(); + current = next; + } + } + + //*********************************** + // Pointer + template + typename etl::enable_if >::value, void>::type + link_clear_range(TLink* start) + { + etl::link_clear_range(*start); } //*************************************************************************** @@ -606,6 +763,7 @@ namespace etl ID = ID_, }; + //*********************************** tree_link() : etl_parent(ETL_NULLPTR) , etl_left(ETL_NULLPTR) @@ -613,6 +771,7 @@ namespace etl { } + //*********************************** tree_link(const tree_link& other) : etl_parent(other.etl_parent) , etl_left(other.etl_left) @@ -620,14 +779,17 @@ namespace etl { } - tree_link& operator =(const tree_link& rhs) + //*********************************** + tree_link& operator =(const tree_link& other) { etl_parent = other.etl_parent; etl_left = other.etl_left; etl_right = other.etl_right; + return *this; } + //*********************************** void clear() { etl_parent = ETL_NULLPTR; @@ -635,37 +797,133 @@ namespace etl etl_right = ETL_NULLPTR; } + //*********************************** bool is_linked() const { return (etl_parent != ETL_NULLPTR) || (etl_left != ETL_NULLPTR) || (etl_right != ETL_NULLPTR); } + //*********************************** + ETL_NODISCARD + bool has_parent() const + { + return etl_parent != ETL_NULLPTR; + } + + //*********************************** + ETL_NODISCARD + bool has_left() const + { + return etl_left != ETL_NULLPTR; + } + + //*********************************** + ETL_NODISCARD + bool has_right() const + { + return etl_right != ETL_NULLPTR; + } + + //*********************************** + void set_parent(tree_link* p) + { + etl_parent = p; + } + + //*********************************** + void set_left(tree_link* l) + { + etl_left = l; + } + + //*********************************** + void set_right(tree_link* r) + { + etl_right = r; + } + + //*********************************** + void set_parent(tree_link& p) + { + etl_parent = &p; + } + + //*********************************** + void set_left(tree_link& l) + { + etl_left = &l; + } + + //*********************************** + void set_right(tree_link& r) + { + etl_right = &r; + } + + //*********************************** + ETL_NODISCARD + tree_link* get_parent() const + { + return etl_parent; + } + + //*********************************** + ETL_NODISCARD + tree_link* get_left() const + { + return etl_left; + } + + //*********************************** + ETL_NODISCARD + tree_link* get_right() const + { + return etl_right; + } + + //*********************************** + void mirror() + { + using ETL_OR_STD::swap; + swap(etl_left, etl_right); + } + tree_link* etl_parent; tree_link* etl_left; tree_link* etl_right; }; + //*********************************** + template + struct is_tree_link + { + static ETL_CONSTANT bool value = etl::is_same >::value; + }; + + //*********************************** +#if ETL_USING_CPP17 + template + inline constexpr bool is_tree_link_v = etl::is_tree_link::value; +#endif + + //*************************************************************************** + // link_left + // Sets the left link. + //*************************************************************************** // Reference, Reference template typename etl::enable_if >::value, void>::type - link_left(TLink& parent, TLink& leaf) + link_left(TLink& parent, TLink& leaf) { parent.etl_left = &leaf; leaf.etl_parent = &parent; } - template - typename etl::enable_if >::value, void>::type - link_right(TLink& parent, TLink& leaf) - { - parent.etl_right = &leaf; - leaf.etl_parent = &parent; - } - + //*********************************** // Pointer, Pointer template typename etl::enable_if >::value, void>::type - link_left(TLink* parent, TLink* leaf) + link_left(TLink* parent, TLink* leaf) { if (parent != ETL_NULLPTR) { @@ -678,9 +936,50 @@ namespace etl } } + //*********************************** + // Reference, Pointer template typename etl::enable_if >::value, void>::type - link_right(TLink* parent, TLink* leaf) + link_left(TLink& parent, TLink* leaf) + { + parent.etl_left = leaf; + + if (leaf != ETL_NULLPTR) + { + leaf->etl_parent = &parent; + } + } + + //*********************************** + // Pointer, Reference + template + typename etl::enable_if >::value, void>::type + link_left(TLink* parent, TLink& leaf) + { + if (parent != ETL_NULLPTR) + { + parent->etl_left = &leaf; + } + + leaf.etl_parent = parent; + } + + //*************************************************************************** + // link_right + // Sets the right link. + //*************************************************************************** + template + typename etl::enable_if >::value, void>::type + link_right(TLink& parent, TLink& leaf) + { + parent.etl_right = &leaf; + leaf.etl_parent = &parent; + } + + //*********************************** + template + typename etl::enable_if >::value, void>::type + link_right(TLink* parent, TLink* leaf) { if (parent != ETL_NULLPTR) { @@ -693,22 +992,10 @@ namespace etl } } - // Reference, Pointer + //*********************************** template typename etl::enable_if >::value, void>::type - link_left(TLink& parent, TLink* leaf) - { - parent.etl_left = leaf; - - if (leaf != ETL_NULLPTR) - { - leaf->etl_parent = &parent; - } - } - - template - typename etl::enable_if >::value, void>::type - link_right(TLink& parent, TLink* leaf) + link_right(TLink& parent, TLink* leaf) { parent.etl_right = leaf; @@ -718,22 +1005,10 @@ namespace etl } } - // Pointer, Reference + //*********************************** template typename etl::enable_if >::value, void>::type - link_left(TLink* parent, TLink& leaf) - { - if (parent != ETL_NULLPTR) - { - parent->etl_left = &leaf; - } - - leaf.etl_parent = parent; - } - - template - typename etl::enable_if >::value, void>::type - link_right(TLink* parent, TLink& leaf) + link_right(TLink* parent, TLink& leaf) { if (parent != ETL_NULLPTR) { @@ -743,10 +1018,13 @@ namespace etl leaf.etl_parent = parent; } + //*************************************************************************** + // link_rotate_left + //*************************************************************************** // Reference, Reference template typename etl::enable_if >::value, void>::type - link_rotate_left(TLink& parent, TLink& leaf) + link_rotate_left(TLink& parent, TLink& leaf) { parent.etl_right = leaf.etl_left; @@ -760,9 +1038,48 @@ namespace etl leaf.etl_left = &parent; } + //*********************************** + // Pointer, Pointer template typename etl::enable_if >::value, void>::type - link_rotate_right(TLink& parent, TLink& leaf) + link_rotate_left(TLink* parent, TLink* leaf) + { + if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR)) + { + link_rotate_left(*parent, *leaf); + } + } + + //*********************************** + // Reference, Pointer + template + typename etl::enable_if >::value, void>::type + link_rotate_left(TLink& parent, TLink* leaf) + { + if (leaf != ETL_NULLPTR) + { + link_rotate_left(parent, *leaf); + } + } + + //*********************************** + // Pointer, Reference + template + typename etl::enable_if >::value, void>::type + link_rotate_left(TLink* parent, TLink& leaf) + { + if (parent != ETL_NULLPTR) + { + link_rotate_left(*parent, leaf); + } + } + + //*************************************************************************** + // link_rotate_right + //*************************************************************************** + template + typename etl::enable_if >::value, void>::type + link_rotate_right(TLink& parent, TLink& leaf) { parent.etl_left = leaf.etl_right; @@ -776,20 +1093,10 @@ namespace etl leaf.etl_right = &parent; } - // Pointer, Pointer + template typename etl::enable_if >::value, void>::type - link_rotate_left(TLink* parent, TLink* leaf) - { - if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR)) - { - link_rotate_left(*parent, *leaf); - } - } - - template - typename etl::enable_if >::value, void>::type - link_rotate_right(TLink* parent, TLink* leaf) + link_rotate_right(TLink* parent, TLink* leaf) { if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR)) { @@ -797,20 +1104,9 @@ namespace etl } } - // Reference, Pointer template typename etl::enable_if >::value, void>::type - link_rotate_left(TLink& parent, TLink* leaf) - { - if (leaf != ETL_NULLPTR) - { - link_rotate_left(parent, *leaf); - } - } - - template - typename etl::enable_if >::value, void>::type - link_rotate_right(TLink& parent, TLink* leaf) + link_rotate_right(TLink& parent, TLink* leaf) { if (leaf != ETL_NULLPTR) { @@ -818,20 +1114,10 @@ namespace etl } } - // Pointer, Reference + //*********************************** template typename etl::enable_if >::value, void>::type - link_rotate_left(TLink* parent, TLink& leaf) - { - if (parent != ETL_NULLPTR) - { - link_rotate_left(*parent, leaf); - } - } - - template - typename etl::enable_if >::value, void>::type - link_rotate_right(TLink* parent, TLink& leaf) + link_rotate_right(TLink* parent, TLink& leaf) { if (parent != ETL_NULLPTR) { @@ -839,11 +1125,14 @@ namespace etl } } + //*************************************************************************** + // link_rotate + //*************************************************************************** // Reference, Reference /// Automatically detects whether a left or right rotate is expected. template typename etl::enable_if >::value, void>::type - link_rotate(TLink& parent, TLink& leaf) + link_rotate(TLink& parent, TLink& leaf) { if (parent.etl_left == &leaf) { @@ -855,11 +1144,12 @@ namespace etl } } + //*********************************** // Pointer, Pointer /// Automatically detects whether a left or right rotate is expected. template typename etl::enable_if >::value, void>::type - link_rotate(TLink* parent, TLink* leaf) + link_rotate(TLink* parent, TLink* leaf) { if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR)) { @@ -874,11 +1164,12 @@ namespace etl } } + //*********************************** // Reference, Pointer /// Automatically detects whether a left or right rotate is expected. template typename etl::enable_if >::value, void>::type - link_rotate(TLink& parent, TLink* leaf) + link_rotate(TLink& parent, TLink* leaf) { if (leaf != ETL_NULLPTR) { @@ -893,11 +1184,12 @@ namespace etl } } + //*********************************** // Pointer, Reference /// Automatically detects whether a left or right rotate is expected. template typename etl::enable_if >::value, void>::type - link_rotate(TLink* parent, TLink& leaf) + link_rotate(TLink* parent, TLink& leaf) { if (parent != ETL_NULLPTR) { diff --git a/support/Release notes.txt b/support/Release notes.txt index 192d1e27..fd9fd08d 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,8 +1,11 @@ =============================================================================== 20.37.0 #708 Fix missing class key with friend. -#709 intrusive_list::iterator operator -> should not dereference pointer before return +#709 intrusive_list::iterator operator -> should not dereference pointer before return. #710 Calling accept on etl::variant visits a copy instead of the original object. +#711 Added etl::is_forward_link, etl::is_bidirectional_link and etl::is_tree_link to intrusive links. + Added Constructors, access and status member functions to intrusive links. +#712 Unable to use etl::optional with non-default-constructible POD objects. Modified etl::visitor to allow direct specification of the argument type. Added etl::is_visitor trait. diff --git a/test/test_intrusive_links.cpp b/test/test_intrusive_links.cpp index 1cacb3ab..829f1b19 100644 --- a/test/test_intrusive_links.cpp +++ b/test/test_intrusive_links.cpp @@ -157,6 +157,49 @@ namespace CHECK_EQUAL(0, pdata->value); } + //************************************************************************* + TEST(test_link_forward_link_get_set) + { + FData data0(0); + FData data1(1); + FData data2(2); + FData data3(3); + + // Use reference interface + data0.FLink0::set_next(data1); + data1.FLink0::set_next(data2); + data2.FLink0::set_next(data3); + data3.FLink0::clear(); + + CHECK(data0.FLink0::get_next() == &data1); + CHECK(data1.FLink0::get_next() == &data2); + CHECK(data2.FLink0::get_next() == &data3); + CHECK(data3.FLink0::get_next() == nullptr); + + // Use pointer interface + data3.FLink0::set_next(&data2); + data2.FLink0::set_next(&data1); + data1.FLink0::set_next(&data0); + data0.FLink0::set_next(nullptr); + + CHECK(data3.FLink0::get_next() == &data2); + CHECK(data2.FLink0::get_next() == &data1); + CHECK(data1.FLink0::get_next() == &data0); + CHECK(data0.FLink0::get_next() == nullptr); + } + + //************************************************************************* + TEST(test_link_forward_link_has_links) + { + FData data0(0); + FData data1(1); + + CHECK_FALSE(data0.FLink0::has_next()); + + data0.FLink0::set_next(data1); + CHECK_TRUE(data0.FLink0::has_next()); + } + //************************************************************************* TEST(test_link_splice_forward_link) { @@ -344,10 +387,13 @@ namespace etl::link(data1, data0); etl::link(data0, nullptr); - etl::unlink_after(data0, data2); - data1.FLink0::clear(); - data2.FLink0::clear(); - + FLink0* start = etl::unlink_after(data0, data2); + CHECK(data0.FLink0::etl_next == &data3); + CHECK(data1.FLink0::etl_next == &data2); + CHECK(data2.FLink0::etl_next == &data3); + CHECK(data3.FLink0::etl_next == nullptr); + + etl::link_clear_range(*start); CHECK(data0.FLink0::etl_next == &data3); CHECK(data1.FLink0::etl_next == nullptr); CHECK(data2.FLink0::etl_next == nullptr); @@ -491,6 +537,77 @@ namespace data2.BLink0::unlink(); } + //************************************************************************* + TEST(test_link_bidirectional_link_get_set) + { + BData data0(0); + BData data1(1); + BData data2(2); + BData data3(3); + + // Use reference interface + data0.BLink0::set_next(data1); + data1.BLink0::set_next(data2); + data2.BLink0::set_next(data3); + + data1.BLink0::set_previous(data0); + data2.BLink0::set_previous(data1); + data3.BLink0::set_previous(data2); + + CHECK(data0.BLink0::get_next() == &data1); + CHECK(data1.BLink0::get_next() == &data2); + CHECK(data2.BLink0::get_next() == &data3); + CHECK(data3.BLink0::get_next() == nullptr); + + CHECK(data3.BLink0::get_previous() == &data2); + CHECK(data2.BLink0::get_previous() == &data1); + CHECK(data1.BLink0::get_previous() == &data0); + CHECK(data0.BLink0::get_previous() == nullptr); + + // Use pointer interface + data0.BLink0::clear(); + data1.BLink0::clear(); + data2.BLink0::clear(); + data3.BLink0::clear(); + + data3.BLink0::set_next(&data2); + data2.BLink0::set_next(&data1); + data1.BLink0::set_next(&data0); + + data0.BLink0::set_previous(&data1); + data1.BLink0::set_previous(&data2); + data2.BLink0::set_previous(&data3); + + CHECK(data3.BLink0::get_next() == &data2); + CHECK(data2.BLink0::get_next() == &data1); + CHECK(data1.BLink0::get_next() == &data0); + CHECK(data0.BLink0::get_next() == nullptr); + + CHECK(data0.BLink0::get_previous() == &data1); + CHECK(data1.BLink0::get_previous() == &data2); + CHECK(data2.BLink0::get_previous() == &data3); + CHECK(data3.BLink0::get_previous() == nullptr); + } + + //************************************************************************* + TEST(test_link_bidirectional_link_has_links) + { + BData data0(0); + BData data1(1); + BData data2(2); + + CHECK_FALSE(data1.BLink0::has_previous()); + CHECK_FALSE(data1.BLink0::has_next()); + + data1.BLink0::set_previous(data0); + CHECK_TRUE(data1.BLink0::has_previous()); + CHECK_FALSE(data1.BLink0::has_next()); + + data1.BLink0::set_next(data2); + CHECK_TRUE(data1.BLink0::has_previous()); + CHECK_TRUE(data1.BLink0::has_next()); + } + //************************************************************************* TEST(test_link_splice_bidirectional_link) { @@ -932,6 +1049,82 @@ namespace CHECK(data3.TLink1::etl_right == nullptr); } + //************************************************************************* + TEST(test_link_tree_link_get_set) + { + TData dataParent(0); + TData dataNode(1); + TData dataLeft(2); + TData dataRight(3); + + // Use reference interface + dataNode.TLink0::set_parent(dataParent); + dataNode.TLink0::set_left(dataLeft); + dataNode.TLink0::set_right(dataRight); + + CHECK(dataNode.TLink0::get_parent() == &dataParent); + CHECK(dataNode.TLink0::get_left() == &dataLeft); + CHECK(dataNode.TLink0::get_right() == &dataRight); + + // Use pointer interface + dataNode.TLink0::clear(); + + dataNode.TLink0::set_parent(&dataParent); + dataNode.TLink0::set_left(&dataLeft); + dataNode.TLink0::set_right(&dataRight); + + CHECK(dataNode.TLink0::get_parent() == &dataParent); + CHECK(dataNode.TLink0::get_left() == &dataLeft); + CHECK(dataNode.TLink0::get_right() == &dataRight); + } + + //************************************************************************* + TEST(test_link_tree_link_has_links) + { + TData dataParent(0); + TData dataNode(1); + TData dataLeft(2); + TData dataRight(3); + + CHECK_FALSE(dataNode.TLink0::has_parent()); + CHECK_FALSE(dataNode.TLink0::has_left()); + CHECK_FALSE(dataNode.TLink0::has_right()); + + dataNode.TLink0::set_parent(dataParent); + CHECK_TRUE(dataNode.TLink0::has_parent()); + CHECK_FALSE(dataNode.TLink0::has_left()); + CHECK_FALSE(dataNode.TLink0::has_right()); + + dataNode.TLink0::set_left(dataLeft); + CHECK_TRUE(dataNode.TLink0::has_parent()); + CHECK_TRUE(dataNode.TLink0::has_left()); + CHECK_FALSE(dataNode.TLink0::has_right()); + + dataNode.TLink0::set_right(dataRight); + CHECK_TRUE(dataNode.TLink0::has_parent()); + CHECK_TRUE(dataNode.TLink0::has_left()); + CHECK_TRUE(dataNode.TLink0::has_right()); + } + + //************************************************************************* + TEST(test_link_tree_link_mirror) + { + TData dataParent(0); + TData dataNode(1); + TData dataLeft(2); + TData dataRight(3); + + dataNode.TLink0::set_parent(dataParent); + dataNode.TLink0::set_left(dataLeft); + dataNode.TLink0::set_right(dataRight); + + dataNode.TLink0::mirror(); + + CHECK(dataNode.TLink0::get_parent() == &dataParent); + CHECK(dataNode.TLink0::get_left() == &dataRight); + CHECK(dataNode.TLink0::get_right() == &dataLeft); + } + //************************************************************************* TEST(test_is_linked) { @@ -1044,13 +1237,13 @@ namespace CHECK(data3.FLink0::etl_next == nullptr); CHECK(data3.BLink1::etl_previous == nullptr); - CHECK(data3.BLink1::etl_next == &data2); + CHECK(data3.BLink1::etl_next == &data2); CHECK(data2.BLink1::etl_previous == &data3); - CHECK(data2.BLink1::etl_next == &data1); + CHECK(data2.BLink1::etl_next == &data1); CHECK(data1.BLink1::etl_previous == &data2); - CHECK(data1.BLink1::etl_next == &data0); + CHECK(data1.BLink1::etl_next == &data0); CHECK(data0.BLink1::etl_previous == &data1); - CHECK(data0.BLink1::etl_next == nullptr); + CHECK(data0.BLink1::etl_next == nullptr); CHECK(data0.TLink2::etl_left == &data1); CHECK(data0.TLink2::etl_right == &data2); diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index e04bc16e..d3ce830a 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1122,6 +1122,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + Default Console @@ -1242,6 +1243,7 @@ EditAndContinue /Zc:__cplusplus %(AdditionalOptions) true + Default Console @@ -12989,6 +12991,7 @@ + @@ -13295,80 +13298,6 @@ false false - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false false diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 214ba86b..94f86371 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1979,9 +1979,6 @@ Tests\Types - - Tests\Types - Tests\Types @@ -3416,6 +3413,9 @@ Tests\State Machines + + Tests\Containers + diff --git a/version.txt b/version.txt index 5649214d..75d012d0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.36.1 +20.37.0