annotate src/c/urweb.c @ 574:ac947e2f29ff

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