annotate src/c/urweb.c @ 643:aa2290c32ce2

Avoid any JavaScript when pages don't need it; update demo prose
author Adam Chlipala <adamc@hcoop.net>
date Tue, 10 Mar 2009 10:44:26 -0400
parents 889dc9fceb3a
children 1b571a05874c
rev   line source
adamc@436 1 #define _XOPEN_SOURCE
adamc@436 2
adamc@117 3 #include <stdlib.h>
adamc@102 4 #include <stdio.h>
adamc@117 5 #include <string.h>
adamc@457 6 #include <strings.h>
adamc@106 7 #include <ctype.h>
adamc@167 8 #include <setjmp.h>
adamc@167 9 #include <stdarg.h>
adamc@102 10
adamc@102 11 #include "types.h"
adamc@102 12
adamc@311 13 uw_unit uw_unit_v = {};
adamc@102 14
adamc@167 15 #define ERROR_BUF_LEN 1024
adamc@167 16
adamc@323 17 typedef struct regions {
adamc@323 18 struct regions *next;
adamc@323 19 } regions;
adamc@323 20
adamc@425 21 typedef struct {
adamc@425 22 void (*func)(void*);
adamc@425 23 void *arg;
adamc@425 24 } cleanup;
adamc@425 25
adamc@311 26 struct uw_context {
adamc@458 27 char *headers, *headers_end;
adamc@457 28
adamc@462 29 char *outHeaders, *outHeaders_front, *outHeaders_back;
adamc@117 30 char *page, *page_front, *page_back;
adamc@136 31 char *heap, *heap_front, *heap_back;
adamc@144 32 char **inputs;
adamc@167 33
adamc@562 34 char *script, *script_front, *script_back;
adamc@565 35 int source_count;
adamc@562 36
adamc@272 37 void *db;
adamc@272 38
adamc@167 39 jmp_buf jmp_buf;
adamc@167 40
adamc@323 41 regions *regions;
adamc@323 42
adamc@425 43 cleanup *cleanup, *cleanup_front, *cleanup_back;
adamc@425 44
adamc@643 45 const char *script_header;
adamc@643 46
adamc@167 47 char error_message[ERROR_BUF_LEN];
adamc@117 48 };
adamc@117 49
adamc@311 50 extern int uw_inputs_len;
adamc@144 51
adamc@562 52 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) {
adamc@311 53 uw_context ctx = malloc(sizeof(struct uw_context));
adamc@136 54
adamc@458 55 ctx->headers = ctx->headers_end = NULL;
adamc@457 56
adamc@462 57 ctx->outHeaders_front = ctx->outHeaders = malloc(outHeaders_len);
adamc@462 58 ctx->outHeaders_back = ctx->outHeaders_front + outHeaders_len;
adamc@462 59
adamc@462 60 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@462 61
adamc@117 62 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 63 ctx->page_back = ctx->page_front + page_len;
adamc@136 64
adamc@136 65 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 66 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 67
adamc@311 68 ctx->inputs = calloc(uw_inputs_len, sizeof(char *));
adamc@144 69
adamc@272 70 ctx->db = NULL;
adamc@272 71
adamc@323 72 ctx->regions = NULL;
adamc@323 73
adamc@425 74 ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
adamc@425 75
adamc@643 76 ctx->script_header = "";
adamc@643 77
adamc@167 78 ctx->error_message[0] = 0;
adamc@167 79
adamc@562 80 ctx->script_front = ctx->script = malloc(script_len);
adamc@562 81 ctx->script_back = ctx->script_front + script_len;
adamc@565 82 ctx->source_count = 0;
adamc@562 83
adamc@117 84 return ctx;
adamc@106 85 }
adamc@106 86
adamc@311 87 void uw_set_db(uw_context ctx, void *db) {
adamc@272 88 ctx->db = db;
adamc@272 89 }
adamc@272 90
adamc@311 91 void *uw_get_db(uw_context ctx) {
adamc@272 92 return ctx->db;
adamc@272 93 }
adamc@272 94
adamc@311 95 void uw_free(uw_context ctx) {
adamc@462 96 free(ctx->outHeaders);
adamc@562 97 free(ctx->script);
adamc@117 98 free(ctx->page);
adamc@136 99 free(ctx->heap);
adamc@144 100 free(ctx->inputs);
adamc@425 101 free(ctx->cleanup);
adamc@136 102 free(ctx);
adamc@136 103 }
adamc@136 104
adamc@562 105 void uw_reset_keep_error_message(uw_context ctx) {
adamc@462 106 ctx->outHeaders_front = ctx->outHeaders;
adamc@562 107 ctx->script_front = ctx->script;
adamc@138 108 ctx->page_front = ctx->page;
adamc@138 109 ctx->heap_front = ctx->heap;
adamc@323 110 ctx->regions = NULL;
adamc@425 111 ctx->cleanup_front = ctx->cleanup;
adamc@565 112 ctx->source_count = 0;
adamc@167 113 }
adamc@167 114
adamc@562 115 void uw_reset_keep_request(uw_context ctx) {
adamc@562 116 uw_reset_keep_error_message(ctx);
adamc@562 117 ctx->error_message[0] = 0;
adamc@167 118 }
adamc@167 119
adamc@311 120 void uw_reset(uw_context ctx) {
adamc@311 121 uw_reset_keep_request(ctx);
adamc@311 122 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *));
adamc@144 123 }
adamc@144 124
adamc@311 125 void uw_db_init(uw_context);
adamc@311 126 void uw_handle(uw_context, char *);
adamc@167 127
adamc@311 128 failure_kind uw_begin_init(uw_context ctx) {
adamc@272 129 int r = setjmp(ctx->jmp_buf);
adamc@272 130
adamc@272 131 if (r == 0)
adamc@311 132 uw_db_init(ctx);
adamc@272 133
adamc@272 134 return r;
adamc@272 135 }
adamc@272 136
adamc@458 137 void uw_set_headers(uw_context ctx, char *headers) {
adamc@458 138 char *s = headers, *s2;
adamc@458 139 ctx->headers = headers;
adamc@458 140
adamc@458 141 while (s2 = strchr(s, '\r')) {
adamc@458 142 s = s2;
adamc@458 143
adamc@458 144 if (s[1] == 0)
adamc@458 145 break;
adamc@458 146
adamc@458 147 *s = 0;
adamc@458 148 s += 2;
adamc@458 149 }
adamc@458 150
adamc@458 151 ctx->headers_end = s;
adamc@458 152 }
adamc@458 153
adamc@458 154 failure_kind uw_begin(uw_context ctx, char *path) {
adamc@190 155 int r = setjmp(ctx->jmp_buf);
adamc@190 156
adamc@190 157 if (r == 0)
adamc@311 158 uw_handle(ctx, path);
adamc@167 159
adamc@190 160 return r;
adamc@167 161 }
adamc@167 162
adamc@311 163 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
adamc@425 164 cleanup *cl;
adamc@425 165
adamc@167 166 va_list ap;
adamc@167 167 va_start(ap, fmt);
adamc@167 168
adamc@167 169 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
adamc@167 170
adamc@425 171 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
adamc@425 172 cl->func(cl->arg);
adamc@425 173
adamc@425 174 ctx->cleanup_front = ctx->cleanup;
adamc@425 175
adamc@190 176 longjmp(ctx->jmp_buf, fk);
adamc@167 177 }
adamc@167 178
adamc@425 179 void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
adamc@425 180 if (ctx->cleanup_front >= ctx->cleanup_back) {
adamc@425 181 int len = ctx->cleanup_back - ctx->cleanup, newLen;
adamc@425 182 if (len == 0)
adamc@425 183 newLen = 1;
adamc@425 184 else
adamc@428 185 newLen = len * 2;
adamc@470 186 ctx->cleanup = realloc(ctx->cleanup, newLen * sizeof(cleanup));
adamc@425 187 ctx->cleanup_front = ctx->cleanup + len;
adamc@425 188 ctx->cleanup_back = ctx->cleanup + newLen;
adamc@425 189 }
adamc@425 190
adamc@425 191 ctx->cleanup_front->func = func;
adamc@425 192 ctx->cleanup_front->arg = arg;
adamc@425 193 ++ctx->cleanup_front;
adamc@425 194 }
adamc@425 195
adamc@425 196 void uw_pop_cleanup(uw_context ctx) {
adamc@425 197 if (ctx->cleanup_front == ctx->cleanup)
adamc@425 198 uw_error(ctx, FATAL, "Attempt to pop from empty cleanup action stack");
adamc@425 199
adamc@425 200 --ctx->cleanup_front;
adamc@425 201 ctx->cleanup_front->func(ctx->cleanup_front->arg);
adamc@425 202 }
adamc@425 203
adamc@311 204 char *uw_error_message(uw_context ctx) {
adamc@167 205 return ctx->error_message;
adamc@167 206 }
adamc@167 207
adamc@311 208 int uw_input_num(char*);
adamc@144 209
adamc@311 210 void uw_set_input(uw_context ctx, char *name, char *value) {
adamc@311 211 int n = uw_input_num(name);
adamc@144 212
adamc@169 213 if (n < 0)
adamc@311 214 uw_error(ctx, FATAL, "Bad input name %s", name);
adamc@144 215
adamc@311 216 if (n >= uw_inputs_len)
adamc@311 217 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
adamc@169 218
adamc@144 219 ctx->inputs[n] = value;
adamc@144 220
adamc@282 221 //printf("[%d] %s = %s\n", n, name, value);
adamc@144 222 }
adamc@144 223
adamc@311 224 char *uw_get_input(uw_context ctx, int n) {
adamc@169 225 if (n < 0)
adamc@311 226 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 227 if (n >= uw_inputs_len)
adamc@311 228 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@282 229 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@144 230 return ctx->inputs[n];
adamc@138 231 }
adamc@138 232
adamc@311 233 char *uw_get_optional_input(uw_context ctx, int n) {
adamc@190 234 if (n < 0)
adamc@311 235 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 236 if (n >= uw_inputs_len)
adamc@311 237 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@426 238 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@190 239 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
adamc@190 240 }
adamc@190 241
adamc@643 242 void uw_set_script_header(uw_context ctx, const char *s) {
adamc@643 243 ctx->script_header = s;
adamc@643 244 }
adamc@643 245
adamc@311 246 static void uw_check_heap(uw_context ctx, size_t extra) {
adamc@136 247 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@321 248 size_t desired = ctx->heap_front - ctx->heap + extra, next;
adamc@136 249 char *new_heap;
adamc@136 250
adamc@317 251 next = ctx->heap_back - ctx->heap;
adamc@317 252 if (next == 0)
adamc@317 253 next = 1;
adamc@317 254 for (; next < desired; next *= 2);
adamc@136 255
adamc@136 256 new_heap = realloc(ctx->heap, next);
adamc@321 257 ctx->heap_front = new_heap + (ctx->heap_front - ctx->heap);
adamc@169 258 ctx->heap_back = new_heap + next;
adamc@136 259
adamc@136 260 if (new_heap != ctx->heap) {
adamc@136 261 ctx->heap = new_heap;
adamc@311 262 uw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
adamc@136 263 }
adamc@136 264
adamc@169 265 ctx->heap = new_heap;
adamc@136 266 }
adamc@136 267 }
adamc@136 268
adamc@311 269 void *uw_malloc(uw_context ctx, size_t len) {
adamc@136 270 void *result;
adamc@136 271
adamc@311 272 uw_check_heap(ctx, len);
adamc@136 273
adamc@136 274 result = ctx->heap_front;
adamc@136 275 ctx->heap_front += len;
adamc@136 276 return result;
adamc@117 277 }
adamc@117 278
adamc@323 279 void uw_begin_region(uw_context ctx) {
adamc@323 280 regions *r = (regions *) ctx->heap_front;
adamc@323 281
adamc@323 282 uw_check_heap(ctx, sizeof(regions));
adamc@323 283
adamc@323 284 ctx->heap_front += sizeof(regions);
adamc@323 285
adamc@323 286 r->next = ctx->regions;
adamc@323 287 ctx->regions = r;
adamc@323 288 }
adamc@323 289
adamc@323 290 void uw_end_region(uw_context ctx) {
adamc@323 291 regions *r = ctx->regions;
adamc@323 292
adamc@323 293 if (r == NULL)
adamc@323 294 uw_error(ctx, FATAL, "Region stack underflow");
adamc@323 295
adamc@323 296 ctx->heap_front = (char *) r;
adamc@323 297 ctx->regions = r->next;
adamc@323 298 }
adamc@323 299
adamc@324 300 void uw_memstats(uw_context ctx) {
adamc@462 301 printf("Headers: %d/%d\n", ctx->outHeaders_front - ctx->outHeaders, ctx->outHeaders_back - ctx->outHeaders);
adamc@562 302 printf("Script: %d/%d\n", ctx->script_front - ctx->script, ctx->script_back - ctx->script);
adamc@324 303 printf("Page: %d/%d\n", ctx->page_front - ctx->page, ctx->page_back - ctx->page);
adamc@324 304 printf("Heap: %d/%d\n", ctx->heap_front - ctx->heap, ctx->heap_back - ctx->heap);
adamc@324 305 }
adamc@324 306
adamc@436 307 int uw_really_send(int sock, const void *buf, size_t len) {
adamc@117 308 while (len > 0) {
adamc@436 309 size_t n = send(sock, buf, len, 0);
adamc@117 310
adamc@117 311 if (n < 0)
adamc@117 312 return n;
adamc@117 313
adamc@117 314 buf += n;
adamc@117 315 len -= n;
adamc@117 316 }
adamc@117 317
adamc@117 318 return 0;
adamc@117 319 }
adamc@117 320
adamc@311 321 int uw_send(uw_context ctx, int sock) {
adamc@462 322 int n = uw_really_send(sock, ctx->outHeaders, ctx->outHeaders_front - ctx->outHeaders);
adamc@462 323
adamc@462 324 if (n < 0)
adamc@462 325 return n;
adamc@462 326
adamc@462 327 n = uw_really_send(sock, "\r\n", 2);
adamc@462 328
adamc@462 329 if (n < 0)
adamc@462 330 return n;
adamc@462 331
adamc@464 332 return uw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@462 333 }
adamc@462 334
adamc@462 335 static void uw_check_headers(uw_context ctx, size_t extra) {
adamc@462 336 size_t desired = ctx->outHeaders_front - ctx->outHeaders + extra, next;
adamc@462 337 char *new_outHeaders;
adamc@462 338
adamc@462 339 next = ctx->outHeaders_back - ctx->outHeaders;
adamc@462 340 if (next < desired) {
adamc@462 341 if (next == 0)
adamc@462 342 next = 1;
adamc@462 343 for (; next < desired; next *= 2);
adamc@462 344
adamc@462 345 new_outHeaders = realloc(ctx->outHeaders, next);
adamc@462 346 ctx->outHeaders_front = new_outHeaders + (ctx->outHeaders_front - ctx->outHeaders);
adamc@462 347 ctx->outHeaders_back = new_outHeaders + next;
adamc@462 348 ctx->outHeaders = new_outHeaders;
adamc@462 349 }
adamc@462 350 }
adamc@462 351
adamc@462 352 void uw_write_header(uw_context ctx, uw_Basis_string s) {
adamc@462 353 int len = strlen(s);
adamc@462 354
adamc@462 355 uw_check_headers(ctx, len + 1);
adamc@462 356 strcpy(ctx->outHeaders_front, s);
adamc@462 357 ctx->outHeaders_front += len;
adamc@562 358 }
adamc@562 359
adamc@562 360 static void uw_check_script(uw_context ctx, size_t extra) {
adamc@562 361 size_t desired = ctx->script_front - ctx->script + extra, next;
adamc@562 362 char *new_script;
adamc@562 363
adamc@562 364 next = ctx->script_back - ctx->script;
adamc@562 365 if (next < desired) {
adamc@562 366 if (next == 0)
adamc@562 367 next = 1;
adamc@562 368 for (; next < desired; next *= 2);
adamc@562 369
adamc@562 370 new_script = realloc(ctx->script, next);
adamc@562 371 ctx->script_front = new_script + (ctx->script_front - ctx->script);
adamc@562 372 ctx->script_back = new_script + next;
adamc@562 373 ctx->script = new_script;
adamc@562 374 }
adamc@562 375 }
adamc@562 376
adamc@562 377 void uw_write_script(uw_context ctx, uw_Basis_string s) {
adamc@562 378 int len = strlen(s);
adamc@562 379
adamc@562 380 uw_check_script(ctx, len + 1);
adamc@562 381 strcpy(ctx->script_front, s);
adamc@562 382 ctx->script_front += len;
adamc@562 383 }
adamc@562 384
adamc@565 385 char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
adamc@565 386 if (ctx->script_front == ctx->script) {
adamc@565 387 char *r = uw_malloc(ctx, 1);
adamc@565 388 r[0] = 0;
adamc@565 389 return r;
adamc@565 390 } else {
adamc@643 391 char *r = uw_malloc(ctx, 41 + (ctx->script_front - ctx->script) + strlen(ctx->script_header));
adamc@565 392
adamc@643 393 sprintf(r, "%s<script>%s</script>", ctx->script_header, ctx->script);
adamc@565 394 return r;
adamc@565 395 }
adamc@565 396 }
adamc@565 397
adamc@574 398 uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
adamc@574 399 char *r, *s2;
adamc@574 400
adamc@574 401 uw_check_heap(ctx, strlen(s) * 4 + 2);
adamc@574 402
adamc@574 403 r = s2 = ctx->heap_front;
adamc@574 404 *s2++ = '"';
adamc@574 405
adamc@574 406 for (; *s; s++) {
adamc@574 407 char c = *s;
adamc@574 408
adamc@574 409 switch (c) {
adamc@574 410 case '"':
adamc@574 411 strcpy(s2, "\\\"");
adamc@574 412 s2 += 2;
adamc@574 413 break;
adamc@574 414 case '\\':
adamc@574 415 strcpy(s2, "\\\\");
adamc@574 416 s2 += 2;
adamc@574 417 break;
adamc@574 418 default:
adamc@574 419 if (isprint(c))
adamc@574 420 *s2++ = c;
adamc@574 421 else {
adamc@574 422 sprintf(s2, "\\%3o", c);
adamc@574 423 s2 += 4;
adamc@574 424 }
adamc@574 425 }
adamc@574 426 }
adamc@574 427
adamc@574 428 strcpy(s2, "\"");
adamc@574 429 ctx->heap_front = s2 + 1;
adamc@574 430 return r;
adamc@574 431 }
adamc@574 432
adamc@574 433 uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) {
adamc@574 434 char *r, *s2;
adamc@574 435
adamc@574 436 uw_check_script(ctx, strlen(s) * 4 + 2);
adamc@574 437
adamc@574 438 r = s2 = ctx->script_front;
adamc@574 439 *s2++ = '"';
adamc@574 440
adamc@574 441 for (; *s; s++) {
adamc@574 442 char c = *s;
adamc@574 443
adamc@574 444 switch (c) {
adamc@577 445 case '\'':
adamc@574 446 strcpy(s2, "\\\"");
adamc@574 447 s2 += 2;
adamc@574 448 break;
adamc@574 449 case '\\':
adamc@574 450 strcpy(s2, "\\\\");
adamc@574 451 s2 += 2;
adamc@574 452 break;
adamc@574 453 default:
adamc@574 454 if (isprint(c))
adamc@574 455 *s2++ = c;
adamc@574 456 else {
adamc@574 457 sprintf(s2, "\\%3o", c);
adamc@574 458 s2 += 4;
adamc@574 459 }
adamc@574 460 }
adamc@574 461 }
adamc@574 462
adamc@574 463 strcpy(s2, "\"");
adamc@574 464 ctx->script_front = s2 + 1;
adamc@574 465 return r;
adamc@574 466 }
adamc@574 467
adamc@577 468 uw_Basis_int uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
adamc@577 469 int len;
adamc@577 470 size_t s_len = strlen(s);
adamc@562 471
adamc@577 472 uw_check_script(ctx, 12 + INTS_MAX + s_len);
adamc@574 473 sprintf(ctx->script_front, "var s%d=sc(%n", ctx->source_count, &len);
adamc@562 474 ctx->script_front += len;
adamc@577 475 strcpy(ctx->script_front, s);
adamc@577 476 ctx->script_front += s_len;
adamc@577 477 strcpy(ctx->script_front, ");");
adamc@577 478 ctx->script_front += 2;
adamc@562 479
adamc@565 480 return ctx->source_count++;
adamc@117 481 }
adamc@117 482
adamc@577 483 uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_int n, uw_Basis_string s) {
adamc@577 484 int len;
adamc@577 485 size_t s_len = strlen(s);
adamc@577 486
adamc@577 487 uw_check_script(ctx, 6 + INTS_MAX + s_len);
adamc@577 488 sprintf(ctx->script_front, "s%d.v=%n", (int)n, &len);
adamc@577 489 ctx->script_front += len;
adamc@577 490 strcpy(ctx->script_front, s);
adamc@577 491 ctx->script_front += s_len;
adamc@577 492 strcpy(ctx->script_front, ";");
adamc@577 493 ctx->script_front++;
adamc@577 494
adamc@577 495 return uw_unit_v;
adamc@577 496 }
adamc@577 497
adamc@311 498 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 499 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 500 char *new_page;
adamc@117 501
adamc@317 502 next = ctx->page_back - ctx->page;
adamc@428 503 if (next < desired) {
adamc@428 504 if (next == 0)
adamc@428 505 next = 1;
adamc@428 506 for (; next < desired; next *= 2);
adamc@117 507
adamc@428 508 new_page = realloc(ctx->page, next);
adamc@428 509 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 510 ctx->page_back = new_page + next;
adamc@428 511 ctx->page = new_page;
adamc@428 512 }
adamc@117 513 }
adamc@117 514
adamc@311 515 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 516 *(ctx->page_front)++ = c;
adamc@117 517 }
adamc@117 518
adamc@311 519 void uw_writec(uw_context ctx, char c) {
adamc@311 520 uw_check(ctx, 1);
adamc@311 521 uw_writec_unsafe(ctx, c);
adamc@117 522 }
adamc@117 523
adamc@311 524 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 525 int len = strlen(s);
adamc@117 526 memcpy(ctx->page_front, s, len);
adamc@117 527 ctx->page_front += len;
adamc@117 528 }
adamc@117 529
adamc@311 530 void uw_write(uw_context ctx, const char* s) {
adamc@311 531 uw_check(ctx, strlen(s) + 1);
adamc@311 532 uw_write_unsafe(ctx, s);
adamc@183 533 *ctx->page_front = 0;
adamc@102 534 }
adamc@106 535
adamc@135 536
adamc@311 537 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 538 char *result;
adamc@136 539 int len;
adamc@311 540 uw_check_heap(ctx, INTS_MAX);
adamc@136 541 result = ctx->heap_front;
adamc@276 542 sprintf(result, "%lld%n", n, &len);
adamc@137 543 ctx->heap_front += len+1;
adamc@136 544 return result;
adamc@106 545 }
adamc@106 546
adamc@311 547 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 548 char *result;
adamc@136 549 int len;
adamc@311 550 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 551 result = ctx->heap_front;
adamc@136 552 sprintf(result, "%g%n", n, &len);
adamc@137 553 ctx->heap_front += len+1;
adamc@136 554 return result;
adamc@106 555 }
adamc@106 556
adamc@311 557 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 558 int len = strlen(s);
adamc@136 559 char *result, *p;
adamc@311 560 uw_check_heap(ctx, len * 6 + 1);
adamc@136 561
adamc@136 562 result = p = ctx->heap_front;
adamc@136 563
adamc@136 564 for (; *s; s++) {
adamc@136 565 char c = *s;
adamc@136 566
adamc@136 567 if (c == '"') {
adamc@136 568 strcpy(p, "&quot;");
adamc@136 569 p += 6;
adamc@136 570 } else if (c == '&') {
adamc@136 571 strcpy(p, "&amp;");
adamc@136 572 p += 5;
adamc@136 573 }
adamc@136 574 else if (isprint(c))
adamc@136 575 *p++ = c;
adamc@136 576 else {
adamc@136 577 int len2;
adamc@136 578 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 579 p += len2;
adamc@136 580 }
adamc@136 581 }
adamc@136 582
adamc@137 583 *p++ = 0;
adamc@136 584 ctx->heap_front = p;
adamc@136 585 return result;
adamc@106 586 }
adamc@106 587
adamc@311 588 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 589 int len;
adamc@117 590
adamc@276 591 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 592 ctx->page_front += len;
adamc@106 593 }
adamc@106 594
adamc@428 595 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 596 uw_check(ctx, INTS_MAX);
adamc@311 597 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 598
adamc@428 599 return uw_unit_v;
adamc@106 600 }
adamc@106 601
adamc@428 602 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 603 int len;
adamc@117 604
adamc@311 605 uw_check(ctx, FLOATS_MAX);
adamc@117 606 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 607 ctx->page_front += len;
adamc@428 608
adamc@428 609 return uw_unit_v;
adamc@117 610 }
adamc@117 611
adamc@428 612 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 613 uw_check(ctx, strlen(s) * 6);
adamc@117 614
adamc@106 615 for (; *s; s++) {
adamc@106 616 char c = *s;
adamc@106 617
adamc@106 618 if (c == '"')
adamc@311 619 uw_write_unsafe(ctx, "&quot;");
adamc@136 620 else if (c == '&')
adamc@311 621 uw_write_unsafe(ctx, "&amp;");
adamc@106 622 else if (isprint(c))
adamc@311 623 uw_writec_unsafe(ctx, c);
adamc@106 624 else {
adamc@311 625 uw_write_unsafe(ctx, "&#");
adamc@311 626 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 627 uw_writec_unsafe(ctx, ';');
adamc@106 628 }
adamc@106 629 }
adamc@428 630
adamc@428 631 return uw_unit_v;
adamc@106 632 }
adamc@120 633
adamc@120 634
adamc@311 635 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 636 int len;
adamc@137 637 char *r;
adamc@137 638
adamc@311 639 uw_check_heap(ctx, INTS_MAX);
adamc@137 640 r = ctx->heap_front;
adamc@276 641 sprintf(r, "%lld%n", n, &len);
adamc@137 642 ctx->heap_front += len+1;
adamc@137 643 return r;
adamc@120 644 }
adamc@120 645
adamc@311 646 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 647 int len;
adamc@137 648 char *r;
adamc@137 649
adamc@311 650 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 651 r = ctx->heap_front;
adamc@137 652 sprintf(r, "%g%n", n, &len);
adamc@137 653 ctx->heap_front += len+1;
adamc@137 654 return r;
adamc@120 655 }
adamc@120 656
adamc@311 657 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 658 char *r, *p;
adamc@137 659
adamc@311 660 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 661
adamc@137 662 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 663 char c = *s;
adamc@137 664
adamc@137 665 if (c == ' ')
adamc@137 666 *p++ = '+';
adamc@137 667 else if (isalnum(c))
adamc@137 668 *p++ = c;
adamc@137 669 else {
adamc@137 670 sprintf(p, "%%%02X", c);
adamc@137 671 p += 3;
adamc@137 672 }
adamc@137 673 }
adamc@137 674
adamc@137 675 *p++ = 0;
adamc@137 676 ctx->heap_front = p;
adamc@137 677 return r;
adamc@120 678 }
adamc@120 679
adamc@311 680 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 681 if (b == uw_Basis_False)
adamc@186 682 return "0";
adamc@186 683 else
adamc@186 684 return "1";
adamc@186 685 }
adamc@186 686
adamc@311 687 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 688 int len;
adamc@120 689
adamc@276 690 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 691 ctx->page_front += len;
adamc@120 692 }
adamc@120 693
adamc@428 694 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 695 uw_check(ctx, INTS_MAX);
adamc@311 696 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 697
adamc@428 698 return uw_unit_v;
adamc@120 699 }
adamc@120 700
adamc@428 701 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 702 int len;
adamc@120 703
adamc@311 704 uw_check(ctx, FLOATS_MAX);
adamc@120 705 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 706 ctx->page_front += len;
adamc@428 707
adamc@428 708 return uw_unit_v;
adamc@120 709 }
adamc@120 710
adamc@488 711 uw_Basis_string uw_Basis_urlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@488 712 return uw_Basis_urlifyInt(ctx, t);
adamc@488 713 }
adamc@488 714
adamc@428 715 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 716 uw_check(ctx, strlen(s) * 3);
adamc@120 717
adamc@120 718 for (; *s; s++) {
adamc@120 719 char c = *s;
adamc@120 720
adamc@120 721 if (c == ' ')
adamc@311 722 uw_writec_unsafe(ctx, '+');
adamc@120 723 else if (isalnum(c))
adamc@311 724 uw_writec_unsafe(ctx, c);
adamc@120 725 else {
adamc@120 726 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 727 ctx->page_front += 3;
adamc@120 728 }
adamc@120 729 }
adamc@428 730
adamc@428 731 return uw_unit_v;
adamc@120 732 }
adamc@120 733
adamc@428 734 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 735 if (b == uw_Basis_False)
adamc@311 736 uw_writec(ctx, '0');
adamc@186 737 else
adamc@311 738 uw_writec(ctx, '1');
adamc@428 739
adamc@428 740 return uw_unit_v;
adamc@186 741 }
adamc@186 742
adamc@120 743
adamc@311 744 static char *uw_unurlify_advance(char *s) {
adamc@144 745 char *new_s = strchr(s, '/');
adamc@120 746
adamc@120 747 if (new_s)
adamc@120 748 *new_s++ = 0;
adamc@120 749 else
adamc@144 750 new_s = strchr(s, 0);
adamc@144 751
adamc@144 752 return new_s;
adamc@144 753 }
adamc@144 754
adamc@311 755 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 756 char *new_s = uw_unurlify_advance(*s);
adamc@311 757 uw_Basis_int r;
adamc@120 758
adamc@276 759 r = atoll(*s);
adamc@120 760 *s = new_s;
adamc@120 761 return r;
adamc@120 762 }
adamc@120 763
adamc@311 764 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 765 char *new_s = uw_unurlify_advance(*s);
adamc@311 766 uw_Basis_float r;
adamc@120 767
adamc@120 768 r = atof(*s);
adamc@120 769 *s = new_s;
adamc@120 770 return r;
adamc@120 771 }
adamc@120 772
adamc@488 773 uw_Basis_time uw_Basis_unurlifyTime(uw_context ctx, char **s) {
adamc@488 774 return uw_Basis_unurlifyInt(ctx, s);
adamc@488 775 }
adamc@488 776
adamc@311 777 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 778 char *s1, *s2;
adamc@144 779 int n;
adamc@136 780
adamc@144 781 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 782 char c = *s2;
adamc@136 783
adamc@136 784 switch (c) {
adamc@136 785 case '+':
adamc@136 786 *s1 = ' ';
adamc@136 787 break;
adamc@136 788 case '%':
adamc@169 789 if (s2[1] == 0)
adamc@311 790 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 791 if (s2[2] == 0)
adamc@311 792 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 793 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 794 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 795 *s1 = n;
adamc@136 796 s2 += 2;
adamc@136 797 break;
adamc@136 798 default:
adamc@136 799 *s1 = c;
adamc@136 800 }
adamc@136 801 }
adamc@136 802 *s1++ = 0;
adamc@144 803 return s1;
adamc@144 804 }
adamc@144 805
adamc@311 806 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 807 char *new_s = uw_unurlify_advance(*s);
adamc@311 808 uw_Basis_bool r;
adamc@186 809
adamc@186 810 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 811 r = uw_Basis_False;
adamc@186 812 else
adamc@311 813 r = uw_Basis_True;
adamc@186 814
adamc@186 815 *s = new_s;
adamc@186 816 return r;
adamc@186 817 }
adamc@186 818
adamc@311 819 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 820 char *new_s = uw_unurlify_advance(*s);
adamc@144 821 char *r, *s1, *s2;
adamc@144 822 int len, n;
adamc@144 823
adamc@200 824 len = strlen(*s);
adamc@311 825 uw_check_heap(ctx, len + 1);
adamc@144 826
adamc@144 827 r = ctx->heap_front;
adamc@311 828 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 829 *s = new_s;
adamc@136 830 return r;
adamc@120 831 }
adamc@135 832
adamc@135 833
adamc@311 834 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 835 int len;
adamc@286 836 char *r;
adamc@286 837
adamc@311 838 uw_check_heap(ctx, INTS_MAX);
adamc@286 839 r = ctx->heap_front;
adamc@286 840 sprintf(r, "%lld%n", n, &len);
adamc@286 841 ctx->heap_front += len+1;
adamc@286 842 return r;
adamc@286 843 }
adamc@286 844
adamc@428 845 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 846 int len;
adamc@286 847
adamc@311 848 uw_check(ctx, INTS_MAX);
adamc@286 849 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 850 ctx->page_front += len;
adamc@428 851
adamc@428 852 return uw_unit_v;
adamc@286 853 }
adamc@286 854
adamc@311 855 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 856 int len;
adamc@286 857 char *r;
adamc@286 858
adamc@311 859 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 860 r = ctx->heap_front;
adamc@286 861 sprintf(r, "%g%n", n, &len);
adamc@286 862 ctx->heap_front += len+1;
adamc@286 863 return r;
adamc@286 864 }
adamc@286 865
adamc@428 866 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 867 int len;
adamc@286 868
adamc@311 869 uw_check(ctx, FLOATS_MAX);
adamc@286 870 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 871 ctx->page_front += len;
adamc@428 872
adamc@428 873 return uw_unit_v;
adamc@286 874 }
adamc@286 875
adamc@311 876 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 877 char *r, *s2;
adamc@137 878
adamc@311 879 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 880
adamc@137 881 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 882 char c = *s;
adamc@137 883
adamc@137 884 switch (c) {
adamc@137 885 case '<':
adamc@137 886 strcpy(s2, "&lt;");
adamc@137 887 s2 += 4;
adamc@137 888 break;
adamc@137 889 case '&':
adamc@137 890 strcpy(s2, "&amp;");
adamc@137 891 s2 += 5;
adamc@137 892 break;
adamc@137 893 default:
adamc@137 894 if (isprint(c))
adamc@137 895 *s2++ = c;
adamc@137 896 else {
adamc@137 897 int len2;
adamc@137 898 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 899 s2 += len2;
adamc@137 900 }
adamc@137 901 }
adamc@137 902 }
adamc@137 903
adamc@137 904 *s2++ = 0;
adamc@137 905 ctx->heap_front = s2;
adamc@137 906 return r;
adamc@135 907 }
adamc@135 908
adamc@428 909 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 910 uw_check(ctx, strlen(s) * 6);
adamc@135 911
adamc@135 912 for (; *s; s++) {
adamc@135 913 char c = *s;
adamc@135 914
adamc@135 915 switch (c) {
adamc@135 916 case '<':
adamc@311 917 uw_write_unsafe(ctx, "&lt;");
adamc@135 918 break;
adamc@135 919 case '&':
adamc@311 920 uw_write_unsafe(ctx, "&amp;");
adamc@135 921 break;
adamc@135 922 default:
adamc@135 923 if (isprint(c))
adamc@311 924 uw_writec_unsafe(ctx, c);
adamc@135 925 else {
adamc@311 926 uw_write_unsafe(ctx, "&#");
adamc@311 927 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 928 uw_writec_unsafe(ctx, ';');
adamc@135 929 }
adamc@135 930 }
adamc@135 931 }
adamc@428 932
adamc@428 933 return uw_unit_v;
adamc@135 934 }
adamc@180 935
adamc@311 936 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 937 if (b == uw_Basis_False)
adamc@286 938 return "False";
adamc@286 939 else
adamc@286 940 return "True";
adamc@286 941 }
adamc@286 942
adamc@428 943 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 944 if (b == uw_Basis_False) {
adamc@311 945 uw_check(ctx, 6);
adamc@286 946 strcpy(ctx->page_front, "False");
adamc@286 947 ctx->page_front += 5;
adamc@286 948 } else {
adamc@311 949 uw_check(ctx, 5);
adamc@286 950 strcpy(ctx->page_front, "True");
adamc@286 951 ctx->page_front += 4;
adamc@286 952 }
adamc@428 953
adamc@428 954 return uw_unit_v;
adamc@286 955 }
adamc@286 956
adamc@436 957 #define TIME_FMT "%x %X"
adamc@438 958 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 959
adamc@436 960 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 961 size_t len;
adamc@436 962 char *r;
adamc@436 963 struct tm stm;
adamc@436 964
adamc@436 965 if (localtime_r(&t, &stm)) {
adamc@436 966 uw_check_heap(ctx, TIMES_MAX);
adamc@436 967 r = ctx->heap_front;
adamc@436 968 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 969 ctx->heap_front += len+1;
adamc@436 970 return r;
adamc@436 971 } else
adamc@436 972 return "<i>Invalid time</i>";
adamc@436 973 }
adamc@436 974
adamc@436 975 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 976 size_t len;
adamc@436 977 char *r;
adamc@436 978 struct tm stm;
adamc@436 979
adamc@436 980 if (localtime_r(&t, &stm)) {
adamc@436 981 uw_check(ctx, TIMES_MAX);
adamc@436 982 r = ctx->page_front;
adamc@436 983 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 984 ctx->page_front += len;
adamc@436 985 } else {
adamc@436 986 uw_check(ctx, 20);
adamc@436 987 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 988 ctx->page_front += 19;
adamc@436 989 }
adamc@436 990
adamc@436 991 return uw_unit_v;
adamc@436 992 }
adamc@436 993
adamc@311 994 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 995 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 996 char *s;
adamc@180 997
adamc@311 998 uw_check_heap(ctx, len);
adamc@180 999
adamc@180 1000 s = ctx->heap_front;
adamc@180 1001
adamc@180 1002 strcpy(s, s1);
adamc@180 1003 strcat(s, s2);
adamc@180 1004 ctx->heap_front += len;
adamc@180 1005
adamc@180 1006 return s;
adamc@180 1007 }
adamc@278 1008
adamc@311 1009 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 1010 int len = strlen(s1) + 1;
adamc@278 1011 char *s;
adamc@278 1012
adamc@311 1013 uw_check_heap(ctx, len);
adamc@278 1014
adamc@278 1015 s = ctx->heap_front;
adamc@278 1016
adamc@278 1017 strcpy(s, s1);
adamc@278 1018 ctx->heap_front += len;
adamc@278 1019
adamc@278 1020 return s;
adamc@278 1021 }
adamc@280 1022
adamc@493 1023 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@493 1024 if (s1)
adamc@493 1025 return uw_Basis_strdup(ctx, s1);
adamc@493 1026 else
adamc@493 1027 return NULL;
adamc@493 1028 }
adamc@493 1029
adamc@280 1030
adamc@311 1031 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 1032 int len;
adamc@281 1033 char *r;
adamc@281 1034
adamc@311 1035 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 1036 r = ctx->heap_front;
adamc@281 1037 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 1038 ctx->heap_front += len+1;
adamc@281 1039 return r;
adamc@281 1040 }
adamc@281 1041
adamc@467 1042 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
adamc@467 1043 if (n == NULL)
adamc@467 1044 return "NULL";
adamc@467 1045 else
adamc@467 1046 return uw_Basis_sqlifyInt(ctx, *n);
adamc@467 1047 }
adamc@467 1048
adamc@311 1049 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 1050 int len;
adamc@281 1051 char *r;
adamc@281 1052
adamc@311 1053 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 1054 r = ctx->heap_front;
adamc@281 1055 sprintf(r, "%g::float8%n", n, &len);
adamc@281 1056 ctx->heap_front += len+1;
adamc@281 1057 return r;
adamc@281 1058 }
adamc@281 1059
adamc@467 1060 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
adamc@467 1061 if (n == NULL)
adamc@467 1062 return "NULL";
adamc@467 1063 else
adamc@467 1064 return uw_Basis_sqlifyFloat(ctx, *n);
adamc@467 1065 }
adamc@467 1066
adamc@281 1067
adamc@311 1068 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 1069 char *r, *s2;
adamc@280 1070
adamc@311 1071 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 1072
adamc@280 1073 r = s2 = ctx->heap_front;
adamc@280 1074 *s2++ = 'E';
adamc@280 1075 *s2++ = '\'';
adamc@280 1076
adamc@280 1077 for (; *s; s++) {
adamc@280 1078 char c = *s;
adamc@280 1079
adamc@280 1080 switch (c) {
adamc@280 1081 case '\'':
adamc@280 1082 strcpy(s2, "\\'");
adamc@280 1083 s2 += 2;
adamc@280 1084 break;
adamc@280 1085 case '\\':
adamc@280 1086 strcpy(s2, "\\\\");
adamc@280 1087 s2 += 2;
adamc@280 1088 break;
adamc@280 1089 default:
adamc@280 1090 if (isprint(c))
adamc@280 1091 *s2++ = c;
adamc@280 1092 else {
adamc@280 1093 sprintf(s2, "\\%3o", c);
adamc@280 1094 s2 += 4;
adamc@280 1095 }
adamc@280 1096 }
adamc@280 1097 }
adamc@280 1098
adamc@281 1099 strcpy(s2, "'::text");
adamc@281 1100 ctx->heap_front = s2 + 8;
adamc@280 1101 return r;
adamc@280 1102 }
adamc@281 1103
adamc@467 1104 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
adamc@467 1105 if (s == NULL)
adamc@467 1106 return "NULL";
adamc@467 1107 else
adamc@467 1108 return uw_Basis_sqlifyString(ctx, s);
adamc@467 1109 }
adamc@467 1110
adamc@311 1111 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 1112 if (b == uw_Basis_False)
adamc@281 1113 return "FALSE";
adamc@281 1114 else
adamc@281 1115 return "TRUE";
adamc@281 1116 }
adamc@282 1117
adamc@467 1118 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
adamc@467 1119 if (b == NULL)
adamc@467 1120 return "NULL";
adamc@467 1121 else
adamc@467 1122 return uw_Basis_sqlifyBool(ctx, *b);
adamc@467 1123 }
adamc@467 1124
adamc@439 1125 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 1126 size_t len;
adamc@439 1127 char *r;
adamc@439 1128 struct tm stm;
adamc@439 1129
adamc@439 1130 if (localtime_r(&t, &stm)) {
adamc@439 1131 uw_check_heap(ctx, TIMES_MAX);
adamc@439 1132 r = ctx->heap_front;
adamc@439 1133 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 1134 ctx->heap_front += len+1;
adamc@439 1135 return r;
adamc@439 1136 } else
adamc@439 1137 return "<Invalid time>";
adamc@439 1138 }
adamc@439 1139
adamc@467 1140 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
adamc@467 1141 if (t == NULL)
adamc@467 1142 return "NULL";
adamc@467 1143 else
adamc@467 1144 return uw_Basis_sqlifyTime(ctx, *t);
adamc@467 1145 }
adamc@467 1146
adamc@311 1147 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 1148 static uw_Basis_int true = 1;
adamc@311 1149 static uw_Basis_int false = 0;
adamc@282 1150
adamc@311 1151 if (b == uw_Basis_False)
adamc@282 1152 return (char *)&false;
adamc@282 1153 else
adamc@282 1154 return (char *)&true;
adamc@282 1155 }
adamc@284 1156
adamc@311 1157 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 1158 int len;
adamc@284 1159 char *r;
adamc@284 1160
adamc@311 1161 uw_check_heap(ctx, INTS_MAX);
adamc@284 1162 r = ctx->heap_front;
adamc@284 1163 sprintf(r, "%lld%n", n, &len);
adamc@284 1164 ctx->heap_front += len+1;
adamc@284 1165 return r;
adamc@284 1166 }
adamc@285 1167
adamc@311 1168 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 1169 int len;
adamc@285 1170 char *r;
adamc@285 1171
adamc@311 1172 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 1173 r = ctx->heap_front;
adamc@285 1174 sprintf(r, "%g%n", n, &len);
adamc@285 1175 ctx->heap_front += len+1;
adamc@285 1176 return r;
adamc@285 1177 }
adamc@285 1178
adamc@311 1179 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 1180 if (b == uw_Basis_False)
adamc@285 1181 return "False";
adamc@285 1182 else
adamc@285 1183 return "True";
adamc@285 1184 }
adamc@288 1185
adamc@436 1186 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 1187 size_t len;
adamc@436 1188 char *r;
adamc@436 1189 struct tm stm;
adamc@436 1190
adamc@436 1191 if (localtime_r(&t, &stm)) {
adamc@436 1192 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1193 r = ctx->heap_front;
adamc@436 1194 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1195 ctx->heap_front += len+1;
adamc@436 1196 return r;
adamc@436 1197 } else
adamc@436 1198 return "<Invalid time>";
adamc@436 1199 }
adamc@288 1200
adamc@311 1201 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1202 char *endptr;
adamc@311 1203 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1204
adamc@288 1205 if (*s != '\0' && *endptr == '\0') {
adamc@311 1206 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1207 *r = n;
adamc@288 1208 return r;
adamc@288 1209 } else
adamc@288 1210 return NULL;
adamc@288 1211 }
adamc@289 1212
adamc@311 1213 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1214 char *endptr;
adamc@311 1215 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1216
adamc@289 1217 if (*s != '\0' && *endptr == '\0') {
adamc@311 1218 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1219 *r = n;
adamc@289 1220 return r;
adamc@289 1221 } else
adamc@289 1222 return NULL;
adamc@289 1223 }
adamc@289 1224
adamc@311 1225 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1226 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1227 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1228
adamc@289 1229 if (!strcasecmp (s, "True"))
adamc@289 1230 return &true;
adamc@289 1231 else if (!strcasecmp (s, "False"))
adamc@289 1232 return &false;
adamc@289 1233 else
adamc@289 1234 return NULL;
adamc@289 1235 }
adamc@292 1236
adamc@436 1237 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1238 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1239 struct tm stm;
adamc@436 1240
adamc@439 1241 if (dot) {
adamc@439 1242 *dot = 0;
adamc@439 1243 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1244 *dot = '.';
adamc@439 1245 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1246 *r = mktime(&stm);
adamc@439 1247 return r;
adamc@439 1248 }
adamc@439 1249 else {
adamc@439 1250 *dot = '.';
adamc@439 1251 return NULL;
adamc@439 1252 }
adamc@436 1253 }
adamc@439 1254 else {
adamc@439 1255 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1256 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1257 *r = mktime(&stm);
adamc@439 1258 return r;
adamc@439 1259 }
adamc@439 1260 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1261 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1262 *r = mktime(&stm);
adamc@439 1263 return r;
adamc@439 1264 }
adamc@439 1265 else
adamc@439 1266 return NULL;
adamc@439 1267 }
adamc@436 1268 }
adamc@436 1269
adamc@311 1270 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1271 char *endptr;
adamc@311 1272 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1273
adamc@292 1274 if (*s != '\0' && *endptr == '\0')
adamc@292 1275 return n;
adamc@292 1276 else
adamc@311 1277 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1278 }
adamc@293 1279
adamc@311 1280 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1281 char *endptr;
adamc@311 1282 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1283
adamc@293 1284 if (*s != '\0' && *endptr == '\0')
adamc@293 1285 return n;
adamc@293 1286 else
adamc@311 1287 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1288 }
adamc@293 1289
adamc@311 1290 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1291 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1292 return uw_Basis_True;
adamc@296 1293 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1294 return uw_Basis_False;
adamc@293 1295 else
adamc@311 1296 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1297 }
adamc@436 1298
adamc@436 1299 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1300 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1301 struct tm stm = {};
adamc@436 1302
adamc@438 1303 if (dot) {
adamc@438 1304 *dot = 0;
adamc@438 1305 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1306 *dot = '.';
adamc@438 1307 return mktime(&stm);
adamc@438 1308 }
adamc@438 1309 else {
adamc@438 1310 *dot = '.';
adamc@438 1311 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1312 }
adamc@438 1313 }
adamc@438 1314 else {
adamc@439 1315 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1316 return mktime(&stm);
adamc@439 1317 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1318 return mktime(&stm);
adamc@438 1319 else
adamc@438 1320 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1321 }
adamc@436 1322 }
adamc@457 1323
adamc@457 1324 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1325 int len = strlen(h);
adamc@457 1326 char *s = ctx->headers, *p;
adamc@457 1327
adamc@457 1328 while (p = strchr(s, ':')) {
adamc@457 1329 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1330 return p + 2;
adamc@457 1331 } else {
adamc@458 1332 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1333 s += 2;
adamc@457 1334 else
adamc@457 1335 return NULL;
adamc@457 1336 }
adamc@457 1337 }
adamc@463 1338 }
adamc@458 1339
adamc@463 1340 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1341 int len = strlen(c);
adamc@474 1342 char *s = ctx->headers, *p = ctx->outHeaders;
adamc@474 1343
adamc@474 1344 while (p = strstr(p, "\nSet-Cookie: ")) {
adamc@474 1345 char *p2;
adamc@474 1346 p += 13;
adamc@474 1347 p2 = strchr(p, '=');
adamc@474 1348
adamc@474 1349 if (p2) {
adamc@474 1350 size_t sz = strcspn(p2+1, ";\r\n");
adamc@474 1351
adamc@474 1352 if (!strncasecmp(p, c, p2 - p)) {
adamc@474 1353 char *ret = uw_malloc(ctx, sz + 1);
adamc@474 1354 memcpy(ret, p2+1, sz);
adamc@474 1355 ret[sz] = 0;
adamc@474 1356 return ret;
adamc@474 1357 }
adamc@474 1358 }
adamc@474 1359 }
adamc@463 1360
adamc@463 1361 while (p = strchr(s, ':')) {
adamc@476 1362 if (!strncasecmp(s, "Cookie: ", 8)) {
adamc@476 1363 p += 2;
adamc@476 1364 while (1) {
adamc@476 1365 if (!strncmp(p, c, len)
adamc@476 1366 && p + len < ctx->headers_end && p[len] == '=')
adamc@476 1367 return p + 1 + len;
adamc@476 1368 else if (p = strchr(p, ';'))
adamc@476 1369 p += 2;
adamc@476 1370 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
adamc@476 1371 s += 2;
adamc@476 1372 break;
adamc@476 1373 }
adamc@476 1374 else
adamc@476 1375 return NULL;
adamc@476 1376 }
adamc@463 1377 } else {
adamc@463 1378 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1379 s += 2;
adamc@463 1380 else
adamc@463 1381 return NULL;
adamc@463 1382 }
adamc@463 1383 }
adamc@457 1384 }
adamc@462 1385
adamc@466 1386 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1387 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1388 uw_write_header(ctx, c);
adamc@462 1389 uw_write_header(ctx, "=");
adamc@462 1390 uw_write_header(ctx, v);
adamc@466 1391 uw_write_header(ctx, "; path=");
adamc@466 1392 uw_write_header(ctx, prefix);
adamc@462 1393 uw_write_header(ctx, "\r\n");
adamc@462 1394
adamc@462 1395 return uw_unit_v;
adamc@462 1396 }