diff options
author | Adam Chlipala <adamc@hcoop.net> | 2008-07-13 15:44:00 -0400 |
---|---|---|
committer | Adam Chlipala <adamc@hcoop.net> | 2008-07-13 15:44:00 -0400 |
commit | c54e3eca0a8d7e72f12801bc5ec993dddfa7958b (patch) | |
tree | a37326be0f01025df57b4f3bf1f209528042df1c /src/c/lacweb.c | |
parent | 0eb51a6e21e5f435d37afd885ae316a0575c7208 (diff) |
Serving pages
Diffstat (limited to 'src/c/lacweb.c')
-rw-r--r-- | src/c/lacweb.c | 105 |
1 files changed, 90 insertions, 15 deletions
diff --git a/src/c/lacweb.c b/src/c/lacweb.c index 10ccd6a0..ef8e7184 100644 --- a/src/c/lacweb.c +++ b/src/c/lacweb.c @@ -1,16 +1,75 @@ +#include <stdlib.h> #include <stdio.h> +#include <string.h> #include <ctype.h> #include "types.h" lw_unit lw_unit_v = {}; -void lw_writec(char c) { - fputc(c, stdout); +struct lw_context { + char *page, *page_front, *page_back; +}; + +lw_context lw_init(int page_len) { + lw_context ctx = malloc(sizeof(struct lw_context)); + ctx->page_front = ctx->page = malloc(page_len); + ctx->page_back = ctx->page_front + page_len; + return ctx; +} + +void lw_free(lw_context ctx) { + free(ctx->page); +} + +int lw_really_send(int sock, const void *buf, ssize_t len) { + while (len > 0) { + ssize_t n = send(sock, buf, len, 0); + + if (n < 0) + return n; + + buf += n; + len -= n; + } + + return 0; } -void lw_write(const char* s) { - fputs(s, stdout); +int lw_send(lw_context ctx, int sock) { + return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page); +} + +static void lw_check(lw_context ctx, size_t extra) { + size_t desired = ctx->page_back - ctx->page_front + extra, next; + char *new_page; + + for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2); + + new_page = realloc(ctx->page, next); + ctx->page_front = new_page + (ctx->page_front - ctx->page); + ctx->page_back = new_page + (ctx->page_back - ctx->page); + ctx->page = new_page; +} + +static void lw_writec_unsafe(lw_context ctx, char c) { + *(ctx->page_front)++ = c; +} + +void lw_writec(lw_context ctx, char c) { + lw_check(ctx, 1); + lw_writec_unsafe(ctx, c); +} + +static void lw_write_unsafe(lw_context ctx, const char* s) { + int len = strlen(s); + memcpy(ctx->page_front, s, len); + ctx->page_front += len; +} + +void lw_write(lw_context ctx, const char* s) { + lw_check(ctx, strlen(s)); + lw_write_unsafe(ctx, s); } char *lw_Basis_attrifyInt(lw_Basis_int n) { @@ -25,27 +84,43 @@ char *lw_Basis_attrifyString(lw_Basis_string s) { return ""; } -char *lw_Basis_attrifyInt_w(lw_Basis_int n) { - printf("%d", n); +#define INTS_MAX 50 +#define FLOATS_MAX 100 + +static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) { + int len; + + sprintf(ctx->page_front, "%d%n", n, &len); + ctx->page_front += len; +} + +void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) { + lw_check(ctx, INTS_MAX); + lw_Basis_attrifyInt_w_unsafe(ctx, n); } -char *lw_Basis_attrifyFloat_w(lw_Basis_float n) { - printf("%g", n); +void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) { + int len; + + lw_check(ctx, FLOATS_MAX); + sprintf(ctx->page_front, "%g%n", n, &len); + ctx->page_front += len; } -char *lw_Basis_attrifyString_w(lw_Basis_string s) { +void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) { + lw_check(ctx, strlen(s) * 6); + for (; *s; s++) { char c = *s; if (c == '"') - lw_write("""); + lw_write_unsafe(ctx, """); else if (isprint(c)) - lw_writec(c); + lw_writec_unsafe(ctx, c); else { - lw_write("&#"); - lw_Basis_attrifyInt_w(c); - lw_writec(';'); + lw_write_unsafe(ctx, "&#"); + lw_Basis_attrifyInt_w_unsafe(ctx, c); + lw_writec_unsafe(ctx, ';'); } } - lw_write(s); } |