annotate src/c/urweb.c @ 562:6daa59a55c43

Add initial C support for reactive
author Adam Chlipala <adamc@hcoop.net>
date Fri, 19 Dec 2008 09:35:44 -0500
parents ae03d09043c1
children 74800be65591
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@562 35 int reactive_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@562 78 ctx->reactive_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@562 108 ctx->reactive_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@562 366 }
adamc@562 367 }
adamc@562 368
adamc@562 369 void uw_write_script(uw_context ctx, uw_Basis_string s) {
adamc@562 370 int len = strlen(s);
adamc@562 371
adamc@562 372 uw_check_script(ctx, len + 1);
adamc@562 373 strcpy(ctx->script_front, s);
adamc@562 374 ctx->script_front += len;
adamc@562 375 }
adamc@562 376
adamc@562 377 int uw_Basis_new_client_reactive(uw_context ctx) {
adamc@562 378 size_t len;
adamc@562 379
adamc@562 380 uw_check_script(ctx, 8 + INTS_MAX);
adamc@562 381 sprintf(ctx->script_front, "var e%d=0\n%n", ctx->reactive_count, &len);
adamc@562 382 ctx->script_front += len;
adamc@562 383
adamc@562 384 return ctx->reactive_count++;
adamc@117 385 }
adamc@117 386
adamc@311 387 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 388 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 389 char *new_page;
adamc@117 390
adamc@317 391 next = ctx->page_back - ctx->page;
adamc@428 392 if (next < desired) {
adamc@428 393 if (next == 0)
adamc@428 394 next = 1;
adamc@428 395 for (; next < desired; next *= 2);
adamc@117 396
adamc@428 397 new_page = realloc(ctx->page, next);
adamc@428 398 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 399 ctx->page_back = new_page + next;
adamc@428 400 ctx->page = new_page;
adamc@428 401 }
adamc@117 402 }
adamc@117 403
adamc@311 404 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 405 *(ctx->page_front)++ = c;
adamc@117 406 }
adamc@117 407
adamc@311 408 void uw_writec(uw_context ctx, char c) {
adamc@311 409 uw_check(ctx, 1);
adamc@311 410 uw_writec_unsafe(ctx, c);
adamc@117 411 }
adamc@117 412
adamc@311 413 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 414 int len = strlen(s);
adamc@117 415 memcpy(ctx->page_front, s, len);
adamc@117 416 ctx->page_front += len;
adamc@117 417 }
adamc@117 418
adamc@311 419 void uw_write(uw_context ctx, const char* s) {
adamc@311 420 uw_check(ctx, strlen(s) + 1);
adamc@311 421 uw_write_unsafe(ctx, s);
adamc@183 422 *ctx->page_front = 0;
adamc@102 423 }
adamc@106 424
adamc@135 425
adamc@311 426 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 427 char *result;
adamc@136 428 int len;
adamc@311 429 uw_check_heap(ctx, INTS_MAX);
adamc@136 430 result = ctx->heap_front;
adamc@276 431 sprintf(result, "%lld%n", n, &len);
adamc@137 432 ctx->heap_front += len+1;
adamc@136 433 return result;
adamc@106 434 }
adamc@106 435
adamc@311 436 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 437 char *result;
adamc@136 438 int len;
adamc@311 439 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 440 result = ctx->heap_front;
adamc@136 441 sprintf(result, "%g%n", n, &len);
adamc@137 442 ctx->heap_front += len+1;
adamc@136 443 return result;
adamc@106 444 }
adamc@106 445
adamc@311 446 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 447 int len = strlen(s);
adamc@136 448 char *result, *p;
adamc@311 449 uw_check_heap(ctx, len * 6 + 1);
adamc@136 450
adamc@136 451 result = p = ctx->heap_front;
adamc@136 452
adamc@136 453 for (; *s; s++) {
adamc@136 454 char c = *s;
adamc@136 455
adamc@136 456 if (c == '"') {
adamc@136 457 strcpy(p, "&quot;");
adamc@136 458 p += 6;
adamc@136 459 } else if (c == '&') {
adamc@136 460 strcpy(p, "&amp;");
adamc@136 461 p += 5;
adamc@136 462 }
adamc@136 463 else if (isprint(c))
adamc@136 464 *p++ = c;
adamc@136 465 else {
adamc@136 466 int len2;
adamc@136 467 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 468 p += len2;
adamc@136 469 }
adamc@136 470 }
adamc@136 471
adamc@137 472 *p++ = 0;
adamc@136 473 ctx->heap_front = p;
adamc@136 474 return result;
adamc@106 475 }
adamc@106 476
adamc@311 477 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 478 int len;
adamc@117 479
adamc@276 480 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 481 ctx->page_front += len;
adamc@106 482 }
adamc@106 483
adamc@428 484 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 485 uw_check(ctx, INTS_MAX);
adamc@311 486 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 487
adamc@428 488 return uw_unit_v;
adamc@106 489 }
adamc@106 490
adamc@428 491 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 492 int len;
adamc@117 493
adamc@311 494 uw_check(ctx, FLOATS_MAX);
adamc@117 495 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 496 ctx->page_front += len;
adamc@428 497
adamc@428 498 return uw_unit_v;
adamc@117 499 }
adamc@117 500
adamc@428 501 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 502 uw_check(ctx, strlen(s) * 6);
adamc@117 503
adamc@106 504 for (; *s; s++) {
adamc@106 505 char c = *s;
adamc@106 506
adamc@106 507 if (c == '"')
adamc@311 508 uw_write_unsafe(ctx, "&quot;");
adamc@136 509 else if (c == '&')
adamc@311 510 uw_write_unsafe(ctx, "&amp;");
adamc@106 511 else if (isprint(c))
adamc@311 512 uw_writec_unsafe(ctx, c);
adamc@106 513 else {
adamc@311 514 uw_write_unsafe(ctx, "&#");
adamc@311 515 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 516 uw_writec_unsafe(ctx, ';');
adamc@106 517 }
adamc@106 518 }
adamc@428 519
adamc@428 520 return uw_unit_v;
adamc@106 521 }
adamc@120 522
adamc@120 523
adamc@311 524 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 525 int len;
adamc@137 526 char *r;
adamc@137 527
adamc@311 528 uw_check_heap(ctx, INTS_MAX);
adamc@137 529 r = ctx->heap_front;
adamc@276 530 sprintf(r, "%lld%n", n, &len);
adamc@137 531 ctx->heap_front += len+1;
adamc@137 532 return r;
adamc@120 533 }
adamc@120 534
adamc@311 535 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 536 int len;
adamc@137 537 char *r;
adamc@137 538
adamc@311 539 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 540 r = ctx->heap_front;
adamc@137 541 sprintf(r, "%g%n", n, &len);
adamc@137 542 ctx->heap_front += len+1;
adamc@137 543 return r;
adamc@120 544 }
adamc@120 545
adamc@311 546 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 547 char *r, *p;
adamc@137 548
adamc@311 549 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 550
adamc@137 551 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 552 char c = *s;
adamc@137 553
adamc@137 554 if (c == ' ')
adamc@137 555 *p++ = '+';
adamc@137 556 else if (isalnum(c))
adamc@137 557 *p++ = c;
adamc@137 558 else {
adamc@137 559 sprintf(p, "%%%02X", c);
adamc@137 560 p += 3;
adamc@137 561 }
adamc@137 562 }
adamc@137 563
adamc@137 564 *p++ = 0;
adamc@137 565 ctx->heap_front = p;
adamc@137 566 return r;
adamc@120 567 }
adamc@120 568
adamc@311 569 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 570 if (b == uw_Basis_False)
adamc@186 571 return "0";
adamc@186 572 else
adamc@186 573 return "1";
adamc@186 574 }
adamc@186 575
adamc@311 576 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 577 int len;
adamc@120 578
adamc@276 579 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 580 ctx->page_front += len;
adamc@120 581 }
adamc@120 582
adamc@428 583 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 584 uw_check(ctx, INTS_MAX);
adamc@311 585 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 586
adamc@428 587 return uw_unit_v;
adamc@120 588 }
adamc@120 589
adamc@428 590 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 591 int len;
adamc@120 592
adamc@311 593 uw_check(ctx, FLOATS_MAX);
adamc@120 594 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 595 ctx->page_front += len;
adamc@428 596
adamc@428 597 return uw_unit_v;
adamc@120 598 }
adamc@120 599
adamc@488 600 uw_Basis_string uw_Basis_urlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@488 601 return uw_Basis_urlifyInt(ctx, t);
adamc@488 602 }
adamc@488 603
adamc@428 604 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 605 uw_check(ctx, strlen(s) * 3);
adamc@120 606
adamc@120 607 for (; *s; s++) {
adamc@120 608 char c = *s;
adamc@120 609
adamc@120 610 if (c == ' ')
adamc@311 611 uw_writec_unsafe(ctx, '+');
adamc@120 612 else if (isalnum(c))
adamc@311 613 uw_writec_unsafe(ctx, c);
adamc@120 614 else {
adamc@120 615 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 616 ctx->page_front += 3;
adamc@120 617 }
adamc@120 618 }
adamc@428 619
adamc@428 620 return uw_unit_v;
adamc@120 621 }
adamc@120 622
adamc@428 623 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 624 if (b == uw_Basis_False)
adamc@311 625 uw_writec(ctx, '0');
adamc@186 626 else
adamc@311 627 uw_writec(ctx, '1');
adamc@428 628
adamc@428 629 return uw_unit_v;
adamc@186 630 }
adamc@186 631
adamc@120 632
adamc@311 633 static char *uw_unurlify_advance(char *s) {
adamc@144 634 char *new_s = strchr(s, '/');
adamc@120 635
adamc@120 636 if (new_s)
adamc@120 637 *new_s++ = 0;
adamc@120 638 else
adamc@144 639 new_s = strchr(s, 0);
adamc@144 640
adamc@144 641 return new_s;
adamc@144 642 }
adamc@144 643
adamc@311 644 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 645 char *new_s = uw_unurlify_advance(*s);
adamc@311 646 uw_Basis_int r;
adamc@120 647
adamc@276 648 r = atoll(*s);
adamc@120 649 *s = new_s;
adamc@120 650 return r;
adamc@120 651 }
adamc@120 652
adamc@311 653 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 654 char *new_s = uw_unurlify_advance(*s);
adamc@311 655 uw_Basis_float r;
adamc@120 656
adamc@120 657 r = atof(*s);
adamc@120 658 *s = new_s;
adamc@120 659 return r;
adamc@120 660 }
adamc@120 661
adamc@488 662 uw_Basis_time uw_Basis_unurlifyTime(uw_context ctx, char **s) {
adamc@488 663 return uw_Basis_unurlifyInt(ctx, s);
adamc@488 664 }
adamc@488 665
adamc@311 666 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 667 char *s1, *s2;
adamc@144 668 int n;
adamc@136 669
adamc@144 670 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 671 char c = *s2;
adamc@136 672
adamc@136 673 switch (c) {
adamc@136 674 case '+':
adamc@136 675 *s1 = ' ';
adamc@136 676 break;
adamc@136 677 case '%':
adamc@169 678 if (s2[1] == 0)
adamc@311 679 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 680 if (s2[2] == 0)
adamc@311 681 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 682 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 683 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 684 *s1 = n;
adamc@136 685 s2 += 2;
adamc@136 686 break;
adamc@136 687 default:
adamc@136 688 *s1 = c;
adamc@136 689 }
adamc@136 690 }
adamc@136 691 *s1++ = 0;
adamc@144 692 return s1;
adamc@144 693 }
adamc@144 694
adamc@311 695 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 696 char *new_s = uw_unurlify_advance(*s);
adamc@311 697 uw_Basis_bool r;
adamc@186 698
adamc@186 699 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 700 r = uw_Basis_False;
adamc@186 701 else
adamc@311 702 r = uw_Basis_True;
adamc@186 703
adamc@186 704 *s = new_s;
adamc@186 705 return r;
adamc@186 706 }
adamc@186 707
adamc@311 708 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 709 char *new_s = uw_unurlify_advance(*s);
adamc@144 710 char *r, *s1, *s2;
adamc@144 711 int len, n;
adamc@144 712
adamc@200 713 len = strlen(*s);
adamc@311 714 uw_check_heap(ctx, len + 1);
adamc@144 715
adamc@144 716 r = ctx->heap_front;
adamc@311 717 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 718 *s = new_s;
adamc@136 719 return r;
adamc@120 720 }
adamc@135 721
adamc@135 722
adamc@311 723 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 724 int len;
adamc@286 725 char *r;
adamc@286 726
adamc@311 727 uw_check_heap(ctx, INTS_MAX);
adamc@286 728 r = ctx->heap_front;
adamc@286 729 sprintf(r, "%lld%n", n, &len);
adamc@286 730 ctx->heap_front += len+1;
adamc@286 731 return r;
adamc@286 732 }
adamc@286 733
adamc@428 734 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 735 int len;
adamc@286 736
adamc@311 737 uw_check(ctx, INTS_MAX);
adamc@286 738 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 739 ctx->page_front += len;
adamc@428 740
adamc@428 741 return uw_unit_v;
adamc@286 742 }
adamc@286 743
adamc@311 744 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 745 int len;
adamc@286 746 char *r;
adamc@286 747
adamc@311 748 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 749 r = ctx->heap_front;
adamc@286 750 sprintf(r, "%g%n", n, &len);
adamc@286 751 ctx->heap_front += len+1;
adamc@286 752 return r;
adamc@286 753 }
adamc@286 754
adamc@428 755 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 756 int len;
adamc@286 757
adamc@311 758 uw_check(ctx, FLOATS_MAX);
adamc@286 759 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 760 ctx->page_front += len;
adamc@428 761
adamc@428 762 return uw_unit_v;
adamc@286 763 }
adamc@286 764
adamc@311 765 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 766 char *r, *s2;
adamc@137 767
adamc@311 768 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 769
adamc@137 770 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 771 char c = *s;
adamc@137 772
adamc@137 773 switch (c) {
adamc@137 774 case '<':
adamc@137 775 strcpy(s2, "&lt;");
adamc@137 776 s2 += 4;
adamc@137 777 break;
adamc@137 778 case '&':
adamc@137 779 strcpy(s2, "&amp;");
adamc@137 780 s2 += 5;
adamc@137 781 break;
adamc@137 782 default:
adamc@137 783 if (isprint(c))
adamc@137 784 *s2++ = c;
adamc@137 785 else {
adamc@137 786 int len2;
adamc@137 787 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 788 s2 += len2;
adamc@137 789 }
adamc@137 790 }
adamc@137 791 }
adamc@137 792
adamc@137 793 *s2++ = 0;
adamc@137 794 ctx->heap_front = s2;
adamc@137 795 return r;
adamc@135 796 }
adamc@135 797
adamc@428 798 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 799 uw_check(ctx, strlen(s) * 6);
adamc@135 800
adamc@135 801 for (; *s; s++) {
adamc@135 802 char c = *s;
adamc@135 803
adamc@135 804 switch (c) {
adamc@135 805 case '<':
adamc@311 806 uw_write_unsafe(ctx, "&lt;");
adamc@135 807 break;
adamc@135 808 case '&':
adamc@311 809 uw_write_unsafe(ctx, "&amp;");
adamc@135 810 break;
adamc@135 811 default:
adamc@135 812 if (isprint(c))
adamc@311 813 uw_writec_unsafe(ctx, c);
adamc@135 814 else {
adamc@311 815 uw_write_unsafe(ctx, "&#");
adamc@311 816 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 817 uw_writec_unsafe(ctx, ';');
adamc@135 818 }
adamc@135 819 }
adamc@135 820 }
adamc@428 821
adamc@428 822 return uw_unit_v;
adamc@135 823 }
adamc@180 824
adamc@311 825 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 826 if (b == uw_Basis_False)
adamc@286 827 return "False";
adamc@286 828 else
adamc@286 829 return "True";
adamc@286 830 }
adamc@286 831
adamc@428 832 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 833 if (b == uw_Basis_False) {
adamc@311 834 uw_check(ctx, 6);
adamc@286 835 strcpy(ctx->page_front, "False");
adamc@286 836 ctx->page_front += 5;
adamc@286 837 } else {
adamc@311 838 uw_check(ctx, 5);
adamc@286 839 strcpy(ctx->page_front, "True");
adamc@286 840 ctx->page_front += 4;
adamc@286 841 }
adamc@428 842
adamc@428 843 return uw_unit_v;
adamc@286 844 }
adamc@286 845
adamc@436 846 #define TIME_FMT "%x %X"
adamc@438 847 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 848
adamc@436 849 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 850 size_t len;
adamc@436 851 char *r;
adamc@436 852 struct tm stm;
adamc@436 853
adamc@436 854 if (localtime_r(&t, &stm)) {
adamc@436 855 uw_check_heap(ctx, TIMES_MAX);
adamc@436 856 r = ctx->heap_front;
adamc@436 857 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 858 ctx->heap_front += len+1;
adamc@436 859 return r;
adamc@436 860 } else
adamc@436 861 return "<i>Invalid time</i>";
adamc@436 862 }
adamc@436 863
adamc@436 864 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 865 size_t len;
adamc@436 866 char *r;
adamc@436 867 struct tm stm;
adamc@436 868
adamc@436 869 if (localtime_r(&t, &stm)) {
adamc@436 870 uw_check(ctx, TIMES_MAX);
adamc@436 871 r = ctx->page_front;
adamc@436 872 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 873 ctx->page_front += len;
adamc@436 874 } else {
adamc@436 875 uw_check(ctx, 20);
adamc@436 876 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 877 ctx->page_front += 19;
adamc@436 878 }
adamc@436 879
adamc@436 880 return uw_unit_v;
adamc@436 881 }
adamc@436 882
adamc@311 883 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 884 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 885 char *s;
adamc@180 886
adamc@311 887 uw_check_heap(ctx, len);
adamc@180 888
adamc@180 889 s = ctx->heap_front;
adamc@180 890
adamc@180 891 strcpy(s, s1);
adamc@180 892 strcat(s, s2);
adamc@180 893 ctx->heap_front += len;
adamc@180 894
adamc@180 895 return s;
adamc@180 896 }
adamc@278 897
adamc@311 898 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 899 int len = strlen(s1) + 1;
adamc@278 900 char *s;
adamc@278 901
adamc@311 902 uw_check_heap(ctx, len);
adamc@278 903
adamc@278 904 s = ctx->heap_front;
adamc@278 905
adamc@278 906 strcpy(s, s1);
adamc@278 907 ctx->heap_front += len;
adamc@278 908
adamc@278 909 return s;
adamc@278 910 }
adamc@280 911
adamc@493 912 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@493 913 if (s1)
adamc@493 914 return uw_Basis_strdup(ctx, s1);
adamc@493 915 else
adamc@493 916 return NULL;
adamc@493 917 }
adamc@493 918
adamc@280 919
adamc@311 920 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 921 int len;
adamc@281 922 char *r;
adamc@281 923
adamc@311 924 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 925 r = ctx->heap_front;
adamc@281 926 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 927 ctx->heap_front += len+1;
adamc@281 928 return r;
adamc@281 929 }
adamc@281 930
adamc@467 931 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
adamc@467 932 if (n == NULL)
adamc@467 933 return "NULL";
adamc@467 934 else
adamc@467 935 return uw_Basis_sqlifyInt(ctx, *n);
adamc@467 936 }
adamc@467 937
adamc@311 938 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 939 int len;
adamc@281 940 char *r;
adamc@281 941
adamc@311 942 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 943 r = ctx->heap_front;
adamc@281 944 sprintf(r, "%g::float8%n", n, &len);
adamc@281 945 ctx->heap_front += len+1;
adamc@281 946 return r;
adamc@281 947 }
adamc@281 948
adamc@467 949 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
adamc@467 950 if (n == NULL)
adamc@467 951 return "NULL";
adamc@467 952 else
adamc@467 953 return uw_Basis_sqlifyFloat(ctx, *n);
adamc@467 954 }
adamc@467 955
adamc@281 956
adamc@311 957 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 958 char *r, *s2;
adamc@280 959
adamc@311 960 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 961
adamc@280 962 r = s2 = ctx->heap_front;
adamc@280 963 *s2++ = 'E';
adamc@280 964 *s2++ = '\'';
adamc@280 965
adamc@280 966 for (; *s; s++) {
adamc@280 967 char c = *s;
adamc@280 968
adamc@280 969 switch (c) {
adamc@280 970 case '\'':
adamc@280 971 strcpy(s2, "\\'");
adamc@280 972 s2 += 2;
adamc@280 973 break;
adamc@280 974 case '\\':
adamc@280 975 strcpy(s2, "\\\\");
adamc@280 976 s2 += 2;
adamc@280 977 break;
adamc@280 978 default:
adamc@280 979 if (isprint(c))
adamc@280 980 *s2++ = c;
adamc@280 981 else {
adamc@280 982 sprintf(s2, "\\%3o", c);
adamc@280 983 s2 += 4;
adamc@280 984 }
adamc@280 985 }
adamc@280 986 }
adamc@280 987
adamc@281 988 strcpy(s2, "'::text");
adamc@281 989 ctx->heap_front = s2 + 8;
adamc@280 990 return r;
adamc@280 991 }
adamc@281 992
adamc@467 993 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
adamc@467 994 if (s == NULL)
adamc@467 995 return "NULL";
adamc@467 996 else
adamc@467 997 return uw_Basis_sqlifyString(ctx, s);
adamc@467 998 }
adamc@467 999
adamc@311 1000 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 1001 if (b == uw_Basis_False)
adamc@281 1002 return "FALSE";
adamc@281 1003 else
adamc@281 1004 return "TRUE";
adamc@281 1005 }
adamc@282 1006
adamc@467 1007 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
adamc@467 1008 if (b == NULL)
adamc@467 1009 return "NULL";
adamc@467 1010 else
adamc@467 1011 return uw_Basis_sqlifyBool(ctx, *b);
adamc@467 1012 }
adamc@467 1013
adamc@439 1014 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 1015 size_t len;
adamc@439 1016 char *r;
adamc@439 1017 struct tm stm;
adamc@439 1018
adamc@439 1019 if (localtime_r(&t, &stm)) {
adamc@439 1020 uw_check_heap(ctx, TIMES_MAX);
adamc@439 1021 r = ctx->heap_front;
adamc@439 1022 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 1023 ctx->heap_front += len+1;
adamc@439 1024 return r;
adamc@439 1025 } else
adamc@439 1026 return "<Invalid time>";
adamc@439 1027 }
adamc@439 1028
adamc@467 1029 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
adamc@467 1030 if (t == NULL)
adamc@467 1031 return "NULL";
adamc@467 1032 else
adamc@467 1033 return uw_Basis_sqlifyTime(ctx, *t);
adamc@467 1034 }
adamc@467 1035
adamc@311 1036 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 1037 static uw_Basis_int true = 1;
adamc@311 1038 static uw_Basis_int false = 0;
adamc@282 1039
adamc@311 1040 if (b == uw_Basis_False)
adamc@282 1041 return (char *)&false;
adamc@282 1042 else
adamc@282 1043 return (char *)&true;
adamc@282 1044 }
adamc@284 1045
adamc@311 1046 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 1047 int len;
adamc@284 1048 char *r;
adamc@284 1049
adamc@311 1050 uw_check_heap(ctx, INTS_MAX);
adamc@284 1051 r = ctx->heap_front;
adamc@284 1052 sprintf(r, "%lld%n", n, &len);
adamc@284 1053 ctx->heap_front += len+1;
adamc@284 1054 return r;
adamc@284 1055 }
adamc@285 1056
adamc@311 1057 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 1058 int len;
adamc@285 1059 char *r;
adamc@285 1060
adamc@311 1061 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 1062 r = ctx->heap_front;
adamc@285 1063 sprintf(r, "%g%n", n, &len);
adamc@285 1064 ctx->heap_front += len+1;
adamc@285 1065 return r;
adamc@285 1066 }
adamc@285 1067
adamc@311 1068 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 1069 if (b == uw_Basis_False)
adamc@285 1070 return "False";
adamc@285 1071 else
adamc@285 1072 return "True";
adamc@285 1073 }
adamc@288 1074
adamc@436 1075 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 1076 size_t len;
adamc@436 1077 char *r;
adamc@436 1078 struct tm stm;
adamc@436 1079
adamc@436 1080 if (localtime_r(&t, &stm)) {
adamc@436 1081 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1082 r = ctx->heap_front;
adamc@436 1083 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1084 ctx->heap_front += len+1;
adamc@436 1085 return r;
adamc@436 1086 } else
adamc@436 1087 return "<Invalid time>";
adamc@436 1088 }
adamc@288 1089
adamc@311 1090 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1091 char *endptr;
adamc@311 1092 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1093
adamc@288 1094 if (*s != '\0' && *endptr == '\0') {
adamc@311 1095 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1096 *r = n;
adamc@288 1097 return r;
adamc@288 1098 } else
adamc@288 1099 return NULL;
adamc@288 1100 }
adamc@289 1101
adamc@311 1102 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1103 char *endptr;
adamc@311 1104 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1105
adamc@289 1106 if (*s != '\0' && *endptr == '\0') {
adamc@311 1107 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1108 *r = n;
adamc@289 1109 return r;
adamc@289 1110 } else
adamc@289 1111 return NULL;
adamc@289 1112 }
adamc@289 1113
adamc@311 1114 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1115 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1116 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1117
adamc@289 1118 if (!strcasecmp (s, "True"))
adamc@289 1119 return &true;
adamc@289 1120 else if (!strcasecmp (s, "False"))
adamc@289 1121 return &false;
adamc@289 1122 else
adamc@289 1123 return NULL;
adamc@289 1124 }
adamc@292 1125
adamc@436 1126 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1127 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1128 struct tm stm;
adamc@436 1129
adamc@439 1130 if (dot) {
adamc@439 1131 *dot = 0;
adamc@439 1132 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1133 *dot = '.';
adamc@439 1134 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1135 *r = mktime(&stm);
adamc@439 1136 return r;
adamc@439 1137 }
adamc@439 1138 else {
adamc@439 1139 *dot = '.';
adamc@439 1140 return NULL;
adamc@439 1141 }
adamc@436 1142 }
adamc@439 1143 else {
adamc@439 1144 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1145 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1146 *r = mktime(&stm);
adamc@439 1147 return r;
adamc@439 1148 }
adamc@439 1149 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1150 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1151 *r = mktime(&stm);
adamc@439 1152 return r;
adamc@439 1153 }
adamc@439 1154 else
adamc@439 1155 return NULL;
adamc@439 1156 }
adamc@436 1157 }
adamc@436 1158
adamc@311 1159 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1160 char *endptr;
adamc@311 1161 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1162
adamc@292 1163 if (*s != '\0' && *endptr == '\0')
adamc@292 1164 return n;
adamc@292 1165 else
adamc@311 1166 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1167 }
adamc@293 1168
adamc@311 1169 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1170 char *endptr;
adamc@311 1171 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1172
adamc@293 1173 if (*s != '\0' && *endptr == '\0')
adamc@293 1174 return n;
adamc@293 1175 else
adamc@311 1176 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1177 }
adamc@293 1178
adamc@311 1179 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1180 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1181 return uw_Basis_True;
adamc@296 1182 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1183 return uw_Basis_False;
adamc@293 1184 else
adamc@311 1185 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1186 }
adamc@436 1187
adamc@436 1188 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1189 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1190 struct tm stm = {};
adamc@436 1191
adamc@438 1192 if (dot) {
adamc@438 1193 *dot = 0;
adamc@438 1194 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1195 *dot = '.';
adamc@438 1196 return mktime(&stm);
adamc@438 1197 }
adamc@438 1198 else {
adamc@438 1199 *dot = '.';
adamc@438 1200 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1201 }
adamc@438 1202 }
adamc@438 1203 else {
adamc@439 1204 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1205 return mktime(&stm);
adamc@439 1206 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1207 return mktime(&stm);
adamc@438 1208 else
adamc@438 1209 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1210 }
adamc@436 1211 }
adamc@457 1212
adamc@457 1213 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1214 int len = strlen(h);
adamc@457 1215 char *s = ctx->headers, *p;
adamc@457 1216
adamc@457 1217 while (p = strchr(s, ':')) {
adamc@457 1218 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1219 return p + 2;
adamc@457 1220 } else {
adamc@458 1221 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1222 s += 2;
adamc@457 1223 else
adamc@457 1224 return NULL;
adamc@457 1225 }
adamc@457 1226 }
adamc@463 1227 }
adamc@458 1228
adamc@463 1229 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1230 int len = strlen(c);
adamc@474 1231 char *s = ctx->headers, *p = ctx->outHeaders;
adamc@474 1232
adamc@474 1233 while (p = strstr(p, "\nSet-Cookie: ")) {
adamc@474 1234 char *p2;
adamc@474 1235 p += 13;
adamc@474 1236 p2 = strchr(p, '=');
adamc@474 1237
adamc@474 1238 if (p2) {
adamc@474 1239 size_t sz = strcspn(p2+1, ";\r\n");
adamc@474 1240
adamc@474 1241 if (!strncasecmp(p, c, p2 - p)) {
adamc@474 1242 char *ret = uw_malloc(ctx, sz + 1);
adamc@474 1243 memcpy(ret, p2+1, sz);
adamc@474 1244 ret[sz] = 0;
adamc@474 1245 return ret;
adamc@474 1246 }
adamc@474 1247 }
adamc@474 1248 }
adamc@463 1249
adamc@463 1250 while (p = strchr(s, ':')) {
adamc@476 1251 if (!strncasecmp(s, "Cookie: ", 8)) {
adamc@476 1252 p += 2;
adamc@476 1253 while (1) {
adamc@476 1254 if (!strncmp(p, c, len)
adamc@476 1255 && p + len < ctx->headers_end && p[len] == '=')
adamc@476 1256 return p + 1 + len;
adamc@476 1257 else if (p = strchr(p, ';'))
adamc@476 1258 p += 2;
adamc@476 1259 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
adamc@476 1260 s += 2;
adamc@476 1261 break;
adamc@476 1262 }
adamc@476 1263 else
adamc@476 1264 return NULL;
adamc@476 1265 }
adamc@463 1266 } else {
adamc@463 1267 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1268 s += 2;
adamc@463 1269 else
adamc@463 1270 return NULL;
adamc@463 1271 }
adamc@463 1272 }
adamc@457 1273 }
adamc@462 1274
adamc@466 1275 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1276 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1277 uw_write_header(ctx, c);
adamc@462 1278 uw_write_header(ctx, "=");
adamc@462 1279 uw_write_header(ctx, v);
adamc@466 1280 uw_write_header(ctx, "; path=");
adamc@466 1281 uw_write_header(ctx, prefix);
adamc@462 1282 uw_write_header(ctx, "\r\n");
adamc@462 1283
adamc@462 1284 return uw_unit_v;
adamc@462 1285 }