Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Created Mar 4, 2010
Embed
What would you like to do?
typedef void (*notify_callback_t)();
typedef void (*result_callback_t)(const char *str, size_t n);
typedef struct callbacks_t {
notify_callback_t request_begin, request_end;
result_callback_t request_method, request_url, request_protocol;
notify_callback_t header_begin, header_end;
result_callback_t header_name, header_value;
} callbacks_t;
#define CALLBACK(p, callback) (((callbacks_t *) (p)->userdata)->callback)
CHARCLASS(istoken, "^\x00-\x1f()<>@,;:\\\"/[]?={} \t\x80-\xff");
CHARCLASS(iseol, "\x0d\x0a");
CHARCLASS(ishspace, "\x09\x20");
CHARCLASS(ishttpversion, "\x2e\x30\x31");
void requestline(parser_t *p) {
CALLBACK(p, request_begin)();
const char *method = REMEMBER(p);
SKIPWHILE1(p, istoken);
CALLBACK(p, request_method)(method, LENGTH(p, method));
SKIPWHILE1(p, ishspace);
const char *url = REMEMBER(p);
SKIPWHILE1(p, !ishspace);
CALLBACK(p, request_url)(url, LENGTH(p, url));
SKIPWHILE1(p, ishspace);
STR(p, "HTTP/");
const char *protocol = REMEMBER(p);
SKIPWHILE1(p, ishttpversion);
CALLBACK(p, request_protocol)(protocol, LENGTH(p, protocol));
SKIP(p, iseol);
CALLBACK(p, request_end)();
}
void headercontents(parser_t *p) {
SKIPWHILE1(p, ishspace);
const char *value = REMEMBER(p);
SKIPWHILE(p, !iseol);
CALLBACK(p, header_value)(value, LENGTH(p, value));
NEXT(p);
}
void header(parser_t *p) {
CALLBACK(p, header_begin)();
const char *name = REMEMBER(p);
SKIPWHILE1(p, istoken);
CHAR(p, ':');
CALLBACK(p, header_name)(name, LENGTH(p, name));
SKIPWHILE1(p, ishspace);
const char *body = REMEMBER(p);
SKIPWHILE(p, !iseol);
CALLBACK(p, header_value)(body, LENGTH(p, body));
NEXT(p);
MANY(p, headercontents);
CALLBACK(p, header_end)();
}
void request(parser_t *p) {
requestline(p);
MANY(p, header);
SKIP(p, iseol);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment