diff options
author | Shav Kinderlehrer <[email protected]> | 2024-07-23 17:48:28 -0400 |
---|---|---|
committer | Shav Kinderlehrer <[email protected]> | 2024-07-23 17:48:28 -0400 |
commit | dc0f2ce9ba97ebb47e05b80a511da6eb29818b63 (patch) | |
tree | dc83035069f5a015047be1ca3da6f65781eb4695 /src/molerat/response.c | |
parent | f638f4bd1e3a03bc2bdd5f9dcd57d4830fd3c553 (diff) | |
download | molehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.tar.gz molehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.zip |
Merge old-moleholencurses
Diffstat (limited to 'src/molerat/response.c')
-rwxr-xr-x | src/molerat/response.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/molerat/response.c b/src/molerat/response.c new file mode 100755 index 0000000..0fffe21 --- /dev/null +++ b/src/molerat/response.c @@ -0,0 +1,215 @@ +#include <stdlib.h> +#include <string.h> + +#include "response.h" + +#define SET_STR(segment) \ + (segment) = malloc(i - start + 1); \ + strncpy((segment), s + start, i - start); + +#define MOVE(amount) \ + i += (amount); \ + start = i; + +#define CHECK_AT_END() \ + if (cur == '\0') { \ + state = END; \ + } + +#define AT_DELIM (cur == '\t' && next == '\r' && next_next == '\n') + +enum state { + STATUS, + + MESSAGE, + MESSAGE_S, + + TYPE_S, + TYPE, + + LENGTH_S, + LENGTH, + + HASH, + HASH_S, + + CONTENT, + END +}; + +int parse_response(struct response *res, char *s) { + int i = 0; + int start = 0; + char cur; + char next; + char next_next; + + int s_len = strlen(s); + + enum state state = STATUS; + + while (state != END) { + cur = s[i]; + if (i < s_len) + next = s[i + 1]; + if (i + 1 < s_len) + next_next = s[i + 2]; + + switch (state) { + case STATUS: + if (cur == '\r' && next == '\n') { + char *status_str; + SET_STR(status_str); + int status = atoi(status_str); + if (status > 0) + res->status = status; + else + return INVALID_STATUS; + free(status_str); + + MOVE(2); + state = MESSAGE; + } + + break; + case MESSAGE: + if (cur == ':') { + char *message_str; + SET_STR(message_str); + if (strncmp(message_str, "message", 7) != 0) { + MOVE(strlen(message_str) * -1); + state = TYPE; + break; + } else { + MOVE(1); // skip ':' + state = MESSAGE_S; + } + + free(message_str); + } + break; + case MESSAGE_S: + if (AT_DELIM) { + char *message_str; + SET_STR(message_str); + res->message = message_str; + + MOVE(3); + state = TYPE; + } + + break; + case TYPE: + if (cur == ':') { + char *type_str; + SET_STR(type_str); + if (strncmp(type_str, "type", 4) != 0) { + MOVE(strlen(type_str) * -1); + state = LENGTH; + } else { + MOVE(1); // skip ':' + state = TYPE_S; + } + + free(type_str); + } + break; + case TYPE_S: + if (cur == '/') { + SET_STR(res->type.type); + MOVE(1); + } else if (AT_DELIM) { + SET_STR(res->type.subtype); + + MOVE(3); + state = LENGTH; + } + break; + + case LENGTH: + if (cur == ':') { + char *length_str; + SET_STR(length_str); + if (strncmp(length_str, "length", 6) != 0) { + MOVE(strlen(length_str) * -1); + state = HASH; + } else { + MOVE(1); // skip ':' + state = LENGTH_S; + } + free(length_str); + } + + case LENGTH_S: + if (AT_DELIM) { + char *length_str; + SET_STR(length_str); + res->length = atoi(length_str); + free(length_str); + + MOVE(3); + state = HASH; + } + break; + + case HASH: + if (cur == ':') { + char *hash_str; + SET_STR(hash_str); + if (strncmp(hash_str, "hash", 4) != 0) { + MOVE(strlen(hash_str) * -1); + free(hash_str); + return UNKNOWN_KEY; + } else { + MOVE(1); // skip ':' + state = HASH_S; + } + free(hash_str); + } + break; + case HASH_S: + if ((cur == '\r' && next == '\n') || AT_DELIM) { + char *hash_str; + SET_STR(hash_str); + res->hash = hash_str; + + MOVE(4); + state = CONTENT; + } + + case CONTENT: + if (res->length < 1) { + state = END; + break; + } + + if (i == s_len - 1) { + char *content_str; + SET_STR(content_str); + res->content = content_str; + + state = END; + } + + case END: + break; + } + + i++; + if (i == s_len) { + state = END; + } + } + + return 0; +} + +void free_response(struct response *res) { + free(res->message); + + free(res->type.type); + free(res->type.subtype); + + free(res->hash); + free(res->content); +} |