Skip to content

List

Description

Double linked list.

Fields

Name Description
head Reference to head node of linked list.
tail Reference to tail node of linked list.
copy_init A user-provided type-specific method to initialize copies of types.
copy_deinit A user-provided type-specific method deinitialize already created copies of types.
length Length of this linked list.

Usage example (Cross-references)

Usage examples (Cross-references)
    /// merge primitives consumed by the typed `List(T)` macros.
    
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Std/Memory.h>
        }
        if (start + count > list->length) {
            LOG_FATAL("List range out of bounds.");
        }
    static void validate_list_structural(const GenericList *l) {
        if (!l->allocator) {
            LOG_FATAL("List allocator pointer is NULL.");
        }
        if (!l->allocator->allocate || !l->allocator->resize || !l->allocator->remap || !l->allocator->deallocate) {
            }
            if (l->head->prev) {
                LOG_FATAL("List head must not have a previous node.");
            }
            if (l->tail->next) {
            }
            if (l->tail->next) {
                LOG_FATAL("List tail must not have a next node.");
            }
        }
    void validate_list(const GenericList *l) {
        if (!l) {
            LOG_FATAL("List pointer is NULL.");
        }
        if (!MAGIC_MATCHES(l->__magic, LIST_MAGIC)) {
    #include "../Harness.h"
    #include "ListInt.h"
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    #define FUZZ_LIST_INT_H
    
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Types.h>
    
    // List(i32) typedef
    typedef List(i32) IntList;
    
    // List(i32) function enumeration
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        typedef List(int) LI;
        LI li = ListInit(ALLOCATOR_OF(&alloc));
        ListForeach(&li, i) {
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    
    static bool test_list_init_variants(void) {
        WriteFmt("Testing List init variants\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list_a = ListInit(&alloc);
        IntList list_b = ListInitT(list_b, &alloc);
    
    static bool test_list_init_optional_allocator(void) {
        WriteFmt("Testing List init optional allocator\n");
    
        typedef List(int) IntList;
        WriteFmt("Testing List init optional allocator\n");
    
        typedef List(int) IntList;
        DefaultAllocator alloc = DefaultAllocatorInit();
        // intentional bypass: no public setter on `Allocator` for effort /
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        };
    
        WriteFmt("[INFO] Starting List.Init tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Init");
    }
    
        WriteFmt("[INFO] Starting List.Init tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Init");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Types.h>
    
    static bool test_list_insert_and_push_aliases(void) {
        WriteFmt("Testing List insert and push aliases\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        int     a    = 10;
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list  = ListInit(&alloc);
        int     arr[] = {1, 2, 3};
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list  = ListInit(&alloc);
        int     arr[] = {4, 5, 6};
    
    static bool test_list_insert_with_deep_copy(void) {
        WriteFmt("Testing List insert with deep copy\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list  = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        int     x     = 7;
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList dest = ListInit(&alloc);
        IntList src  = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
    
    static bool test_list_merge_variants(void) {
        WriteFmt("Testing List merge variants\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList dest_l = ListInit(&alloc);
        IntList src_l  = ListInit(&alloc);
    
    static bool test_list_merge_edge_cases(void) {
        WriteFmt("Testing List merge edge cases\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList deep_dest   = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        IntList shallow_src = ListInit(&alloc);
        };
    
        WriteFmt("[INFO] Starting List.Insert tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Insert");
    }
    
        WriteFmt("[INFO] Starting List.Insert tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Insert");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    
    static bool test_list_foreach_basic(void) {
        WriteFmt("Testing basic List foreach macros\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list              = ListInit(&alloc);
        int     reverse_values[5] = {0};
    
    static bool test_list_foreach_ranges(void) {
        WriteFmt("Testing ranged List foreach macros\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list              = ListInit(&alloc);
        int     forward_range_sum = 0;
    
    static bool test_list_foreach_range_edge_cases(void) {
        WriteFmt("Testing List ranged foreach edge cases\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list  = ListInit(&alloc);
        int     count = 0;
    
    static bool test_list_foreach_index_variants(void) {
        WriteFmt("Testing indexed List foreach macros\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list              = ListInit(&alloc);
        int     reverse_values[5] = {0};
    
    static bool test_list_foreach_index_jump_contract(void) {
        WriteFmt("Testing indexed List foreach jump contract\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list              = ListInit(&alloc);
        int     forward_values[3] = {0};
    
    static bool test_list_foreach_empty_lists(void) {
        WriteFmt("Testing List foreach macros on empty list\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list  = ListInit(&alloc);
        u64     count = 0;
        };
    
        WriteFmt("[INFO] Starting List.Foreach tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Foreach");
    }
    
        WriteFmt("[INFO] Starting List.Foreach tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Foreach");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList empty     = ListInit(&alloc);
        IntList singleton = ListInit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        };
    
        WriteFmt("[INFO] Starting List.Ops tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Ops");
    }
    
        WriteFmt("[INFO] Starting List.Ops tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Ops");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Types.h>
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
    
    static bool test_list_value_access_and_swap(void) {
        WriteFmt("Testing List accessors and swap\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
    
    static bool test_list_node_access_and_navigation(void) {
        WriteFmt("Testing List node access and navigation\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        };
    
        WriteFmt("[INFO] Starting List.Access tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Access");
    }
    
        WriteFmt("[INFO] Starting List.Access tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Access");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Types.h>
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list    = ListInit(&alloc);
        int     removed = 0;
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list       = ListInit(&alloc);
        int     removed[2] = {0, 0};
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list      = ListInit(&alloc);
        int     prefix[2] = {0, 0};
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list       = ListInit(&alloc);
        int     removed[3] = {0, 0, 0};
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list    = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        int     removed = 0;
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list       = ListInitWithDeepCopy(tracked_copy_init, tracked_copy_deinit, &alloc);
        int     removed[2] = {0, 0};
        };
    
        WriteFmt("[INFO] Starting List.Remove tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Remove");
    }
    
        WriteFmt("[INFO] Starting List.Remove tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Remove");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
        WriteFmt("Testing ValidateList on corrupt empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        // intentional bypass: ListHead is read-only, no public setter exists --
        // plant a bogus head pointer on an empty list so ValidateList trips its
        WriteFmt("Testing ValidateList on invalid magic\n");
    
        List(int) list = ListInit(get_test_alloc());
        // intentional bypass: __magic is the private sentinel ValidateList
        // checks; scramble it directly to exercise the type-confusion /
    
        GenericListNode node = {0};
        List(int) list       = ListInit(get_test_alloc());
        GenericList *g       = GENERIC_LIST(&list);
        int             value = 1;
        GenericListNode node  = {.next = NULL, .prev = NULL, .data = &value};
        List(int) list        = ListInit(get_test_alloc());
        GenericList *g        = GENERIC_LIST(&list);
        int             value = 1;
        GenericListNode node  = {.next = NULL, .prev = (GenericListNode *)1, .data = &value};
        List(int) list        = ListInit(get_test_alloc());
        GenericList *g        = GENERIC_LIST(&list);
        int             value = 1;
        GenericListNode node  = {.next = (GenericListNode *)1, .prev = NULL, .data = &value};
        List(int) list        = ListInit(get_test_alloc());
        GenericList *g        = GENERIC_LIST(&list);
        WriteFmt("Testing ListPtrAt on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPtrAt(&list, 0);
        WriteFmt("Testing ListPtrAt out of bounds\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListPtrAt(&list, 1);
        WriteFmt("Testing ListAt out of bounds\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        (void)ListAt(&list, 1);
        WriteFmt("Testing ListNodePtrAt on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListNodePtrAt(&list, 0);
        WriteFmt("Testing ListNodePtrAt out of bounds\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListNodePtrAt(&list, 1);
        WriteFmt("Testing ListNodeAt out of bounds\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        (void)ListNodeAt(&list, 1);
        WriteFmt("Testing ListFirst on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListFirst(&list);
        WriteFmt("Testing ListLast on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListLast(&list);
        WriteFmt("Testing ListNodeAt on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        (void)ListNodeAt(&list, 0);
        WriteFmt("Testing ListInsertR out of range\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListInsertR(&list, 10, 1);
        WriteFmt("Testing ListRemove out of range\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListRemove(&list, NULL, 1);
        WriteFmt("Testing ListPopFront on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPopFront(&list, NULL);
        WriteFmt("Testing ListPopBack on empty list\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPopBack(&list, NULL);
        WriteFmt("Testing ListRemoveRange out of range\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListPushBackR(&list, 20);
        WriteFmt("Testing ListSwapItems out of range\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListSwapItems(&list, 0, 1);
        WriteFmt("Testing ListFind without compare function\n");
    
        List(int) list = ListInit(get_test_alloc());
        int key        = 10;
        ListPushBackR(&list, 10);
        WriteFmt("Testing ListFind without key pointer\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListFind(&list, NULL, compare_ints);
        WriteFmt("Testing ListSort without compare function\n");
    
        List(int) list = ListInit(get_test_alloc());
        ListPushBackR(&list, 10);
        ListSort(&list, NULL);
        };
    
        WriteFmt("[INFO] Starting List.Deadend tests\n\n");
        return run_test_suite(
            NULL,
            deadend_tests,
            (int)(sizeof(deadend_tests) / sizeof(deadend_tests[0])),
            "List.Deadend"
        );
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/List.h>
    #include <Misra/Std/Log.h>
    
    static bool test_list_type_defaults(void) {
        WriteFmt("Testing List type defaults\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        typedef List(int) IntList;
        IntList list = ListInit(&alloc);
        };
    
        WriteFmt("[INFO] Starting List.Type tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Type");
    }
    
        WriteFmt("[INFO] Starting List.Type tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "List.Type");
    }
    #endif
    #if FEATURE_LIST
    #    include <Misra/Std/Container/List.h>
    #endif
    #if FEATURE_MAP
    
    // clang-format off
    #include "List/Type.h"
    #include "List/Init.h"
    #include "List/Insert.h"
    // clang-format off
    #include "List/Type.h"
    #include "List/Init.h"
    #include "List/Insert.h"
    #include "List/Remove.h"
    #include "List/Type.h"
    #include "List/Init.h"
    #include "List/Insert.h"
    #include "List/Remove.h"
    #include "List/Access.h"
    #include "List/Init.h"
    #include "List/Insert.h"
    #include "List/Remove.h"
    #include "List/Access.h"
    #include "List/Foreach.h"
    #include "List/Insert.h"
    #include "List/Remove.h"
    #include "List/Access.h"
    #include "List/Foreach.h"
    #include "List/Ops.h"
    #include "List/Remove.h"
    #include "List/Access.h"
    #include "List/Foreach.h"
    #include "List/Ops.h"
    #include "List/Private.h"
    #include "List/Access.h"
    #include "List/Foreach.h"
    #include "List/Ops.h"
    #include "List/Private.h"
    // clang-format on
    #include "List/Foreach.h"
    #include "List/Ops.h"
    #include "List/Private.h"
    // clang-format on
Last updated on