annotate src/c/urweb.c @ 479:ffa18975e661

Broaden set of possible especializations
author Adam Chlipala <adamc@hcoop.net>
date Sat, 08 Nov 2008 14:42:52 -0500
parents c9566d49ecfe
children 5521bb0b4014
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@428 560 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 561 uw_check(ctx, strlen(s) * 3);
adamc@120 562
adamc@120 563 for (; *s; s++) {
adamc@120 564 char c = *s;
adamc@120 565
adamc@120 566 if (c == ' ')
adamc@311 567 uw_writec_unsafe(ctx, '+');
adamc@120 568 else if (isalnum(c))
adamc@311 569 uw_writec_unsafe(ctx, c);
adamc@120 570 else {
adamc@120 571 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 572 ctx->page_front += 3;
adamc@120 573 }
adamc@120 574 }
adamc@428 575
adamc@428 576 return uw_unit_v;
adamc@120 577 }
adamc@120 578
adamc@428 579 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 580 if (b == uw_Basis_False)
adamc@311 581 uw_writec(ctx, '0');
adamc@186 582 else
adamc@311 583 uw_writec(ctx, '1');
adamc@428 584
adamc@428 585 return uw_unit_v;
adamc@186 586 }
adamc@186 587
adamc@120 588
adamc@311 589 static char *uw_unurlify_advance(char *s) {
adamc@144 590 char *new_s = strchr(s, '/');
adamc@120 591
adamc@120 592 if (new_s)
adamc@120 593 *new_s++ = 0;
adamc@120 594 else
adamc@144 595 new_s = strchr(s, 0);
adamc@144 596
adamc@144 597 return new_s;
adamc@144 598 }
adamc@144 599
adamc@311 600 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 601 char *new_s = uw_unurlify_advance(*s);
adamc@311 602 uw_Basis_int r;
adamc@120 603
adamc@276 604 r = atoll(*s);
adamc@120 605 *s = new_s;
adamc@120 606 return r;
adamc@120 607 }
adamc@120 608
adamc@311 609 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 610 char *new_s = uw_unurlify_advance(*s);
adamc@311 611 uw_Basis_float r;
adamc@120 612
adamc@120 613 r = atof(*s);
adamc@120 614 *s = new_s;
adamc@120 615 return r;
adamc@120 616 }
adamc@120 617
adamc@311 618 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 619 char *s1, *s2;
adamc@144 620 int n;
adamc@136 621
adamc@144 622 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 623 char c = *s2;
adamc@136 624
adamc@136 625 switch (c) {
adamc@136 626 case '+':
adamc@136 627 *s1 = ' ';
adamc@136 628 break;
adamc@136 629 case '%':
adamc@169 630 if (s2[1] == 0)
adamc@311 631 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 632 if (s2[2] == 0)
adamc@311 633 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 634 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 635 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 636 *s1 = n;
adamc@136 637 s2 += 2;
adamc@136 638 break;
adamc@136 639 default:
adamc@136 640 *s1 = c;
adamc@136 641 }
adamc@136 642 }
adamc@136 643 *s1++ = 0;
adamc@144 644 return s1;
adamc@144 645 }
adamc@144 646
adamc@311 647 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 648 char *new_s = uw_unurlify_advance(*s);
adamc@311 649 uw_Basis_bool r;
adamc@186 650
adamc@186 651 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 652 r = uw_Basis_False;
adamc@186 653 else
adamc@311 654 r = uw_Basis_True;
adamc@186 655
adamc@186 656 *s = new_s;
adamc@186 657 return r;
adamc@186 658 }
adamc@186 659
adamc@311 660 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 661 char *new_s = uw_unurlify_advance(*s);
adamc@144 662 char *r, *s1, *s2;
adamc@144 663 int len, n;
adamc@144 664
adamc@200 665 len = strlen(*s);
adamc@311 666 uw_check_heap(ctx, len + 1);
adamc@144 667
adamc@144 668 r = ctx->heap_front;
adamc@311 669 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 670 *s = new_s;
adamc@136 671 return r;
adamc@120 672 }
adamc@135 673
adamc@135 674
adamc@311 675 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 676 int len;
adamc@286 677 char *r;
adamc@286 678
adamc@311 679 uw_check_heap(ctx, INTS_MAX);
adamc@286 680 r = ctx->heap_front;
adamc@286 681 sprintf(r, "%lld%n", n, &len);
adamc@286 682 ctx->heap_front += len+1;
adamc@286 683 return r;
adamc@286 684 }
adamc@286 685
adamc@428 686 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 687 int len;
adamc@286 688
adamc@311 689 uw_check(ctx, INTS_MAX);
adamc@286 690 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 691 ctx->page_front += len;
adamc@428 692
adamc@428 693 return uw_unit_v;
adamc@286 694 }
adamc@286 695
adamc@311 696 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 697 int len;
adamc@286 698 char *r;
adamc@286 699
adamc@311 700 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 701 r = ctx->heap_front;
adamc@286 702 sprintf(r, "%g%n", n, &len);
adamc@286 703 ctx->heap_front += len+1;
adamc@286 704 return r;
adamc@286 705 }
adamc@286 706
adamc@428 707 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 708 int len;
adamc@286 709
adamc@311 710 uw_check(ctx, FLOATS_MAX);
adamc@286 711 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 712 ctx->page_front += len;
adamc@428 713
adamc@428 714 return uw_unit_v;
adamc@286 715 }
adamc@286 716
adamc@311 717 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 718 char *r, *s2;
adamc@137 719
adamc@311 720 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 721
adamc@137 722 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 723 char c = *s;
adamc@137 724
adamc@137 725 switch (c) {
adamc@137 726 case '<':
adamc@137 727 strcpy(s2, "&lt;");
adamc@137 728 s2 += 4;
adamc@137 729 break;
adamc@137 730 case '&':
adamc@137 731 strcpy(s2, "&amp;");
adamc@137 732 s2 += 5;
adamc@137 733 break;
adamc@137 734 default:
adamc@137 735 if (isprint(c))
adamc@137 736 *s2++ = c;
adamc@137 737 else {
adamc@137 738 int len2;
adamc@137 739 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 740 s2 += len2;
adamc@137 741 }
adamc@137 742 }
adamc@137 743 }
adamc@137 744
adamc@137 745 *s2++ = 0;
adamc@137 746 ctx->heap_front = s2;
adamc@137 747 return r;
adamc@135 748 }
adamc@135 749
adamc@428 750 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 751 uw_check(ctx, strlen(s) * 6);
adamc@135 752
adamc@135 753 for (; *s; s++) {
adamc@135 754 char c = *s;
adamc@135 755
adamc@135 756 switch (c) {
adamc@135 757 case '<':
adamc@311 758 uw_write_unsafe(ctx, "&lt;");
adamc@135 759 break;
adamc@135 760 case '&':
adamc@311 761 uw_write_unsafe(ctx, "&amp;");
adamc@135 762 break;
adamc@135 763 default:
adamc@135 764 if (isprint(c))
adamc@311 765 uw_writec_unsafe(ctx, c);
adamc@135 766 else {
adamc@311 767 uw_write_unsafe(ctx, "&#");
adamc@311 768 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 769 uw_writec_unsafe(ctx, ';');
adamc@135 770 }
adamc@135 771 }
adamc@135 772 }
adamc@428 773
adamc@428 774 return uw_unit_v;
adamc@135 775 }
adamc@180 776
adamc@311 777 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 778 if (b == uw_Basis_False)
adamc@286 779 return "False";
adamc@286 780 else
adamc@286 781 return "True";
adamc@286 782 }
adamc@286 783
adamc@428 784 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 785 if (b == uw_Basis_False) {
adamc@311 786 uw_check(ctx, 6);
adamc@286 787 strcpy(ctx->page_front, "False");
adamc@286 788 ctx->page_front += 5;
adamc@286 789 } else {
adamc@311 790 uw_check(ctx, 5);
adamc@286 791 strcpy(ctx->page_front, "True");
adamc@286 792 ctx->page_front += 4;
adamc@286 793 }
adamc@428 794
adamc@428 795 return uw_unit_v;
adamc@286 796 }
adamc@286 797
adamc@436 798 #define TIME_FMT "%x %X"
adamc@438 799 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 800
adamc@436 801 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 802 size_t len;
adamc@436 803 char *r;
adamc@436 804 struct tm stm;
adamc@436 805
adamc@436 806 if (localtime_r(&t, &stm)) {
adamc@436 807 uw_check_heap(ctx, TIMES_MAX);
adamc@436 808 r = ctx->heap_front;
adamc@436 809 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 810 ctx->heap_front += len+1;
adamc@436 811 return r;
adamc@436 812 } else
adamc@436 813 return "<i>Invalid time</i>";
adamc@436 814 }
adamc@436 815
adamc@436 816 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 817 size_t len;
adamc@436 818 char *r;
adamc@436 819 struct tm stm;
adamc@436 820
adamc@436 821 if (localtime_r(&t, &stm)) {
adamc@436 822 uw_check(ctx, TIMES_MAX);
adamc@436 823 r = ctx->page_front;
adamc@436 824 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 825 ctx->page_front += len;
adamc@436 826 } else {
adamc@436 827 uw_check(ctx, 20);
adamc@436 828 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 829 ctx->page_front += 19;
adamc@436 830 }
adamc@436 831
adamc@436 832 return uw_unit_v;
adamc@436 833 }
adamc@436 834
adamc@311 835 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 836 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 837 char *s;
adamc@180 838
adamc@311 839 uw_check_heap(ctx, len);
adamc@180 840
adamc@180 841 s = ctx->heap_front;
adamc@180 842
adamc@180 843 strcpy(s, s1);
adamc@180 844 strcat(s, s2);
adamc@180 845 ctx->heap_front += len;
adamc@180 846
adamc@180 847 return s;
adamc@180 848 }
adamc@278 849
adamc@311 850 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 851 int len = strlen(s1) + 1;
adamc@278 852 char *s;
adamc@278 853
adamc@311 854 uw_check_heap(ctx, len);
adamc@278 855
adamc@278 856 s = ctx->heap_front;
adamc@278 857
adamc@278 858 strcpy(s, s1);
adamc@278 859 ctx->heap_front += len;
adamc@278 860
adamc@278 861 return s;
adamc@278 862 }
adamc@280 863
adamc@280 864
adamc@311 865 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 866 int len;
adamc@281 867 char *r;
adamc@281 868
adamc@311 869 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 870 r = ctx->heap_front;
adamc@281 871 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 872 ctx->heap_front += len+1;
adamc@281 873 return r;
adamc@281 874 }
adamc@281 875
adamc@467 876 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
adamc@467 877 if (n == NULL)
adamc@467 878 return "NULL";
adamc@467 879 else
adamc@467 880 return uw_Basis_sqlifyInt(ctx, *n);
adamc@467 881 }
adamc@467 882
adamc@311 883 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 884 int len;
adamc@281 885 char *r;
adamc@281 886
adamc@311 887 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 888 r = ctx->heap_front;
adamc@281 889 sprintf(r, "%g::float8%n", n, &len);
adamc@281 890 ctx->heap_front += len+1;
adamc@281 891 return r;
adamc@281 892 }
adamc@281 893
adamc@467 894 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
adamc@467 895 if (n == NULL)
adamc@467 896 return "NULL";
adamc@467 897 else
adamc@467 898 return uw_Basis_sqlifyFloat(ctx, *n);
adamc@467 899 }
adamc@467 900
adamc@281 901
adamc@311 902 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 903 char *r, *s2;
adamc@280 904
adamc@311 905 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 906
adamc@280 907 r = s2 = ctx->heap_front;
adamc@280 908 *s2++ = 'E';
adamc@280 909 *s2++ = '\'';
adamc@280 910
adamc@280 911 for (; *s; s++) {
adamc@280 912 char c = *s;
adamc@280 913
adamc@280 914 switch (c) {
adamc@280 915 case '\'':
adamc@280 916 strcpy(s2, "\\'");
adamc@280 917 s2 += 2;
adamc@280 918 break;
adamc@280 919 case '\\':
adamc@280 920 strcpy(s2, "\\\\");
adamc@280 921 s2 += 2;
adamc@280 922 break;
adamc@280 923 default:
adamc@280 924 if (isprint(c))
adamc@280 925 *s2++ = c;
adamc@280 926 else {
adamc@280 927 sprintf(s2, "\\%3o", c);
adamc@280 928 s2 += 4;
adamc@280 929 }
adamc@280 930 }
adamc@280 931 }
adamc@280 932
adamc@281 933 strcpy(s2, "'::text");
adamc@281 934 ctx->heap_front = s2 + 8;
adamc@280 935 return r;
adamc@280 936 }
adamc@281 937
adamc@467 938 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
adamc@467 939 if (s == NULL)
adamc@467 940 return "NULL";
adamc@467 941 else
adamc@467 942 return uw_Basis_sqlifyString(ctx, s);
adamc@467 943 }
adamc@467 944
adamc@311 945 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 946 if (b == uw_Basis_False)
adamc@281 947 return "FALSE";
adamc@281 948 else
adamc@281 949 return "TRUE";
adamc@281 950 }
adamc@282 951
adamc@467 952 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
adamc@467 953 if (b == NULL)
adamc@467 954 return "NULL";
adamc@467 955 else
adamc@467 956 return uw_Basis_sqlifyBool(ctx, *b);
adamc@467 957 }
adamc@467 958
adamc@439 959 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 960 size_t len;
adamc@439 961 char *r;
adamc@439 962 struct tm stm;
adamc@439 963
adamc@439 964 if (localtime_r(&t, &stm)) {
adamc@439 965 uw_check_heap(ctx, TIMES_MAX);
adamc@439 966 r = ctx->heap_front;
adamc@439 967 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 968 ctx->heap_front += len+1;
adamc@439 969 return r;
adamc@439 970 } else
adamc@439 971 return "<Invalid time>";
adamc@439 972 }
adamc@439 973
adamc@467 974 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
adamc@467 975 if (t == NULL)
adamc@467 976 return "NULL";
adamc@467 977 else
adamc@467 978 return uw_Basis_sqlifyTime(ctx, *t);
adamc@467 979 }
adamc@467 980
adamc@311 981 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 982 static uw_Basis_int true = 1;
adamc@311 983 static uw_Basis_int false = 0;
adamc@282 984
adamc@311 985 if (b == uw_Basis_False)
adamc@282 986 return (char *)&false;
adamc@282 987 else
adamc@282 988 return (char *)&true;
adamc@282 989 }
adamc@284 990
adamc@311 991 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 992 int len;
adamc@284 993 char *r;
adamc@284 994
adamc@311 995 uw_check_heap(ctx, INTS_MAX);
adamc@284 996 r = ctx->heap_front;
adamc@284 997 sprintf(r, "%lld%n", n, &len);
adamc@284 998 ctx->heap_front += len+1;
adamc@284 999 return r;
adamc@284 1000 }
adamc@285 1001
adamc@311 1002 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 1003 int len;
adamc@285 1004 char *r;
adamc@285 1005
adamc@311 1006 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 1007 r = ctx->heap_front;
adamc@285 1008 sprintf(r, "%g%n", n, &len);
adamc@285 1009 ctx->heap_front += len+1;
adamc@285 1010 return r;
adamc@285 1011 }
adamc@285 1012
adamc@311 1013 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 1014 if (b == uw_Basis_False)
adamc@285 1015 return "False";
adamc@285 1016 else
adamc@285 1017 return "True";
adamc@285 1018 }
adamc@288 1019
adamc@436 1020 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 1021 size_t len;
adamc@436 1022 char *r;
adamc@436 1023 struct tm stm;
adamc@436 1024
adamc@436 1025 if (localtime_r(&t, &stm)) {
adamc@436 1026 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1027 r = ctx->heap_front;
adamc@436 1028 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1029 ctx->heap_front += len+1;
adamc@436 1030 return r;
adamc@436 1031 } else
adamc@436 1032 return "<Invalid time>";
adamc@436 1033 }
adamc@288 1034
adamc@311 1035 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1036 char *endptr;
adamc@311 1037 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1038
adamc@288 1039 if (*s != '\0' && *endptr == '\0') {
adamc@311 1040 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1041 *r = n;
adamc@288 1042 return r;
adamc@288 1043 } else
adamc@288 1044 return NULL;
adamc@288 1045 }
adamc@289 1046
adamc@311 1047 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1048 char *endptr;
adamc@311 1049 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1050
adamc@289 1051 if (*s != '\0' && *endptr == '\0') {
adamc@311 1052 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1053 *r = n;
adamc@289 1054 return r;
adamc@289 1055 } else
adamc@289 1056 return NULL;
adamc@289 1057 }
adamc@289 1058
adamc@311 1059 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1060 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1061 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1062
adamc@289 1063 if (!strcasecmp (s, "True"))
adamc@289 1064 return &true;
adamc@289 1065 else if (!strcasecmp (s, "False"))
adamc@289 1066 return &false;
adamc@289 1067 else
adamc@289 1068 return NULL;
adamc@289 1069 }
adamc@292 1070
adamc@436 1071 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1072 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1073 struct tm stm;
adamc@436 1074
adamc@439 1075 if (dot) {
adamc@439 1076 *dot = 0;
adamc@439 1077 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1078 *dot = '.';
adamc@439 1079 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1080 *r = mktime(&stm);
adamc@439 1081 return r;
adamc@439 1082 }
adamc@439 1083 else {
adamc@439 1084 *dot = '.';
adamc@439 1085 return NULL;
adamc@439 1086 }
adamc@436 1087 }
adamc@439 1088 else {
adamc@439 1089 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1090 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1091 *r = mktime(&stm);
adamc@439 1092 return r;
adamc@439 1093 }
adamc@439 1094 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1095 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1096 *r = mktime(&stm);
adamc@439 1097 return r;
adamc@439 1098 }
adamc@439 1099 else
adamc@439 1100 return NULL;
adamc@439 1101 }
adamc@436 1102 }
adamc@436 1103
adamc@311 1104 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1105 char *endptr;
adamc@311 1106 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1107
adamc@292 1108 if (*s != '\0' && *endptr == '\0')
adamc@292 1109 return n;
adamc@292 1110 else
adamc@311 1111 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1112 }
adamc@293 1113
adamc@311 1114 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1115 char *endptr;
adamc@311 1116 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1117
adamc@293 1118 if (*s != '\0' && *endptr == '\0')
adamc@293 1119 return n;
adamc@293 1120 else
adamc@311 1121 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1122 }
adamc@293 1123
adamc@311 1124 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1125 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1126 return uw_Basis_True;
adamc@296 1127 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1128 return uw_Basis_False;
adamc@293 1129 else
adamc@311 1130 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1131 }
adamc@436 1132
adamc@436 1133 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1134 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1135 struct tm stm = {};
adamc@436 1136
adamc@438 1137 if (dot) {
adamc@438 1138 *dot = 0;
adamc@438 1139 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1140 *dot = '.';
adamc@438 1141 return mktime(&stm);
adamc@438 1142 }
adamc@438 1143 else {
adamc@438 1144 *dot = '.';
adamc@438 1145 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1146 }
adamc@438 1147 }
adamc@438 1148 else {
adamc@439 1149 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1150 return mktime(&stm);
adamc@439 1151 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1152 return mktime(&stm);
adamc@438 1153 else
adamc@438 1154 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1155 }
adamc@436 1156 }
adamc@457 1157
adamc@457 1158 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1159 int len = strlen(h);
adamc@457 1160 char *s = ctx->headers, *p;
adamc@457 1161
adamc@457 1162 while (p = strchr(s, ':')) {
adamc@457 1163 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1164 return p + 2;
adamc@457 1165 } else {
adamc@458 1166 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1167 s += 2;
adamc@457 1168 else
adamc@457 1169 return NULL;
adamc@457 1170 }
adamc@457 1171 }
adamc@463 1172 }
adamc@458 1173
adamc@463 1174 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1175 int len = strlen(c);
adamc@474 1176 char *s = ctx->headers, *p = ctx->outHeaders;
adamc@474 1177
adamc@474 1178 while (p = strstr(p, "\nSet-Cookie: ")) {
adamc@474 1179 char *p2;
adamc@474 1180 p += 13;
adamc@474 1181 p2 = strchr(p, '=');
adamc@474 1182
adamc@474 1183 if (p2) {
adamc@474 1184 size_t sz = strcspn(p2+1, ";\r\n");
adamc@474 1185
adamc@474 1186 if (!strncasecmp(p, c, p2 - p)) {
adamc@474 1187 char *ret = uw_malloc(ctx, sz + 1);
adamc@474 1188 memcpy(ret, p2+1, sz);
adamc@474 1189 ret[sz] = 0;
adamc@474 1190 return ret;
adamc@474 1191 }
adamc@474 1192 }
adamc@474 1193 }
adamc@463 1194
adamc@463 1195 while (p = strchr(s, ':')) {
adamc@476 1196 if (!strncasecmp(s, "Cookie: ", 8)) {
adamc@476 1197 p += 2;
adamc@476 1198 while (1) {
adamc@476 1199 if (!strncmp(p, c, len)
adamc@476 1200 && p + len < ctx->headers_end && p[len] == '=')
adamc@476 1201 return p + 1 + len;
adamc@476 1202 else if (p = strchr(p, ';'))
adamc@476 1203 p += 2;
adamc@476 1204 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
adamc@476 1205 s += 2;
adamc@476 1206 break;
adamc@476 1207 }
adamc@476 1208 else
adamc@476 1209 return NULL;
adamc@476 1210 }
adamc@463 1211 } else {
adamc@463 1212 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1213 s += 2;
adamc@463 1214 else
adamc@463 1215 return NULL;
adamc@463 1216 }
adamc@463 1217 }
adamc@457 1218 }
adamc@462 1219
adamc@466 1220 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1221 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1222 uw_write_header(ctx, c);
adamc@462 1223 uw_write_header(ctx, "=");
adamc@462 1224 uw_write_header(ctx, v);
adamc@466 1225 uw_write_header(ctx, "; path=");
adamc@466 1226 uw_write_header(ctx, prefix);
adamc@462 1227 uw_write_header(ctx, "\r\n");
adamc@462 1228
adamc@462 1229 return uw_unit_v;
adamc@462 1230 }