-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathslice.c
More file actions
225 lines (197 loc) · 6.38 KB
/
slice.c
File metadata and controls
225 lines (197 loc) · 6.38 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "smalloc.h"
#include <stdbool.h>
#include "slice.h"
slice new_slice(ssize_t cap, ssize_t base, ssize_t item_width) {
struct slice aslice;
aslice.len = 0;
aslice.start = 0;
aslice.parent = new_dynarray(cap, base, item_width);
return(aslice);
}
dynarray *new_dynarray(ssize_t cap, ssize_t base, ssize_t item_width) {
dynarray *darray = smalloc(sizeof(dynarray));
darray->cap = cap;
darray->base = base;
darray->item_width = item_width;
darray->array = smalloc(cap * sizeof(char) * item_width);
return(darray);
}
slice new_slice_from_arr(void *arr, ssize_t cap, ssize_t base, ssize_t item_width) {
slice s = new_slice(cap, base, item_width);
s = set_slice_arr(s, arr, cap);
return s;
}
slice dup_slice(slice inslice) {
slice outslice = inslice;
outslice.parent = new_dynarray(inslice.parent->cap, inslice.parent->base, inslice.parent->item_width);
dynarray inp = *inslice.parent;
dynarray outp = *outslice.parent;
memcpy(outp.array, inp.array, outp.cap * outp.item_width);
return(outslice);
}
void free_slice(slice aslice) {
free(aslice.parent->array);
free(aslice.parent);
}
void grow_dynarray(dynarray *d, ssize_t length_needed) {
d->cap = length_needed;
d->array = srealloc(d->array, length_needed * sizeof(char) * d->item_width);
}
void shift_dynarray(dynarray *d, ssize_t shift_dist) {
ssize_t old_cap = d->cap;
ssize_t cap_needed = d->cap + shift_dist;
while (cap_needed >= d->cap) {
grow_dynarray(d, cap_needed * 2);
}
for (ssize_t i=old_cap; i>=0; i--) {
memcpy(d->array + ((i + shift_dist) * d->item_width), d->array + (i * d->item_width), d->item_width);
};
d->base = d->base + shift_dist;
}
slice append_slice(slice aslice, const void *item) {
return extend_slice(aslice, item, 1);
}
slice slice_append_slice(slice aslice, slice item) {
return extend_slice(aslice, &item, 1);
}
slice lappend_slice(slice aslice, const void *item) {
return lextend_slice(aslice, item, 1);
}
slice slice_lappend_slice(slice aslice, slice item) {
return lextend_slice(aslice, &item, 1);
}
slice extend_slice(slice s, const void *item, ssize_t nmemb) {
slice s_end = set_slice_arr(sub_slice(s, s.len, 0), item, nmemb);
s.len = s.len + s_end.len;
return s;
}
slice lextend_slice(slice s, const void *item, ssize_t nmemb) {
slice s_new = set_slice_arr(sub_slice(s, -nmemb, 0), item, nmemb);
s.len = s.len + s_new.len;
s.start = s.start - nmemb;
return s;
}
slice concat_slices(slice dest, slice source) {
return extend_slice(dest, slice_get_ptr(source), source.len);
}
slice set_slice_arr(slice s, const void *item, ssize_t nmemb) {
dynarray *d = s.parent;
ssize_t shift_needed = -(d->base + s.start);
if (shift_needed > 0) {
shift_dynarray(d, shift_needed);
}
ssize_t cap_needed = d->base + s.start + nmemb;
while (cap_needed >= d->cap) {
grow_dynarray(d, cap_needed * 2);
}
memcpy(slice_get_ptr(s), item, d->item_width * nmemb);
s.len += nmemb;
return s;
}
slice set_slice(slice dest, slice source) {
return set_slice_arr(dest, slice_get_ptr(source), source.len);
}
void print_slice(slice s, void (*fp) (void *)) {
for (ssize_t i=s.start; i<s.start + s.len; i++) {
fp(s.parent->array + ((i + s.parent->base) * s.parent->item_width));
}
printf("\n");
}
void introspect_slice(slice s, void (*fp) (void *)) {
dynarray d = *s.parent;
printf("len: %ld\nstart: %ld\nparent: %p\ncap: %ld\nbase: %ld\nitem_width: %ld\narray: %p\n",
s.len,
s.start,
(void *) s.parent,
d.cap,
d.base,
d.item_width,
(void *) d.array
);
print_slice(s, fp);
}
void print_double(void *d) {
double d2;
memcpy(&d2, d, sizeof(double));
printf("%10lg", d2);
}
void print_char(void *d) {
char d2;
memcpy(&d2, d, sizeof(char));
printf("%c", d2);
}
void print_long_long(void *d) {
long long d2;
memcpy(&d2, d, sizeof(long long));
printf("%10lld", d2);
}
slice sub_slice(slice ins, ssize_t start, ssize_t len) {
slice outs = ins;
outs.start = start + outs.start;
outs.len = len;
return(outs);
}
void slice_extract(void *dest, struct slice source) {
dynarray d = *source.parent;
memcpy(dest, slice_get_ptr(source), source.len * d.item_width);
}
slice slice_extract_slice(struct slice source) {
slice buf;
dynarray d = *source.parent;
memcpy(&buf, slice_get_ptr(source), source.len * d.item_width);
return buf;
}
void * slice_get_ptr(slice s) {
return s.parent->array + ((s.parent->base + s.start) * s.parent->item_width);
}
slice split_slice(slice to_split, slice separators) {
slice out = new_slice(0, 0, sizeof(slice));
ssize_t start = 0;
for (ssize_t pos=0; pos < to_split.len; pos++) {
for (ssize_t sep_index=0; sep_index < separators.len; sep_index++) {
if (!memcmp(
slice_get_ptr(sub_slice(to_split, pos, 1)),
slice_get_ptr(sub_slice(separators, sep_index, 1)),
to_split.parent->item_width
)) {
slice to_append = sub_slice(to_split, start, pos-start);
out = append_slice(out, &to_append);
start = pos+1;
break;
}
}
}
return out;
}
slice tokenize_slice(slice to_split, slice separators) {
slice out = new_slice(0, 0, sizeof(slice));
ssize_t start = 0;
bool started_token = true;
bool sep_match = false;
for (ssize_t pos=0; pos < to_split.len; pos++) {
for (ssize_t sep_index=0; sep_index < separators.len; sep_index++) {
if (!memcmp(
slice_get_ptr(sub_slice(to_split, pos, 1)),
slice_get_ptr(sub_slice(separators, sep_index, 1)),
to_split.parent->item_width
)) {
sep_match = true;
if (started_token) {
slice to_append = sub_slice(to_split, start, pos-start);
out = append_slice(out, &to_append);
}
started_token = false;
break;
}
if (sep_index == separators.len-1) {sep_match = false;}
}
if ((!started_token) && !sep_match) {
start = pos;
started_token = true;
};
}
return out;
}