/
list.c
130 lines (103 loc) · 1.83 KB
/
list.c
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
static void *getnext(void *);
static void link(void *, void const *);
static void *walk(void *, size_t);
#if 0
void *
cadr(void *li)
{
List(char) *tmp;
tmp = getnext(li);
if (!tmp) return NULL;
return car(tmp);
}
void *
cddr(void *li)
{
List(char) *tmp;
tmp = getnext(li);
if (!tmp) return NULL;
return getnext(tmp);
}
#endif
void
free_list(void *list)
{
void *next, *prev;
next = list;
while (next) {
prev = next;
next = getnext(prev);
free(prev);
}
}
void *
list_cons(void *data, void *_list)
{
char *ret;
size_t off;
List(char) list;
assert(data);
assert(_list);
memcpy(&list, _list, sizeof list);
ret = calloc(1, sizeof list);
if (!ret) return NULL;
off = offsetof(List(char), z);
memcpy(ret + off, &list.z, sizeof list.z);
off = offsetof(List(char), next);
if (list.w) memset(ret + off, 0, sizeof list.next);
else memcpy(ret + off, &_list, sizeof _list);
off = offsetof(List(char), val);
memcpy(ret + off, data, list.z);
if (list.w) {
memcpy(_list, ret, sizeof list);
free(ret);
ret = _list;
list.w = 0;
}
return ret;
}
void *
getnext(void *list)
{
size_t off;
void *ret;
off = offsetof(List(char), next);
memcpy(&ret, (char *)list + off, sizeof (void *));
return ret;
}
void
link(void *prev, void const *next)
{
size_t off;
off = offsetof(List(char), next);
memcpy((char *)prev + off, &next, sizeof next);
}
void *
walk(void *list, size_t ext)
{
size_t rem;
void *cur, *prev;
rem = ext;
cur = list;
while (--rem) {
prev = cur;
cur = getnext(cur);
if (!cur) return prev;
}
return cur;
}
void
list_append(void *dest, void *src)
{
List(char) li;
memcpy(&li, dest, sizeof li);
if (li.w) {
memcpy(dest, src, sizeof li);
free(src);
} else link(walk(dest, (size_t)-1), src);
}