4223
|
1 #include "config.h"
|
|
2 #include "IO.h"
|
|
3 #include "Str.h"
|
|
4 #include "kork.h"
|
|
5 #include "strutil.h"
|
|
6 #include "xmalloc.h"
|
|
7
|
|
8 #include <stdio.h>
|
|
9 #include <assert.h>
|
|
10 #include <string.h>
|
|
11 #include <ctype.h>
|
|
12
|
|
13 typedef struct ko_dolphin dolphin;
|
|
14 typedef struct kork kork;
|
|
15
|
|
16 static dolphin nil = {
|
|
17 { "FLIPPER", 1, 1, 0 },
|
|
18 0
|
|
19 };
|
|
20
|
|
21 static dolphin *incr(dolphin *dp) {
|
|
22 ++dp->refs;
|
|
23 return dp;
|
|
24 }
|
|
25
|
|
26 static void decr(dolphin *dp) {
|
|
27 if (dp->refs) {
|
|
28 --dp->refs;
|
|
29 return;
|
|
30 }
|
|
31
|
|
32 St_clear(&dp->str);
|
|
33 xfree(dp);
|
|
34 }
|
|
35
|
|
36 kork *ko_new(void) {
|
|
37 kork *const k = xmalloc(1, sizeof *k);
|
|
38 k->kdp = incr(&nil);
|
|
39 k->offset = 0;
|
|
40 k->length = 0;
|
|
41 return k;
|
|
42 }
|
|
43
|
|
44 kork *ko_dup(const kork *old) {
|
|
45 kork *const k = xmalloc(1, sizeof *k);
|
|
46 *k = *old;
|
|
47 incr(k->kdp);
|
|
48 return k;
|
|
49 }
|
|
50
|
|
51 void ko_decouple(kork *k) {
|
|
52 dolphin *const dp = k->kdp;
|
|
53 if (!k->kdp->refs) {
|
|
54 return;
|
|
55 }
|
|
56 k->kdp = xmalloc(1, sizeof *k->kdp);
|
|
57 St_init(&k->kdp->str);
|
|
58 St_cpy_m(&k->kdp->str, St_ptr(&dp->str) + k->offset, k->length);
|
|
59 k->kdp->refs = 0;
|
|
60 k->offset = 0;
|
|
61 decr(dp);
|
|
62 }
|
|
63
|
|
64 void ko_delete(kork *k) {
|
|
65 decr(k->kdp);
|
|
66 xfree(k);
|
|
67 }
|
|
68
|
|
69 size_t (ko_length)(const kork *k) {
|
|
70 return ko_length(k);
|
|
71 }
|
|
72
|
|
73 int ko_at(const kork *k, size_t i) {
|
|
74 return i < k->length ? ST_INDEX(&k->kdp->str, k->offset + i) : EOF;
|
|
75 }
|
|
76
|
|
77 int ko_lastchar(const kork *k) {
|
|
78 return k->length ? ST_INDEX(&k->kdp->str, k->offset + k->length - 1u) : EOF;
|
|
79 }
|
|
80
|
|
81 int ko_cmp(const kork *k1, const kork *k2) {
|
|
82 return u_cmp(
|
|
83 St_ptr(&k1->kdp->str) + k1->offset, k1->length,
|
|
84 St_ptr(&k2->kdp->str) + k2->offset, k2->length
|
|
85 );
|
|
86 }
|
|
87
|
|
88 void (ko_zero)(kork *k) {
|
|
89 ko_zero(k);
|
|
90 }
|
|
91
|
|
92 const char *ko_ptr(const kork *k) {
|
|
93 return St_ptr(&k->kdp->str) + k->offset;
|
|
94 }
|
|
95
|
|
96 static void offoff(kork *k) {
|
|
97 ko_decouple(k);
|
|
98 if (k->offset) {
|
|
99 St_del(&k->kdp->str, 0, k->offset);
|
|
100 k->offset = 0;
|
|
101 }
|
|
102 assert(St_len(&k->kdp->str) >= k->length);
|
|
103 }
|
|
104
|
|
105 const String *ko_str(kork *k) {
|
|
106 offoff(k);
|
|
107 St_trunc(&k->kdp->str, k->length);
|
|
108 return &k->kdp->str;
|
|
109 }
|
|
110
|
|
111 const char *ko_szp(kork *k) {
|
|
112 if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) {
|
|
113 offoff(k);
|
|
114 }
|
|
115 return St_ptr(&k->kdp->str) + k->offset;
|
|
116 }
|
|
117
|
|
118 void ko_grep(kork *k, int (*pred)(int)) {
|
|
119 offoff(k);
|
|
120 St_grep(&k->kdp->str, pred);
|
|
121 k->length = St_len(&k->kdp->str);
|
|
122 }
|
|
123
|
|
124 void ko_shift(kork *k, size_t n) {
|
|
125 if (n > k->length) {
|
|
126 n = k->length;
|
|
127 }
|
|
128 k->offset += n;
|
|
129 k->length -= n;
|
|
130 }
|
|
131
|
|
132 void ko_num(kork *k, double d) {
|
|
133 offoff(k);
|
|
134 St_num(&k->kdp->str, d);
|
|
135 k->length = St_len(&k->kdp->str);
|
|
136 }
|
|
137
|
|
138 void ko_cpy_m(kork *k, const void *p, size_t n) {
|
|
139 if (!n) {
|
|
140 ko_zero(k);
|
|
141 return;
|
|
142 }
|
|
143 offoff(k);
|
|
144 St_cpy_m(&k->kdp->str, p, n);
|
|
145 k->length = St_len(&k->kdp->str);
|
|
146 }
|
|
147
|
|
148 void ko_cpy(kork *k, const kork *z) {
|
|
149 ko_cpy_m(k, ko_ptr(z), ko_length(z));
|
|
150 }
|
|
151
|
|
152 void ko_cpy_s(kork *k, const char *s) {
|
|
153 ko_cpy_m(k, s, strlen(s));
|
|
154 }
|
|
155
|
|
156 void ko_cpy_c(kork *k, char c) {
|
|
157 offoff(k);
|
|
158 St_cpy_c(&k->kdp->str, c);
|
|
159 k->length = 1;
|
|
160 }
|
|
161
|
|
162 void ko_cat_m(kork *k, const void *p, size_t n) {
|
|
163 if (!n) {
|
|
164 return;
|
|
165 }
|
|
166 if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) {
|
|
167 offoff(k);
|
|
168 }
|
|
169 assert(k->offset + k->length <= St_len(&k->kdp->str));
|
|
170 St_trunc(&k->kdp->str, k->offset + k->length);
|
|
171 St_cat_m(&k->kdp->str, p, n);
|
|
172 k->length += n;
|
|
173 }
|
|
174
|
|
175 void ko_cat(kork *k, const kork *z) {
|
|
176 ko_cat_m(k, ko_ptr(z), ko_length(z));
|
|
177 }
|
|
178
|
|
179 void ko_cat_c(kork *k, char c) {
|
|
180 ko_cat_m(k, &c, 1);
|
|
181 }
|
|
182
|
|
183 void ko_reverse(kork *k) {
|
|
184 offoff(k);
|
|
185 St_reverse(&k->kdp->str);
|
|
186 }
|
|
187
|
|
188 size_t ko_getline(IO *io, kork *k) {
|
|
189 size_t tmp;
|
|
190 offoff(k);
|
|
191 tmp = io_getline(io, &k->kdp->str);
|
|
192 k->length = St_len(&k->kdp->str);
|
|
193 return tmp;
|
|
194 }
|
|
195
|
|
196 size_t ko_read(IO *io, kork *k, size_t n) {
|
|
197 size_t tmp;
|
|
198 offoff(k);
|
|
199 tmp = io_read(io, &k->kdp->str, n);
|
|
200 k->length = St_len(&k->kdp->str);
|
|
201 return tmp;
|
|
202 }
|
|
203
|
|
204 void ko_lower(kork *k) {
|
|
205 offoff(k);
|
|
206 St_lower(&k->kdp->str);
|
|
207 }
|
|
208
|
|
209 void ko_upper(kork *k) {
|
|
210 offoff(k);
|
|
211 St_upper(&k->kdp->str);
|
|
212 }
|
|
213
|
|
214 size_t ko_chr(const kork *k, int c) {
|
|
215 const char *const p = memchr(St_ptr(&k->kdp->str) + k->offset, c, k->length);
|
|
216 if (!p) {
|
|
217 return -1;
|
|
218 }
|
|
219 return p - (St_ptr(&k->kdp->str) + k->offset);
|
|
220 }
|
|
221
|
|
222 void ko_shiftws(kork *k) {
|
|
223 while (
|
|
224 k->length &&
|
|
225 isspace((unsigned char)St_ptr(&k->kdp->str)[k->offset])
|
|
226 ) {
|
|
227 ++k->offset;
|
|
228 --k->length;
|
|
229 }
|
|
230 }
|
|
231
|
|
232 void ko_trunc(kork *k, size_t n) {
|
|
233 if (n >= k->length) {
|
|
234 return;
|
|
235 }
|
|
236 k->length = n;
|
|
237 }
|