/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Assertions.h" #include "mozilla/DoublyLinkedList.h" using mozilla::DoublyLinkedList; using mozilla::DoublyLinkedListElement; struct SomeClass : public DoublyLinkedListElement { unsigned int mValue; explicit SomeClass(int aValue) : mValue(aValue) {} void incr() { ++mValue; } bool operator==(const SomeClass& other) { return mValue == other.mValue; } }; template static void CheckListValues(ListType& list, unsigned int (&values)[N]) { size_t count = 0; for (auto& x : list) { MOZ_RELEASE_ASSERT(x.mValue == values[count]); ++count; } MOZ_RELEASE_ASSERT(count == N); } static void TestDoublyLinkedList() { DoublyLinkedList list; SomeClass one(1), two(2), three(3); MOZ_RELEASE_ASSERT(list.isEmpty()); MOZ_RELEASE_ASSERT(!list.begin()); MOZ_RELEASE_ASSERT(!list.end()); for (SomeClass& x : list) { MOZ_RELEASE_ASSERT(x.mValue); MOZ_RELEASE_ASSERT(false); } list.pushFront(&one); { unsigned int check[] { 1 }; CheckListValues(list, check); } MOZ_RELEASE_ASSERT(list.contains(one)); MOZ_RELEASE_ASSERT(!list.contains(two)); MOZ_RELEASE_ASSERT(!list.contains(three)); MOZ_RELEASE_ASSERT(!list.isEmpty()); MOZ_RELEASE_ASSERT(list.begin()->mValue == 1); MOZ_RELEASE_ASSERT(!list.end()); list.pushFront(&two); { unsigned int check[] { 2, 1 }; CheckListValues(list, check); } MOZ_RELEASE_ASSERT(list.begin()->mValue == 2); MOZ_RELEASE_ASSERT(!list.end()); MOZ_RELEASE_ASSERT(!list.contains(three)); list.pushBack(&three); { unsigned int check[] { 2, 1, 3 }; CheckListValues(list, check); } MOZ_RELEASE_ASSERT(list.begin()->mValue == 2); MOZ_RELEASE_ASSERT(!list.end()); list.remove(&one); { unsigned int check[] { 2, 3 }; CheckListValues(list, check); } list.insertBefore(list.find(three), &one); { unsigned int check[] { 2, 1, 3 }; CheckListValues(list, check); } list.remove(&three); { unsigned int check[] { 2, 1 }; CheckListValues(list, check); } list.insertBefore(list.find(two), &three); { unsigned int check[] { 3, 2, 1 }; CheckListValues(list, check); } list.remove(&three); { unsigned int check[] { 2, 1 }; CheckListValues(list, check); } list.insertBefore(++list.find(two), &three); { unsigned int check[] { 2, 3, 1 }; CheckListValues(list, check); } list.remove(&one); { unsigned int check[] { 2, 3 }; CheckListValues(list, check); } list.remove(&two); { unsigned int check[] { 3 }; CheckListValues(list, check); } list.insertBefore(list.find(three), &two); { unsigned int check[] { 2, 3 }; CheckListValues(list, check); } list.remove(&three); { unsigned int check[] { 2 }; CheckListValues(list, check); } list.remove(&two); MOZ_RELEASE_ASSERT(list.isEmpty()); list.pushBack(&three); { unsigned int check[] { 3 }; CheckListValues(list, check); } list.pushFront(&two); { unsigned int check[] { 2, 3 }; CheckListValues(list, check); } // This should modify the values of |two| and |three| as pointers to them are // stored in the list, not copies. for (SomeClass& x : list) { x.incr(); } MOZ_RELEASE_ASSERT(*list.begin() == two); MOZ_RELEASE_ASSERT(*++list.begin() == three); SomeClass four(4); MOZ_RELEASE_ASSERT(++list.begin() == list.find(four)); } struct InTwoLists { explicit InTwoLists(unsigned int aValue) : mValue(aValue) {} DoublyLinkedListElement mListOne; DoublyLinkedListElement mListTwo; unsigned int mValue; struct GetListOneTrait { static DoublyLinkedListElement& Get(InTwoLists *aThis) { return aThis->mListOne; } }; }; namespace mozilla { template<> struct GetDoublyLinkedListElement { static DoublyLinkedListElement& Get(InTwoLists* aThis) { return aThis->mListTwo; } }; } static void TestCustomAccessor() { DoublyLinkedList listOne; DoublyLinkedList listTwo; InTwoLists one(1); InTwoLists two(2); listOne.pushBack(&one); listOne.pushBack(&two); { unsigned int check[] { 1, 2 }; CheckListValues(listOne, check); } listTwo.pushBack(&one); listTwo.pushBack(&two); { unsigned int check[] { 1, 2 }; CheckListValues(listOne, check); } { unsigned int check[] { 1, 2 }; CheckListValues(listTwo, check); } (void)listTwo.popBack(); { unsigned int check[] { 1, 2 }; CheckListValues(listOne, check); } { unsigned int check[] { 1 }; CheckListValues(listTwo, check); } (void)listOne.popBack(); { unsigned int check[] { 1 }; CheckListValues(listOne, check); } { unsigned int check[] { 1 }; CheckListValues(listTwo, check); } } int main() { TestDoublyLinkedList(); TestCustomAccessor(); return 0; }