adamc@117
|
1 #include <stdlib.h>
|
adamc@102
|
2 #include <stdio.h>
|
adamc@117
|
3 #include <string.h>
|
adamc@106
|
4 #include <ctype.h>
|
adamc@136
|
5 #include <assert.h>
|
adamc@102
|
6
|
adamc@102
|
7 #include "types.h"
|
adamc@102
|
8
|
adamc@102
|
9 lw_unit lw_unit_v = {};
|
adamc@102
|
10
|
adamc@117
|
11 struct lw_context {
|
adamc@117
|
12 char *page, *page_front, *page_back;
|
adamc@136
|
13 char *heap, *heap_front, *heap_back;
|
adamc@117
|
14 };
|
adamc@117
|
15
|
adamc@136
|
16 lw_context lw_init(size_t page_len, size_t heap_len) {
|
adamc@117
|
17 lw_context ctx = malloc(sizeof(struct lw_context));
|
adamc@136
|
18
|
adamc@117
|
19 ctx->page_front = ctx->page = malloc(page_len);
|
adamc@117
|
20 ctx->page_back = ctx->page_front + page_len;
|
adamc@136
|
21
|
adamc@136
|
22 ctx->heap_front = ctx->heap = malloc(heap_len);
|
adamc@136
|
23 ctx->heap_back = ctx->heap_front + heap_len;
|
adamc@136
|
24
|
adamc@117
|
25 return ctx;
|
adamc@106
|
26 }
|
adamc@106
|
27
|
adamc@117
|
28 void lw_free(lw_context ctx) {
|
adamc@117
|
29 free(ctx->page);
|
adamc@136
|
30 free(ctx->heap);
|
adamc@136
|
31 free(ctx);
|
adamc@136
|
32 }
|
adamc@136
|
33
|
adamc@138
|
34 void lw_reset(lw_context ctx) {
|
adamc@138
|
35 ctx->page_front = ctx->page;
|
adamc@138
|
36 ctx->heap_front = ctx->heap;
|
adamc@138
|
37 }
|
adamc@138
|
38
|
adamc@136
|
39 static void lw_check_heap(lw_context ctx, size_t extra) {
|
adamc@136
|
40 if (ctx->heap_back - ctx->heap_front < extra) {
|
adamc@136
|
41 size_t desired = ctx->heap_back - ctx->heap_front + extra, next;
|
adamc@136
|
42 char *new_heap;
|
adamc@136
|
43
|
adamc@136
|
44 for (next = ctx->heap_back - ctx->heap_front; next < desired; next *= 2);
|
adamc@136
|
45
|
adamc@136
|
46 new_heap = realloc(ctx->heap, next);
|
adamc@136
|
47
|
adamc@136
|
48 if (new_heap != ctx->heap) {
|
adamc@136
|
49 ctx->heap = new_heap;
|
adamc@136
|
50 puts("Couldn't get contiguous chunk");
|
adamc@136
|
51 exit(1);
|
adamc@136
|
52 }
|
adamc@136
|
53
|
adamc@136
|
54 ctx->heap_back = new_heap + next;
|
adamc@136
|
55 }
|
adamc@136
|
56 }
|
adamc@136
|
57
|
adamc@136
|
58 void *lw_malloc(lw_context ctx, size_t len) {
|
adamc@136
|
59 void *result;
|
adamc@136
|
60
|
adamc@136
|
61 lw_check_heap(ctx, len);
|
adamc@136
|
62
|
adamc@136
|
63 result = ctx->heap_front;
|
adamc@136
|
64 ctx->heap_front += len;
|
adamc@136
|
65 return result;
|
adamc@117
|
66 }
|
adamc@117
|
67
|
adamc@117
|
68 int lw_really_send(int sock, const void *buf, ssize_t len) {
|
adamc@117
|
69 while (len > 0) {
|
adamc@117
|
70 ssize_t n = send(sock, buf, len, 0);
|
adamc@117
|
71
|
adamc@117
|
72 if (n < 0)
|
adamc@117
|
73 return n;
|
adamc@117
|
74
|
adamc@117
|
75 buf += n;
|
adamc@117
|
76 len -= n;
|
adamc@117
|
77 }
|
adamc@117
|
78
|
adamc@117
|
79 return 0;
|
adamc@117
|
80 }
|
adamc@117
|
81
|
adamc@117
|
82 int lw_send(lw_context ctx, int sock) {
|
adamc@117
|
83 return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
|
adamc@117
|
84 }
|
adamc@117
|
85
|
adamc@117
|
86 static void lw_check(lw_context ctx, size_t extra) {
|
adamc@117
|
87 size_t desired = ctx->page_back - ctx->page_front + extra, next;
|
adamc@117
|
88 char *new_page;
|
adamc@117
|
89
|
adamc@117
|
90 for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2);
|
adamc@117
|
91
|
adamc@117
|
92 new_page = realloc(ctx->page, next);
|
adamc@117
|
93 ctx->page_front = new_page + (ctx->page_front - ctx->page);
|
adamc@117
|
94 ctx->page_back = new_page + (ctx->page_back - ctx->page);
|
adamc@117
|
95 ctx->page = new_page;
|
adamc@117
|
96 }
|
adamc@117
|
97
|
adamc@117
|
98 static void lw_writec_unsafe(lw_context ctx, char c) {
|
adamc@117
|
99 *(ctx->page_front)++ = c;
|
adamc@117
|
100 }
|
adamc@117
|
101
|
adamc@117
|
102 void lw_writec(lw_context ctx, char c) {
|
adamc@117
|
103 lw_check(ctx, 1);
|
adamc@117
|
104 lw_writec_unsafe(ctx, c);
|
adamc@117
|
105 }
|
adamc@117
|
106
|
adamc@117
|
107 static void lw_write_unsafe(lw_context ctx, const char* s) {
|
adamc@117
|
108 int len = strlen(s);
|
adamc@117
|
109 memcpy(ctx->page_front, s, len);
|
adamc@117
|
110 ctx->page_front += len;
|
adamc@117
|
111 }
|
adamc@117
|
112
|
adamc@117
|
113 void lw_write(lw_context ctx, const char* s) {
|
adamc@117
|
114 lw_check(ctx, strlen(s));
|
adamc@117
|
115 lw_write_unsafe(ctx, s);
|
adamc@102
|
116 }
|
adamc@106
|
117
|
adamc@135
|
118
|
adamc@136
|
119 #define INTS_MAX 50
|
adamc@136
|
120 #define FLOATS_MAX 100
|
adamc@136
|
121
|
adamc@136
|
122 char *lw_Basis_attrifyInt(lw_context ctx, lw_Basis_int n) {
|
adamc@136
|
123 char *result;
|
adamc@136
|
124 int len;
|
adamc@136
|
125 lw_check_heap(ctx, INTS_MAX);
|
adamc@136
|
126 result = ctx->heap_front;
|
adamc@136
|
127 sprintf(result, "%d%n", n, &len);
|
adamc@137
|
128 ctx->heap_front += len+1;
|
adamc@136
|
129 return result;
|
adamc@106
|
130 }
|
adamc@106
|
131
|
adamc@136
|
132 char *lw_Basis_attrifyFloat(lw_context ctx, lw_Basis_float n) {
|
adamc@136
|
133 char *result;
|
adamc@136
|
134 int len;
|
adamc@137
|
135 lw_check_heap(ctx, FLOATS_MAX);
|
adamc@136
|
136 result = ctx->heap_front;
|
adamc@136
|
137 sprintf(result, "%g%n", n, &len);
|
adamc@137
|
138 ctx->heap_front += len+1;
|
adamc@136
|
139 return result;
|
adamc@106
|
140 }
|
adamc@106
|
141
|
adamc@136
|
142 char *lw_Basis_attrifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@136
|
143 int len = strlen(s);
|
adamc@136
|
144 char *result, *p;
|
adamc@137
|
145 lw_check_heap(ctx, len * 6 + 1);
|
adamc@136
|
146
|
adamc@136
|
147 result = p = ctx->heap_front;
|
adamc@136
|
148
|
adamc@136
|
149 for (; *s; s++) {
|
adamc@136
|
150 char c = *s;
|
adamc@136
|
151
|
adamc@136
|
152 if (c == '"') {
|
adamc@136
|
153 strcpy(p, """);
|
adamc@136
|
154 p += 6;
|
adamc@136
|
155 } else if (c == '&') {
|
adamc@136
|
156 strcpy(p, "&");
|
adamc@136
|
157 p += 5;
|
adamc@136
|
158 }
|
adamc@136
|
159 else if (isprint(c))
|
adamc@136
|
160 *p++ = c;
|
adamc@136
|
161 else {
|
adamc@136
|
162 int len2;
|
adamc@136
|
163 sprintf(p, "&#%d;%n", c, &len2);
|
adamc@136
|
164 p += len2;
|
adamc@136
|
165 }
|
adamc@136
|
166 }
|
adamc@136
|
167
|
adamc@137
|
168 *p++ = 0;
|
adamc@136
|
169 ctx->heap_front = p;
|
adamc@136
|
170 return result;
|
adamc@106
|
171 }
|
adamc@106
|
172
|
adamc@117
|
173 static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
174 int len;
|
adamc@117
|
175
|
adamc@117
|
176 sprintf(ctx->page_front, "%d%n", n, &len);
|
adamc@117
|
177 ctx->page_front += len;
|
adamc@106
|
178 }
|
adamc@106
|
179
|
adamc@117
|
180 void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
181 lw_check(ctx, INTS_MAX);
|
adamc@117
|
182 lw_Basis_attrifyInt_w_unsafe(ctx, n);
|
adamc@106
|
183 }
|
adamc@106
|
184
|
adamc@117
|
185 void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@117
|
186 int len;
|
adamc@117
|
187
|
adamc@117
|
188 lw_check(ctx, FLOATS_MAX);
|
adamc@117
|
189 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@117
|
190 ctx->page_front += len;
|
adamc@117
|
191 }
|
adamc@117
|
192
|
adamc@117
|
193 void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@117
|
194 lw_check(ctx, strlen(s) * 6);
|
adamc@117
|
195
|
adamc@106
|
196 for (; *s; s++) {
|
adamc@106
|
197 char c = *s;
|
adamc@106
|
198
|
adamc@106
|
199 if (c == '"')
|
adamc@117
|
200 lw_write_unsafe(ctx, """);
|
adamc@136
|
201 else if (c == '&')
|
adamc@136
|
202 lw_write_unsafe(ctx, "&");
|
adamc@106
|
203 else if (isprint(c))
|
adamc@117
|
204 lw_writec_unsafe(ctx, c);
|
adamc@106
|
205 else {
|
adamc@117
|
206 lw_write_unsafe(ctx, "&#");
|
adamc@117
|
207 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@117
|
208 lw_writec_unsafe(ctx, ';');
|
adamc@106
|
209 }
|
adamc@106
|
210 }
|
adamc@106
|
211 }
|
adamc@120
|
212
|
adamc@120
|
213
|
adamc@137
|
214 char *lw_Basis_urlifyInt(lw_context ctx, lw_Basis_int n) {
|
adamc@137
|
215 int len;
|
adamc@137
|
216 char *r;
|
adamc@137
|
217
|
adamc@137
|
218 lw_check_heap(ctx, INTS_MAX);
|
adamc@137
|
219 r = ctx->heap_front;
|
adamc@137
|
220 sprintf(r, "%d%n", n, &len);
|
adamc@137
|
221 ctx->heap_front += len+1;
|
adamc@137
|
222 return r;
|
adamc@120
|
223 }
|
adamc@120
|
224
|
adamc@137
|
225 char *lw_Basis_urlifyFloat(lw_context ctx, lw_Basis_float n) {
|
adamc@137
|
226 int len;
|
adamc@137
|
227 char *r;
|
adamc@137
|
228
|
adamc@137
|
229 lw_check_heap(ctx, FLOATS_MAX);
|
adamc@137
|
230 r = ctx->heap_front;
|
adamc@137
|
231 sprintf(r, "%g%n", n, &len);
|
adamc@137
|
232 ctx->heap_front += len+1;
|
adamc@137
|
233 return r;
|
adamc@120
|
234 }
|
adamc@120
|
235
|
adamc@137
|
236 char *lw_Basis_urlifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@137
|
237 char *r, *p;
|
adamc@137
|
238
|
adamc@137
|
239 lw_check_heap(ctx, strlen(s) * 3 + 1);
|
adamc@137
|
240
|
adamc@137
|
241 for (r = p = ctx->heap_front; *s; s++) {
|
adamc@137
|
242 char c = *s;
|
adamc@137
|
243
|
adamc@137
|
244 if (c == ' ')
|
adamc@137
|
245 *p++ = '+';
|
adamc@137
|
246 else if (isalnum(c))
|
adamc@137
|
247 *p++ = c;
|
adamc@137
|
248 else {
|
adamc@137
|
249 sprintf(p, "%%%02X", c);
|
adamc@137
|
250 p += 3;
|
adamc@137
|
251 }
|
adamc@137
|
252 }
|
adamc@137
|
253
|
adamc@137
|
254 *p++ = 0;
|
adamc@137
|
255 ctx->heap_front = p;
|
adamc@137
|
256 return r;
|
adamc@120
|
257 }
|
adamc@120
|
258
|
adamc@120
|
259 static void lw_Basis_urlifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
260 int len;
|
adamc@120
|
261
|
adamc@120
|
262 sprintf(ctx->page_front, "%d%n", n, &len);
|
adamc@120
|
263 ctx->page_front += len;
|
adamc@120
|
264 }
|
adamc@120
|
265
|
adamc@120
|
266 void lw_Basis_urlifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
267 lw_check(ctx, INTS_MAX);
|
adamc@120
|
268 lw_Basis_urlifyInt_w_unsafe(ctx, n);
|
adamc@120
|
269 }
|
adamc@120
|
270
|
adamc@120
|
271 void lw_Basis_urlifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@120
|
272 int len;
|
adamc@120
|
273
|
adamc@120
|
274 lw_check(ctx, FLOATS_MAX);
|
adamc@120
|
275 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@120
|
276 ctx->page_front += len;
|
adamc@120
|
277 }
|
adamc@120
|
278
|
adamc@120
|
279 void lw_Basis_urlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@120
|
280 lw_check(ctx, strlen(s) * 3);
|
adamc@120
|
281
|
adamc@120
|
282 for (; *s; s++) {
|
adamc@120
|
283 char c = *s;
|
adamc@120
|
284
|
adamc@120
|
285 if (c == ' ')
|
adamc@120
|
286 lw_writec_unsafe(ctx, '+');
|
adamc@120
|
287 else if (isalnum(c))
|
adamc@120
|
288 lw_writec_unsafe(ctx, c);
|
adamc@120
|
289 else {
|
adamc@120
|
290 sprintf(ctx->page_front, "%%%02X", c);
|
adamc@120
|
291 ctx->page_front += 3;
|
adamc@120
|
292 }
|
adamc@120
|
293 }
|
adamc@120
|
294 }
|
adamc@120
|
295
|
adamc@120
|
296
|
adamc@120
|
297 lw_Basis_int lw_unurlifyInt(char **s) {
|
adamc@120
|
298 char *new_s = strchr(*s, '/');
|
adamc@120
|
299 int r;
|
adamc@120
|
300
|
adamc@120
|
301 if (new_s)
|
adamc@120
|
302 *new_s++ = 0;
|
adamc@120
|
303 else
|
adamc@120
|
304 new_s = strchr(*s, 0);
|
adamc@120
|
305
|
adamc@120
|
306 r = atoi(*s);
|
adamc@120
|
307 *s = new_s;
|
adamc@120
|
308 return r;
|
adamc@120
|
309 }
|
adamc@120
|
310
|
adamc@120
|
311 lw_Basis_float lw_unurlifyFloat(char **s) {
|
adamc@120
|
312 char *new_s = strchr(*s, '/');
|
adamc@120
|
313 int r;
|
adamc@120
|
314
|
adamc@120
|
315 if (new_s)
|
adamc@120
|
316 *new_s++ = 0;
|
adamc@120
|
317 else
|
adamc@120
|
318 new_s = strchr(*s, 0);
|
adamc@120
|
319
|
adamc@120
|
320 r = atof(*s);
|
adamc@120
|
321 *s = new_s;
|
adamc@120
|
322 return r;
|
adamc@120
|
323 }
|
adamc@120
|
324
|
adamc@136
|
325 lw_Basis_string lw_unurlifyString(lw_context ctx, char **s) {
|
adamc@136
|
326 char *new_s = strchr(*s, '/');
|
adamc@136
|
327 char *r, *s1, *s2;
|
adamc@136
|
328 int len, n;
|
adamc@136
|
329
|
adamc@136
|
330 if (new_s)
|
adamc@136
|
331 *new_s++ = 0;
|
adamc@136
|
332 else
|
adamc@136
|
333 new_s = strchr(*s, 0);
|
adamc@136
|
334
|
adamc@136
|
335 len = strlen(*s);
|
adamc@136
|
336 lw_check_heap(ctx, len + 1);
|
adamc@136
|
337
|
adamc@136
|
338 r = ctx->heap_front;
|
adamc@136
|
339 for (s1 = r, s2 = *s; *s2; ++s1, ++s2) {
|
adamc@136
|
340 char c = *s2;
|
adamc@136
|
341
|
adamc@136
|
342 switch (c) {
|
adamc@136
|
343 case '+':
|
adamc@136
|
344 *s1 = ' ';
|
adamc@136
|
345 break;
|
adamc@136
|
346 case '%':
|
adamc@136
|
347 assert(s2 + 2 < new_s);
|
adamc@136
|
348 sscanf(s2+1, "%02X", &n);
|
adamc@136
|
349 *s1 = n;
|
adamc@136
|
350 s2 += 2;
|
adamc@136
|
351 break;
|
adamc@136
|
352 default:
|
adamc@136
|
353 *s1 = c;
|
adamc@136
|
354 }
|
adamc@136
|
355 }
|
adamc@136
|
356 *s1++ = 0;
|
adamc@136
|
357 ctx->heap_front = s1;
|
adamc@136
|
358 *s = new_s;
|
adamc@136
|
359 return r;
|
adamc@120
|
360 }
|
adamc@135
|
361
|
adamc@135
|
362
|
adamc@136
|
363 char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@137
|
364 char *r, *s2;
|
adamc@137
|
365
|
adamc@137
|
366 lw_check_heap(ctx, strlen(s) * 5 + 1);
|
adamc@137
|
367
|
adamc@137
|
368 for (r = s2 = ctx->heap_front; *s; s++) {
|
adamc@137
|
369 char c = *s;
|
adamc@137
|
370
|
adamc@137
|
371 switch (c) {
|
adamc@137
|
372 case '<':
|
adamc@137
|
373 strcpy(s2, "<");
|
adamc@137
|
374 s2 += 4;
|
adamc@137
|
375 break;
|
adamc@137
|
376 case '&':
|
adamc@137
|
377 strcpy(s2, "&");
|
adamc@137
|
378 s2 += 5;
|
adamc@137
|
379 break;
|
adamc@137
|
380 default:
|
adamc@137
|
381 if (isprint(c))
|
adamc@137
|
382 *s2++ = c;
|
adamc@137
|
383 else {
|
adamc@137
|
384 int len2;
|
adamc@137
|
385 sprintf(s2, "&#%d;%n", c, &len2);
|
adamc@137
|
386 s2 += len2;
|
adamc@137
|
387 }
|
adamc@137
|
388 }
|
adamc@137
|
389 }
|
adamc@137
|
390
|
adamc@137
|
391 *s2++ = 0;
|
adamc@137
|
392 ctx->heap_front = s2;
|
adamc@137
|
393 return r;
|
adamc@135
|
394 }
|
adamc@135
|
395
|
adamc@135
|
396 void lw_Basis_htmlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@135
|
397 lw_check(ctx, strlen(s) * 5);
|
adamc@135
|
398
|
adamc@135
|
399 for (; *s; s++) {
|
adamc@135
|
400 char c = *s;
|
adamc@135
|
401
|
adamc@135
|
402 switch (c) {
|
adamc@135
|
403 case '<':
|
adamc@135
|
404 lw_write_unsafe(ctx, "<");
|
adamc@135
|
405 break;
|
adamc@135
|
406 case '&':
|
adamc@135
|
407 lw_write_unsafe(ctx, "&");
|
adamc@135
|
408 break;
|
adamc@135
|
409 default:
|
adamc@135
|
410 if (isprint(c))
|
adamc@135
|
411 lw_writec_unsafe(ctx, c);
|
adamc@135
|
412 else {
|
adamc@135
|
413 lw_write_unsafe(ctx, "&#");
|
adamc@135
|
414 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@135
|
415 lw_writec_unsafe(ctx, ';');
|
adamc@135
|
416 }
|
adamc@135
|
417 }
|
adamc@135
|
418 }
|
adamc@135
|
419 }
|