annotate src/c/urweb.c @ 524:a6159d0940f0

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