一些基础组件
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
#include <c_List.h>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#ifndef INCLUDED_C_LIST_H
|
||||||
|
#define INCLUDED_C_LIST_H
|
||||||
|
|
||||||
|
#ifndef INCLUDED_C_TYPES_H
|
||||||
|
#include <c_Types.h>
|
||||||
|
#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*/
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "c_List.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user