annotate src/c/urweb.c @ 588:5803b4f041cb

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