summaryrefslogtreecommitdiff
path: root/src/c/lacweb.c
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2008-07-13 15:44:00 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2008-07-13 15:44:00 -0400
commitc54e3eca0a8d7e72f12801bc5ec993dddfa7958b (patch)
treea37326be0f01025df57b4f3bf1f209528042df1c /src/c/lacweb.c
parent0eb51a6e21e5f435d37afd885ae316a0575c7208 (diff)
Serving pages
Diffstat (limited to 'src/c/lacweb.c')
-rw-r--r--src/c/lacweb.c105
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("&quot;");
+ lw_write_unsafe(ctx, "&quot;");
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);
}