-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbytevector.c
149 lines (120 loc) · 3.56 KB
/
bytevector.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <string.h>
#include "lisp.h"
#define LENGTH(x) ST_BYTEVECTOR_LENGTH(x)
#define DATA(x) ST_BYTEVECTOR_DATA(x)
StObject St_MakeBytevector(int size, int byte)
{
StObject o = St_Alloc2(TBYTEVECTOR, sizeof(struct StBytevectorRec) + size);
LENGTH(o) = size;
if (byte >= 0)
{
memset(DATA(o), byte, size);
}
return o;
}
StObject St_MakeBytevectorFromList(StObject bytes)
{
int len = St_Length(bytes);
StObject o = St_MakeBytevector(len, -1);
int i = 0;
ST_FOREACH(p, bytes) {
St_BytevectorU8Set(o, i++, ST_INT_VALUE(ST_CAR(p)));
}
return o;
}
size_t St_BytevectorLength(StObject b)
{
return LENGTH(b);
}
#define VALIDATE_INDEX(n, b, k) \
do { \
if ((k) < 0 || LENGTH(b) <= (size_t)(k)) \
{ \
St_Error("%s: index out of range: %d against %d", (n), (k), LENGTH(b)); \
} \
} while (0)
#define VALIDATE_SIZE(n, b, k) \
do { \
if ((k) < 0 || LENGTH(b) < (size_t)(k)) \
{ \
St_Error("%s: index out of range: %d against %d", (n), (k), LENGTH(b)); \
} \
} while (0)
uint8_t St_BytevectorU8Ref(StObject b, int k)
{
VALIDATE_INDEX("bytevector-u8-ref", b, k);
return DATA(b)[k];
}
void St_BytevectorU8Set(StObject b, int k, uint8_t byte)
{
VALIDATE_INDEX("bytevector-u8-set!", b, k);
DATA(b)[k] = byte;
}
StObject St_MakeBytevectorFrom(StObject b, int start, int end)
{
if (start < 0)
{
start = 0;
}
VALIDATE_INDEX("bytevector-copy", b, start);
if (end < 0)
{
end = LENGTH(b);
}
VALIDATE_SIZE("bytevector-copy", b, end);
int newlen = end - start;
if (newlen < 0)
{
St_Error("bytevector-copy: end %d is less than start %d", end, start);
}
StObject o = St_MakeBytevector(newlen, -1);
memcpy(DATA(o), DATA(b) + start, newlen);
return o;
}
void St_BytevectorCopy(StObject to, int at, StObject from, int start, int end)
{
VALIDATE_INDEX("bytevector-copy!", to, at);
if (start < 0)
{
start = 0;
}
VALIDATE_INDEX("bytevector-copy!", from, start);
if (end < 0)
{
end = LENGTH(from);
}
VALIDATE_SIZE("bytevector-copy!", from, end);
int copylen = end - start;
if (copylen < 0)
{
St_Error("bytevector-copy!: end %d is less than start %d", end, start);
}
int capa = LENGTH(to) - at;
if (capa < copylen)
{
St_Error("bytevector-copy!: length to copy %d is more than capacity %d", copylen, capa);
}
memmove(DATA(to) + at, DATA(from) + start, copylen);
}
StObject St_BytevectorAppend(StObject vectors)
{
int len = 0;
ST_FOREACH(p, vectors) {
len += LENGTH(ST_CAR(p));
}
StObject o = St_MakeBytevector(len, -1);
int d = 0;
ST_FOREACH(p, vectors) {
memcpy(DATA(o) + d, DATA(ST_CAR(p)), LENGTH(ST_CAR(p)));
d += LENGTH(ST_CAR(p));
}
return o;
}
bool St_BytevectorEqualP(StObject b1, StObject b2)
{
if (LENGTH(b1) != LENGTH(b2))
{
return false;
}
return memcmp(DATA(b1), DATA(b2), LENGTH(b1)) == 0;
}