annotate src/c/urweb.c @ 660:9abeb533f6a7

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