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@136
|
123 ctx->heap_front += len;
|
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@136
|
130 lw_check_heap(ctx, INTS_MAX);
|
adamc@136
|
131 result = ctx->heap_front;
|
adamc@136
|
132 sprintf(result, "%g%n", n, &len);
|
adamc@136
|
133 ctx->heap_front += len;
|
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@136
|
140 lw_check_heap(ctx, len * 6);
|
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@136
|
163 ctx->heap_front = p;
|
adamc@136
|
164 return result;
|
adamc@106
|
165 }
|
adamc@106
|
166
|
adamc@117
|
167 static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
168 int len;
|
adamc@117
|
169
|
adamc@117
|
170 sprintf(ctx->page_front, "%d%n", n, &len);
|
adamc@117
|
171 ctx->page_front += len;
|
adamc@106
|
172 }
|
adamc@106
|
173
|
adamc@117
|
174 void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
175 lw_check(ctx, INTS_MAX);
|
adamc@117
|
176 lw_Basis_attrifyInt_w_unsafe(ctx, n);
|
adamc@106
|
177 }
|
adamc@106
|
178
|
adamc@117
|
179 void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@117
|
180 int len;
|
adamc@117
|
181
|
adamc@117
|
182 lw_check(ctx, FLOATS_MAX);
|
adamc@117
|
183 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@117
|
184 ctx->page_front += len;
|
adamc@117
|
185 }
|
adamc@117
|
186
|
adamc@117
|
187 void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@117
|
188 lw_check(ctx, strlen(s) * 6);
|
adamc@117
|
189
|
adamc@106
|
190 for (; *s; s++) {
|
adamc@106
|
191 char c = *s;
|
adamc@106
|
192
|
adamc@106
|
193 if (c == '"')
|
adamc@117
|
194 lw_write_unsafe(ctx, """);
|
adamc@136
|
195 else if (c == '&')
|
adamc@136
|
196 lw_write_unsafe(ctx, "&");
|
adamc@106
|
197 else if (isprint(c))
|
adamc@117
|
198 lw_writec_unsafe(ctx, c);
|
adamc@106
|
199 else {
|
adamc@117
|
200 lw_write_unsafe(ctx, "&#");
|
adamc@117
|
201 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@117
|
202 lw_writec_unsafe(ctx, ';');
|
adamc@106
|
203 }
|
adamc@106
|
204 }
|
adamc@106
|
205 }
|
adamc@120
|
206
|
adamc@120
|
207
|
adamc@120
|
208 char *lw_Basis_urlifyInt(lw_Basis_int n) {
|
adamc@120
|
209 return "0";
|
adamc@120
|
210 }
|
adamc@120
|
211
|
adamc@120
|
212 char *lw_Basis_urlifyFloat(lw_Basis_float n) {
|
adamc@120
|
213 return "0.0";
|
adamc@120
|
214 }
|
adamc@120
|
215
|
adamc@120
|
216 char *lw_Basis_urlifyString(lw_Basis_string s) {
|
adamc@120
|
217 return "";
|
adamc@120
|
218 }
|
adamc@120
|
219
|
adamc@120
|
220 static void lw_Basis_urlifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
221 int len;
|
adamc@120
|
222
|
adamc@120
|
223 sprintf(ctx->page_front, "%d%n", n, &len);
|
adamc@120
|
224 ctx->page_front += len;
|
adamc@120
|
225 }
|
adamc@120
|
226
|
adamc@120
|
227 void lw_Basis_urlifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
228 lw_check(ctx, INTS_MAX);
|
adamc@120
|
229 lw_Basis_urlifyInt_w_unsafe(ctx, n);
|
adamc@120
|
230 }
|
adamc@120
|
231
|
adamc@120
|
232 void lw_Basis_urlifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@120
|
233 int len;
|
adamc@120
|
234
|
adamc@120
|
235 lw_check(ctx, FLOATS_MAX);
|
adamc@120
|
236 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@120
|
237 ctx->page_front += len;
|
adamc@120
|
238 }
|
adamc@120
|
239
|
adamc@120
|
240 void lw_Basis_urlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@120
|
241 lw_check(ctx, strlen(s) * 3);
|
adamc@120
|
242
|
adamc@120
|
243 for (; *s; s++) {
|
adamc@120
|
244 char c = *s;
|
adamc@120
|
245
|
adamc@120
|
246 if (c == ' ')
|
adamc@120
|
247 lw_writec_unsafe(ctx, '+');
|
adamc@120
|
248 else if (isalnum(c))
|
adamc@120
|
249 lw_writec_unsafe(ctx, c);
|
adamc@120
|
250 else {
|
adamc@120
|
251 sprintf(ctx->page_front, "%%%02X", c);
|
adamc@120
|
252 ctx->page_front += 3;
|
adamc@120
|
253 }
|
adamc@120
|
254 }
|
adamc@120
|
255 }
|
adamc@120
|
256
|
adamc@120
|
257
|
adamc@120
|
258 lw_Basis_int lw_unurlifyInt(char **s) {
|
adamc@120
|
259 char *new_s = strchr(*s, '/');
|
adamc@120
|
260 int r;
|
adamc@120
|
261
|
adamc@120
|
262 if (new_s)
|
adamc@120
|
263 *new_s++ = 0;
|
adamc@120
|
264 else
|
adamc@120
|
265 new_s = strchr(*s, 0);
|
adamc@120
|
266
|
adamc@120
|
267 r = atoi(*s);
|
adamc@120
|
268 *s = new_s;
|
adamc@120
|
269 return r;
|
adamc@120
|
270 }
|
adamc@120
|
271
|
adamc@120
|
272 lw_Basis_float lw_unurlifyFloat(char **s) {
|
adamc@120
|
273 char *new_s = strchr(*s, '/');
|
adamc@120
|
274 int r;
|
adamc@120
|
275
|
adamc@120
|
276 if (new_s)
|
adamc@120
|
277 *new_s++ = 0;
|
adamc@120
|
278 else
|
adamc@120
|
279 new_s = strchr(*s, 0);
|
adamc@120
|
280
|
adamc@120
|
281 r = atof(*s);
|
adamc@120
|
282 *s = new_s;
|
adamc@120
|
283 return r;
|
adamc@120
|
284 }
|
adamc@120
|
285
|
adamc@136
|
286 lw_Basis_string lw_unurlifyString(lw_context ctx, char **s) {
|
adamc@136
|
287 char *new_s = strchr(*s, '/');
|
adamc@136
|
288 char *r, *s1, *s2;
|
adamc@136
|
289 int len, n;
|
adamc@136
|
290
|
adamc@136
|
291 if (new_s)
|
adamc@136
|
292 *new_s++ = 0;
|
adamc@136
|
293 else
|
adamc@136
|
294 new_s = strchr(*s, 0);
|
adamc@136
|
295
|
adamc@136
|
296 len = strlen(*s);
|
adamc@136
|
297 lw_check_heap(ctx, len + 1);
|
adamc@136
|
298
|
adamc@136
|
299 r = ctx->heap_front;
|
adamc@136
|
300 for (s1 = r, s2 = *s; *s2; ++s1, ++s2) {
|
adamc@136
|
301 char c = *s2;
|
adamc@136
|
302
|
adamc@136
|
303 switch (c) {
|
adamc@136
|
304 case '+':
|
adamc@136
|
305 *s1 = ' ';
|
adamc@136
|
306 break;
|
adamc@136
|
307 case '%':
|
adamc@136
|
308 assert(s2 + 2 < new_s);
|
adamc@136
|
309 sscanf(s2+1, "%02X", &n);
|
adamc@136
|
310 *s1 = n;
|
adamc@136
|
311 s2 += 2;
|
adamc@136
|
312 break;
|
adamc@136
|
313 default:
|
adamc@136
|
314 *s1 = c;
|
adamc@136
|
315 }
|
adamc@136
|
316 }
|
adamc@136
|
317 *s1++ = 0;
|
adamc@136
|
318 ctx->heap_front = s1;
|
adamc@136
|
319 *s = new_s;
|
adamc@136
|
320 return r;
|
adamc@120
|
321 }
|
adamc@135
|
322
|
adamc@135
|
323
|
adamc@136
|
324 char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@135
|
325 return "";
|
adamc@135
|
326 }
|
adamc@135
|
327
|
adamc@135
|
328 void lw_Basis_htmlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@135
|
329 lw_check(ctx, strlen(s) * 5);
|
adamc@135
|
330
|
adamc@135
|
331 for (; *s; s++) {
|
adamc@135
|
332 char c = *s;
|
adamc@135
|
333
|
adamc@135
|
334 switch (c) {
|
adamc@135
|
335 case '<':
|
adamc@135
|
336 lw_write_unsafe(ctx, "<");
|
adamc@135
|
337 break;
|
adamc@135
|
338 case '&':
|
adamc@135
|
339 lw_write_unsafe(ctx, "&");
|
adamc@135
|
340 break;
|
adamc@135
|
341 default:
|
adamc@135
|
342 if (isprint(c))
|
adamc@135
|
343 lw_writec_unsafe(ctx, c);
|
adamc@135
|
344 else {
|
adamc@135
|
345 lw_write_unsafe(ctx, "&#");
|
adamc@135
|
346 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@135
|
347 lw_writec_unsafe(ctx, ';');
|
adamc@135
|
348 }
|
adamc@135
|
349 }
|
adamc@135
|
350 }
|
adamc@135
|
351 }
|