annotate src/c/urweb.c @ 466:1626dcba13ee

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