From 636657f454a3ce7fcd7d1dc76a76a65144ce7b91 Mon Sep 17 00:00:00 2001 From: Chen Peng Date: Sun, 30 Aug 2026 04:01:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=9F=BA=E7=A1=80=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Foundation/c_List.c | 1 + Foundation/c_List.h | 73 +++++++++++++++++++++ Foundation/c_List.t.c | 144 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 Foundation/c_List.c create mode 100644 Foundation/c_List.h create mode 100644 Foundation/c_List.t.c diff --git a/Foundation/c_List.c b/Foundation/c_List.c new file mode 100644 index 0000000..2857b2c --- /dev/null +++ b/Foundation/c_List.c @@ -0,0 +1 @@ +#include diff --git a/Foundation/c_List.h b/Foundation/c_List.h new file mode 100644 index 0000000..f3c99ed --- /dev/null +++ b/Foundation/c_List.h @@ -0,0 +1,73 @@ +#ifndef INCLUDED_C_LIST_H +#define INCLUDED_C_LIST_H + +#ifndef INCLUDED_C_TYPES_H +#include +#endif /*INCLUDED_C_TYPES_H*/ + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +typedef struct c_ListNode_t { + struct c_ListNode_t* prev; + struct c_ListNode_t* next; +}c_ListNode_t; + +typedef c_ListNode_t c_List_t; + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +#define c_List_Prev(n) (n)->prev +#define c_List_Next(n) (n)->next +#define c_List_PrevNext(n) c_List_Next(c_List_Prev(n)) +#define c_List_NextPrev(n) c_List_Prev(c_List_Next(n)) + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + + +#define c_List_Init(n) do{ \ + c_List_Prev(n) = c_List_Next(n) = (n); \ +}while(0) + +#define c_List_IsEmpty(n) ((c_List_Next(n) == (n)) && (c_List_Prev(n) == (n))) + +#define c_List_InsertBefore(L, N) do { \ + c_List_Next(N) = (L); \ + c_List_Prev(N) = c_List_Prev(L); \ + c_List_PrevNext(N) = (N); \ + c_List_Prev(L) = (N); \ +} while(0) + +#define c_List_InsertAfter(L, N) do { \ + c_List_Prev(N) = (L); \ + c_List_Next(N) = c_List_Next(L); \ + c_List_NextPrev(N) = (N); \ + c_List_Next(L) = (N); \ +} while(0) + +#define c_List_Remove(n) do { \ + c_List_PrevNext(n) = c_List_Next(n); \ + c_List_NextPrev(n) = c_List_Prev(n); \ + c_List_Init(n); \ +} while(0) + +#define c_List_Entry(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +// Standard forward loop: Safe for lookups, UNSAFE for deletions +#define c_List_ForEachEntry(head, pos, type, member) \ + for (pos = c_List_Entry(c_List_Next(head), type, member); \ + &pos->member != (head); \ + pos = c_List_Entry(c_List_Next(&pos->member), type, member)) + +// Safe forward loop: Explicitly safe to call c_List_Remove inside the loop body +#define c_List_ForEachEntrySafe(head, pos, n, type, member) \ + for (pos = c_List_Entry(c_List_Next(head), type, member), \ + n = c_List_Entry(c_List_Next(&pos->member), type, member); \ + &pos->member != (head); \ + pos = n, n = c_List_Entry(c_List_Next(&n->member), type, member)) + +#endif /*INCLUDED_C_LIST_H*/ diff --git a/Foundation/c_List.t.c b/Foundation/c_List.t.c new file mode 100644 index 0000000..62d327b --- /dev/null +++ b/Foundation/c_List.t.c @@ -0,0 +1,144 @@ +#include + +#include "c_List.h" +#include +#include + +// Custom User Type showcasing intrusive inclusion +typedef struct { + int value; + c_ListNode_t node; // Intrusive node payload linkage +} CustomData_t; + +static void test2(void) { + printf("==================================================\n"); + printf(" Starting Intrusive Safe-Iterator Unit Tests\n"); + printf("==================================================\n\n"); + + c_List_t head; + c_List_Init(&head); + + CustomData_t d1 = {10}; + CustomData_t d2 = {20}; + CustomData_t d3 = {30}; + + // Linking nodes to tail: [Head] <-> [10] <-> [20] <-> [30] + c_List_InsertBefore(&head, &d1.node); + c_List_InsertBefore(&head, &d2.node); + c_List_InsertBefore(&head, &d3.node); + + // ========================================== + // 1. Verify Lookups via ForEachEntry + // ========================================== + CustomData_t* pos; + int index = 0; + int expected[] = {10, 20, 30}; + + printf("Reading nodes using standard ForEachEntry:\n"); + c_List_ForEachEntry(&head, pos, CustomData_t, node) { + printf(" Found Entry value: %d\n", pos->value); + assert(pos->value == expected[index++]); + } + assert(index == 3); + printf("[PASS] Standard lookup loop complete.\n\n"); + + // ========================================== + // 2. Verify Mutations via ForEachEntrySafe + // ========================================== + CustomData_t* tmp; // Cache variable for safe traversal tracking + index = 0; + + printf("Filtering and removing matching entry elements via Safe Loop:\n"); + c_List_ForEachEntrySafe(&head, pos, tmp, CustomData_t, node) { + if (pos->value == 20) { + printf(" Modifying layout: Safely dropping element (%d)\n", pos->value); + c_List_Remove(&pos->node); // Remove middle item mid-flight + } + index++; + } + assert(index == 3); // Iterated through all three bounds + + // ========================================== + // 3. Confirm Final Structure Integrity + // ========================================== + // List must now structurally bridge to bypass item 20: [10] <-> [30] + index = 0; + c_List_ForEachEntry(&head, pos, CustomData_t, node) { + if (index == 0) assert(pos->value == 10); + if (index == 1) assert(pos->value == 30); + index++; + } + assert(index == 2); + printf("[PASS] Structural integrity verified following safe removal mutation.\n"); + + printf("\n==================================================\n"); + printf(" Success! Intrusive layout traversal operates flawlessly!\n"); + printf("==================================================\n"); +} + +int main() { + printf("==================================================\n"); + printf(" Starting Intrusive Circular Doubly Linked List Tests\n"); + printf("==================================================\n\n"); + + // Initialize list head context anchor + c_List_t head; + c_List_Init(&head); + assert(c_List_IsEmpty(&head) == 1); + + CustomData_t d1 = {100}; + CustomData_t d2 = {200}; + CustomData_t d3 = {300}; + + // ========================================== + // 1. Insertion Testing + // ========================================== + // Insert d1 after head -> List: [Head] <-> [100] + c_List_InsertAfter(&head, &d1.node); + assert(c_List_IsEmpty(&head) == 0); + + // Insert d3 before head -> List: [Head] <-> [100] <-> [300] + c_List_InsertBefore(&head, &d3.node); + + // Insert d2 after d1 -> List: [Head] <-> [100] <-> [200] <-> [300] + c_List_InsertAfter(&d1.node, &d2.node); + + printf("[PASS] Sequence insertions complete.\n"); + + // ========================================== + // 2. Linear Traversal Verification + // ========================================== + c_ListNode_t* curr = c_List_Next(&head); + int expected_values[] = {100, 200, 300}; + int idx = 0; + + while (curr != &head) { + CustomData_t* entry = c_List_Entry(curr, CustomData_t, node); + assert(entry->value == expected_values[idx]); + curr = c_List_Next(curr); + idx++; + } + assert(idx == 3); + printf("[PASS] Intrusive forward iterator matching sequential expectations.\n"); + + // ========================================== + // 3. Deletion and Mutation Verification + // ========================================== + // Target and drop middle node (200) + c_List_Remove(&d2.node); + + // Structure must bridge gaps smoothly: [100] <-> [300] + assert(c_List_Next(&d1.node) == &d3.node); + assert(c_List_Prev(&d3.node) == &d1.node); + + // Eliminated isolated node must be self-referencing via macro assignment + assert(c_List_IsEmpty(&d2.node) == 1); + printf("[PASS] Drop operation and isolated reference initialization verified.\n"); + + printf("\n==================================================\n"); + printf(" Success! Intrusive macro mutations match layout specs!\n"); + printf("==================================================\n"); + + test2(); + return 0; +} \ No newline at end of file