2
0
Fork 0
lighttpd2/src/main/chunk_parser.c

107 lines
2.8 KiB
C
Raw Normal View History

#include <lighttpd/base.h>
2009-07-09 20:17:24 +00:00
void li_chunk_parser_init(liChunkParserCtx *ctx, liChunkQueue *cq) {
ctx->cq = cq;
2009-07-09 20:17:24 +00:00
li_chunk_parser_reset(ctx);
2008-08-05 15:08:32 +00:00
}
2009-07-09 20:17:24 +00:00
void li_chunk_parser_reset(liChunkParserCtx *ctx) {
ctx->bytes_in = 0;
ctx->curi.element = NULL;
ctx->start = 0;
ctx->length = 0;
ctx->buf = NULL;
}
2009-07-09 20:17:24 +00:00
liHandlerResult li_chunk_parser_prepare(liChunkParserCtx *ctx) {
if (NULL == ctx->curi.element) {
2009-09-26 18:31:52 +00:00
ctx->curi = li_chunkqueue_iter(ctx->cq);
if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;
}
return LI_HANDLER_GO_ON;
}
2009-07-09 20:17:24 +00:00
liHandlerResult li_chunk_parser_next(liVRequest *vr, liChunkParserCtx *ctx, char **p, char **pe) {
off_t l;
liHandlerResult res;
if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;
2009-09-26 18:31:52 +00:00
while (ctx->start >= (l = li_chunkiter_length(ctx->curi))) {
liChunkIter i = ctx->curi;
/* Wait at the end of the last chunk if it gets extended */
2009-09-26 18:31:52 +00:00
if (!li_chunkiter_next(&i)) return LI_HANDLER_WAIT_FOR_EVENT;
ctx->curi = i;
2008-08-04 22:25:42 +00:00
ctx->start -= l;
}
if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;
2009-07-09 20:17:24 +00:00
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length))) {
return res;
}
*p = ctx->buf;
*pe = ctx->buf + ctx->length;
return LI_HANDLER_GO_ON;
}
2009-07-09 20:17:24 +00:00
void li_chunk_parser_done(liChunkParserCtx *ctx, goffset len) {
ctx->bytes_in += len;
ctx->start += len;
}
2009-07-09 20:17:24 +00:00
gboolean li_chunk_extract_to(liVRequest *vr, liChunkParserMark from, liChunkParserMark to, GString *dest) {
liChunkParserMark i;
g_string_set_size(dest, to.abs_pos - from.abs_pos);
li_g_string_clear(dest);
2008-08-04 22:25:42 +00:00
2009-09-26 18:31:52 +00:00
for ( i = from; i.ci.element != to.ci.element; li_chunkiter_next(&i.ci) ) {
goffset len = li_chunkiter_length(i.ci);
while (i.pos < len) {
char *buf;
off_t we_have;
2009-07-09 20:17:24 +00:00
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, i.ci, i.pos, len - i.pos, &buf, &we_have)) goto error;
if (dest->len + we_have < dest->allocated_len) {
/* "fast" append */
memcpy(dest->str + dest->len, buf, we_have);
dest->len += we_have;
dest->str[dest->len] = '\0';
} else {
g_string_append_len(dest, buf, we_have);
}
i.pos += we_have;
}
i.pos = 0;
}
while (i.pos < to.pos) {
char *buf;
off_t we_have;
2009-07-09 20:17:24 +00:00
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, i.ci, i.pos, to.pos - i.pos, &buf, &we_have)) goto error;
if (dest->len + we_have < dest->allocated_len) {
/* "fast" append */
memcpy(dest->str + dest->len, buf, we_have);
dest->len += we_have;
dest->str[dest->len] = '\0';
} else {
g_string_append_len(dest, buf, we_have);
}
i.pos += we_have;
}
2008-08-04 22:25:42 +00:00
return TRUE;
error:
li_g_string_clear(dest);
2008-08-04 22:25:42 +00:00
return FALSE;
}
2009-07-09 20:17:24 +00:00
GString* li_chunk_extract(liVRequest *vr, liChunkParserMark from, liChunkParserMark to) {
2008-08-04 22:25:42 +00:00
GString *str = g_string_sized_new(0);
2009-07-09 20:17:24 +00:00
if (li_chunk_extract_to(vr, from, to, str)) return str;
g_string_free(str, TRUE);
return NULL;
}