parslib/tinyparser.c

233 lines
4.5 KiB
C
Raw Normal View History

2024-08-15 23:12:06 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tinyparser.h"
#include "streecmp/streecmp.h"
extern char *methods;
extern char *headers;
static struct nod *method_tree = NULL;
static struct nod *header_tree = NULL;
static void debug_stats(struct httpars *pars) {
fprintf(stderr, "\tstats:\n"
"\t\tmethod\t: %d\n"
"\t\turi\t: %.*s\n"
"\t\tver\t: %.*s\n",
pars->titl.method,
pars->titl.uri.len, pars->titl.uri.er,
pars->titl.ver.len, pars->titl.ver.er
);
fprintf(stdout, "\theaders:\n");
for (int i = 0; i < header_count; i++) {
struct point *pnt = &pars->hentries[i];
if (!pnt->er) {
continue;
}
fprintf(stdout, "\t\t%d\t: %.*s\n", i, pnt->len, pnt->er);
}
}
int initres(void) {
int ret = 0;
header_tree = allocnod();
if (!header_tree) {
return -1;
}
2024-08-15 23:12:06 +00:00
method_tree = allocnod();
if (!method_tree) {
return -1;
}
2024-08-15 23:12:06 +00:00
ret = gentree(header_tree, headers, NULL);
if (ret < 0) {
return -1;
}
ret = gentree(method_tree, methods, NULL);
if (ret < 0) {
return -1;
}
return 0;
}
void fretres(void) {
free(method_tree);
free(header_tree);
}
int read_line(char **buff, char **buff_lim) {
2024-08-15 23:12:06 +00:00
int diff = 0;
if ((*buff) >= (*buff_lim)) {
return diff;
}
2024-08-15 23:12:06 +00:00
int ret = 0;
char *match = strstr(*buff, "\r\n");
if (match) {
ret = match-(*buff);
*buff += 2;
} else {
ret = (*buff_lim)-(*buff);
}
*buff += ret;
return ret;
2024-08-15 23:12:06 +00:00
}
int parshfield(char *offset, int len, struct point *hentries) {
2024-09-03 19:51:27 +00:00
int key = 0;
int ret = 0;
2024-09-03 19:51:27 +00:00
int diff = 0;
char *cursor = offset;
char *cursor_lim = offset+len;
// header title
char *htitle_lim = strchr(cursor, ':');
2024-09-03 19:51:27 +00:00
if (!htitle_lim) {
return -1;
}
2024-09-03 19:51:27 +00:00
if (htitle_lim > cursor_lim) {
return -1;
}
2024-09-03 19:51:27 +00:00
diff = htitle_lim-cursor;
ret = streencmp(header_tree, cursor, diff);
if (!ret) {
return -1;
}
2024-09-03 19:51:27 +00:00
key = ret;
cursor += diff;
// white space and seperators
_loop:
if (cursor > cursor_lim) {
return -1;
}
if (*cursor == ':') {
cursor++;
goto _loop;
}
if (*cursor == ' ') {
2024-09-03 19:51:27 +00:00
cursor++;
goto _loop;
2024-09-03 19:51:27 +00:00
}
// header value
diff = cursor_lim-cursor;
hentries[key].er = cursor;
hentries[key].len = diff;
return 0;
}
int parstitle(char *offset, int len, struct httitle *titl) {
int ret = 0;
int diff = 0;
char *cursor = offset;
char *cursor_lim = cursor+len;
2024-08-15 23:12:06 +00:00
// method
char *method_lim = strchr(offset, ' ');
if (!method_lim) {
return -1;
}
if (method_lim > cursor_lim) {
return -1;
}
2024-08-15 23:12:06 +00:00
diff = method_lim-cursor;
ret = streencmp(method_tree, cursor, diff);
if (ret == 0) {
return -1;
}
2024-08-15 23:12:06 +00:00
titl->method = ret;
cursor += diff;
// white space
_loop1:
if (cursor > cursor_lim) {
return -1;
}
if (*cursor == ' ') {
cursor++;
goto _loop1;
}
// uri
char *uri_lim = strchr(cursor, ' ');
if (!uri_lim) {
return -1;
}
if (uri_lim > cursor_lim) {
return -1;
}
diff = uri_lim-cursor;
titl->uri.er = cursor;
titl->uri.len = diff;
cursor += diff;
// white space
_loop2:
if (cursor > cursor_lim) {
return -1;
}
if (*cursor == ' ') {
cursor++;
goto _loop2;
2024-08-15 23:12:06 +00:00
}
// ver
diff = cursor_lim-cursor;
titl->ver.er = cursor;
titl->ver.len = diff;
cursor += diff;
2024-08-15 23:12:06 +00:00
return 0;
}
int parsme(char *buff, struct httpars *pars) {
2024-08-15 23:12:06 +00:00
int ret;
char *buff_lim = buff+strlen(buff);
2024-08-15 23:12:06 +00:00
char *title_offset = buff;
int title_len = read_line(&buff, &buff_lim);
if ((ret = parstitle(title_offset, title_len, &pars->titl)) < 0) {
2024-08-15 23:12:06 +00:00
fprintf(stderr, "Failed parsing title\n");
return -1;
}
for (int bound = 0; bound < MAX_BOUND; bound++) {
char *header_offset = buff;
int header_len = read_line(&buff, &buff_lim);
char *header_limit = header_offset+header_len;
// IF END OF MESSAGE
if (!header_len) {
break;
}
if ((ret = parshfield(header_offset,
header_len,
pars->hentries)) < 0) {
fprintf(stderr, "Failed parsing header\n");
return -1;
}
}
2024-08-15 23:12:06 +00:00
return 0;
}