@@ -81,49 +81,57 @@ std::unique_ptr<List::Node> *List::ownerAt(unsigned int index) {
8181 return owner;
8282}
8383
84- void List::connectNodes (unsigned int index1, unsigned int index2) {
85- if (index1 == index2 || index1 >= count || index2 >= count) {
86- throw std::out_of_range{" Index out of range!" };
87- }
88-
89- if (index1 < index2) {
90- auto *owner1 = ownerAt (index1);
91- auto *owner2 = ownerAt (index2);
92- if (!owner1 || !owner2) {
93- throw std::out_of_range{" Index out of range!" };
94- }
95- Node *node1 = owner1->get ();
96- Node *node2 = owner2->get ();
97- if (!node1 || !node2) {
98- throw std::out_of_range{" Index out of range!" };
84+ void List::connectNodes (unsigned int index1, unsigned int index2)
85+ {
86+ if (index1 == index2 || index1 >= count || index2 >= count) {
87+ throw std::out_of_range{" Index out of range!" };
9988 }
100- if (node1->next .get () == node2) {
101- return ;
102- }
103- auto moving = std::move (*owner2);
104- *owner2 = std::move (moving->next );
105- moving->next = std::move (node1->next );
106- node1->next = std::move (moving);
107- return ;
108- }
10989
110- auto *owner2 = ownerAt (index2);
111- if (!owner2) {
112- throw std::out_of_range{" Index out of range!" };
113- }
114- auto moving = std::move (*owner2);
115- *owner2 = std::move (moving->next );
90+ auto requireOwner = [&](unsigned int idx) {
91+ if (auto * o = ownerAt (idx)) return o;
92+ throw std::out_of_range{" Index out of range!" };
93+ };
94+
95+ auto detachAt = [&](unsigned int idx) -> std::unique_ptr<Node> {
96+ auto * owner = requireOwner (idx); // owner points to the unique_ptr that owns node idx
97+ auto moving = std::move (*owner); // take node idx
98+ *owner = std::move (moving->next ); // owner now owns the remainder
99+ moving->next = nullptr ; // optional: make it explicit it's detached
100+ return moving;
101+ };
102+
103+ auto insertAfter = [&](unsigned int idx, std::unique_ptr<Node> moving) {
104+ auto * owner = requireOwner (idx);
105+ Node* node = owner->get ();
106+ if (!node) throw std::out_of_range{" Index out of range!" };
107+
108+ moving->next = std::move (node->next );
109+ node->next = std::move (moving);
110+ };
111+
112+ // - if index1 < index2: move node at index2 after node at index1, unless already adjacent
113+ // - else: move node at index2 after node at (index1 - 1)
114+ if (index1 < index2) {
115+ auto * owner1 = requireOwner (index1);
116+ auto * owner2 = requireOwner (index2);
117+
118+ Node* node1 = owner1->get ();
119+ Node* node2 = owner2->get ();
120+ if (!node1 || !node2) throw std::out_of_range{" Index out of range!" };
121+
122+ if (node1->next .get () == node2) {
123+ return ; // already connected in desired way
124+ }
125+
126+ insertAfter (index1, detachAt (index2));
127+ return ;
128+ }
116129
117- auto *owner1 = ownerAt (index1 - 1 );
118- if (!owner1) {
119- throw std::out_of_range{" Index out of range!" };
120- }
121- Node *node1 = owner1->get ();
122- if (!node1) {
123- throw std::out_of_range{" Index out of range!" };
124- }
125- moving->next = std::move (node1->next );
126- node1->next = std::move (moving);
130+ // index1 > index2
131+ if (index1 == 0 ) { // defensive: would underflow (even though bounds might already prevent it)
132+ throw std::out_of_range{" Index out of range!" };
133+ }
134+ insertAfter (index1 - 1 , detachAt (index2));
127135}
128136
129137void List::print () const {
0 commit comments