diff --git a/src/List.cc b/src/List.cc index 8d70cc95c2..1f2e4ec410 100644 --- a/src/List.cc +++ b/src/List.cc @@ -114,3 +114,17 @@ TEST_CASE("plists") delete v; list.clear(); } + +TEST_CASE("unordered list operation") + { + List list({1, 2, 3, 4}); + CHECK(list.size() == 4); + + // An unordered list doesn't maintain the ordering of the elements when + // one is removed. It just swaps the last element into the hole. + list.remove(2); + CHECK(list.size() == 3); + CHECK(list[0] == 1); + CHECK(list[1] == 4); + CHECK(list[2] == 3); + } diff --git a/src/List.h b/src/List.h index 57d26c462b..55256b35fb 100644 --- a/src/List.h +++ b/src/List.h @@ -29,7 +29,9 @@ // TODO: this can be removed in v3.1 when List::sort() is removed typedef int (*list_cmp_func)(const void* v1, const void* v2); -template +enum list_order { LIST_ORDERED, LIST_UNORDERED }; + +template class List { public: @@ -195,13 +197,11 @@ public: bool remove(const T& a) // delete entry from list { - for ( int i = 0; i < num_entries; ++i ) + int pos = member_pos(a); + if ( pos != -1 ) { - if ( a == entries[i] ) - { - remove_nth(i); - return true; - } + remove_nth(pos); + return true; } return false; @@ -212,10 +212,22 @@ public: assert(n >=0 && n < num_entries); T old_ent = entries[n]; - --num_entries; - for ( ; n < num_entries; ++n ) - entries[n] = entries[n+1]; + // For data where we don't care about ordering, we don't care about keeping + // the list in the same order when removing an element. Just swap the last + // element with the element being removed. + if ( Order == LIST_ORDERED ) + { + --num_entries; + + for ( ; n < num_entries; ++n ) + entries[n] = entries[n+1]; + } + else + { + entries[n] = entries[num_entries - 1]; + --num_entries; + } return old_ent; } @@ -332,8 +344,8 @@ protected: // Specialization of the List class to store pointers of a type. -template -using PList = List; +template +using PList = List; // Popular type of list: list of strings. typedef PList name_list;