aboutsummaryrefslogtreecommitdiff
path: root/src/molerat/response.c
diff options
context:
space:
mode:
authorShav Kinderlehrer <[email protected]>2024-07-23 17:48:28 -0400
committerShav Kinderlehrer <[email protected]>2024-07-23 17:48:28 -0400
commitdc0f2ce9ba97ebb47e05b80a511da6eb29818b63 (patch)
treedc83035069f5a015047be1ca3da6f65781eb4695 /src/molerat/response.c
parentf638f4bd1e3a03bc2bdd5f9dcd57d4830fd3c553 (diff)
downloadmolehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.tar.gz
molehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.zip
Merge old-moleholencurses
Diffstat (limited to 'src/molerat/response.c')
-rwxr-xr-xsrc/molerat/response.c215
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);
+}