annotate src/c/lacweb.c @ 136:133fa2d51bb4

Dynamic arena allocation
author Adam Chlipala <adamc@hcoop.net>
date Thu, 17 Jul 2008 14:18:57 -0400
parents b1cfe49ce692
children 4ffdbf429e8d
rev   line source
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, "&quot;");
adamc@136 149 p += 6;
adamc@136 150 } else if (c == '&') {
adamc@136 151 strcpy(p, "&amp;");
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, "&quot;");
adamc@136 195 else if (c == '&')
adamc@136 196 lw_write_unsafe(ctx, "&amp;");
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, "&lt;");
adamc@135 337 break;
adamc@135 338 case '&':
adamc@135 339 lw_write_unsafe(ctx, "&amp;");
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 }