summaryrefslogtreecommitdiff
path: root/libs/dolphin/src/support/List.c
blob: 34b6bc8a56985e382e19f5746014413b4c842e01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <charPipeline/structures/List.h>

void DSInitList(DSListPtr list, Ptr obj, DSLinkPtr link) {
    list->Head = NULL;
    list->Tail = NULL;
    list->Offset = (Ptr)link - obj;
}

void DSInsertListObject(DSListPtr list, Ptr cursor, Ptr obj) {
    DSLinkPtr link;
    DSLinkPtr linkNext;
    DSLinkPtr linkPrev;

    link = (DSLinkPtr)(obj + list->Offset);
    if (list->Head) {
        if (!cursor) {
            linkPrev = (DSLinkPtr)(list->Tail + list->Offset);
            linkPrev->Next = obj;
            link->Prev = list->Tail;
            link->Next = NULL;
            list->Tail = obj;
        } else {
            linkNext = (DSLinkPtr)(cursor + list->Offset);
            if (cursor == list->Head) {
                list->Head = obj;
                link->Next = cursor;
                linkNext->Prev = obj;
            } else {
                linkPrev = (DSLinkPtr)(linkNext->Prev + list->Offset);
                link->Next = cursor;
                link->Prev = linkNext->Prev;
                linkNext->Prev = obj;
                linkPrev->Next = obj;
            }
        }
    } else {
        list->Tail = obj;
        list->Head = obj;
        link->Next = link->Prev = NULL;
    }
}

void DSRemoveListObject(DSListPtr list, Ptr obj) {
    DSLinkPtr link = (DSLinkPtr)(obj + list->Offset);

    if (obj) {
        if (link->Prev) {
            ((DSLinkPtr)(link->Prev + list->Offset))->Next = link->Next;
        } else {
            list->Head = link->Next;
        }

        if (link->Next) {
            ((DSLinkPtr)(link->Next + list->Offset))->Prev = link->Prev;
        } else {
            list->Tail = link->Prev;
        }

        link->Prev = NULL;
        link->Next = NULL;
    }
}

void DSAttachList(DSListPtr baseList, DSListPtr attachList) {
    DSLinkPtr link;
    DSLinkPtr linkPrev;

    if (baseList->Offset == attachList->Offset && (attachList->Head || attachList->Tail)) {
        linkPrev = (DSLinkPtr)(attachList->Head + attachList->Offset);
        if (baseList->Head) {
            link = (DSLinkPtr)(baseList->Tail + baseList->Offset);
            link->Next = attachList->Head;
            linkPrev->Prev = baseList->Tail;
            baseList->Tail = attachList->Tail;
            return;
        }
        baseList->Head = attachList->Head;
        baseList->Tail = attachList->Tail;
        linkPrev;  // needed to match
    }
}

void* DSNextListObj(DSListPtr list, Ptr obj) {
    if (!list) {
        return NULL;
    }
    if (!obj) {
        return list->Head;
    }

    return ((DSLinkPtr)(obj + list->Offset))->Next;
}