+#include <mongoose.h>\r
+#define STB_DS_IMPLEMENTATION\r
+#include <stb_ds.h>\r
+\r
+\r
+#define NAME_LEN 32\r
+#define CONTENT_LEN 1024\r
+#define HTML_LEN 1024*8\r
+\r
+typedef struct post Post;\r
+typedef struct user User;\r
+\r
+User * UsersFind(struct mg_str name);\r
+\r
+// Post\r
+\r
+struct post {\r
+ time_t timestamp;\r
+ User * user;\r
+ char content[CONTENT_LEN];\r
+};\r
+\r
+\r
+\r
+// User\r
+\r
+struct user {\r
+ char name[NAME_LEN];\r
+ Post * posts;\r
+ User ** following;\r
+};\r
+\r
+User\r
+UserNew(const char * name) {\r
+ User result;\r
+ strcpy(result.name, name);\r
+ result.posts = NULL;\r
+ result.following = NULL;\r
+ return result;\r
+}\r
+\r
+void\r
+UserWrite(User * user) {\r
+ char filename[128];\r
+ snprintf(filename, 128, "data/users/%s", user->name);\r
+ FILE * f = fopen(filename, "w");\r
+\r
+ int numFollowing = arrlen(user->following);\r
+ int numPosts = arrlen(user->posts);\r
+ fwrite(&numFollowing, sizeof(int), 1, f);\r
+ fwrite(&numPosts, sizeof(int), 1, f);\r
+ for (int i = 0; i < numFollowing; i++) {\r
+ fwrite(user->following[i]->name, 1, sizeof(user->following[i]->name), f);\r
+ }\r
+ for (int i = 0; i < numPosts; i++) {\r
+ fwrite(&user->posts[i].timestamp, sizeof(user->posts[i].timestamp), 1, f);\r
+ fwrite(user->posts[i].user->name, 1, sizeof(user->posts[i].user->name), f);\r
+ fwrite(user->posts[i].content, 1, sizeof(user->posts[i].content), f);\r
+ }\r
+ fclose(f);\r
+}\r
+\r
+void\r
+UserRead(User * user) {\r
+ char filename[128];\r
+ snprintf(filename, 128, "data/users/%s", user->name);\r
+ FILE * f = fopen(filename, "r");\r
+\r
+ int numFollowing;\r
+ int numPosts;\r
+ fread(&numFollowing, sizeof(int), 1, f);\r
+ fread(&numPosts, sizeof(int), 1, f);\r
+ for (int i = 0; i < numFollowing; i++) {\r
+ char name[NAME_LEN];\r
+ fread(name, 1, sizeof(name), f);\r
+ arrput(user->following, UsersFind(mg_str(name)));\r
+ }\r
+ for (int i = 0; i < numPosts; i++) {\r
+ char name[NAME_LEN];\r
+ Post post;\r
+ fread(&post.timestamp, sizeof(post.timestamp), 1, f);\r
+ fread(name, 1, sizeof(name), f);\r
+ post.user = UsersFind(mg_str(name));\r
+ fread(post.content, 1, sizeof(post.content), f);\r
+ }\r
+ fclose(f);\r
+}\r
+\r
+\r
+\r
+// Users\r
+\r
+User ** g_users;\r
+static User pat, yas, tof;\r
+\r
+void\r
+UsersSetup() {\r
+ pat = UserNew("pat");\r
+ yas = UserNew("yas");\r
+ tof = UserNew("tof");\r
+\r
+ UserRead(&pat);\r
+ UserRead(&yas);\r
+ UserRead(&tof);\r
+\r
+ arrput(pat.following, &yas);\r
+ arrput(yas.following, &pat);\r
+ arrput(tof.following, &yas);\r
+ arrput(tof.following, &pat);\r
+\r
+ arrput(g_users, &pat);\r
+ arrput(g_users, &yas);\r
+ arrput(g_users, &tof);\r
+}\r
+\r
+User *\r
+UsersFind(struct mg_str name) {\r
+ for (int i = 0; i < arrlen(g_users); i++) {\r
+ User * user = g_users[i];\r
+ if (strncmp(user->name, name.ptr, name.len) == 0)\r
+ return user;\r
+ }\r
+ return NULL;\r
+}\r
+\r