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