#include "settings.h" #include "json.h" #include "string.h" #include "arena.h" #include "scratch.h" #include "math.h" struct string settings_serialize(struct arena *arena, const struct sys_window_settings *settings) { __prof; struct string minimized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED ? LIT("true") : LIT("false"); struct string maximized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED ? LIT("true") : LIT("false"); struct string fullscreen = settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN ? LIT("true") : LIT("false"); i32 x = settings->floating_x; i32 y = settings->floating_y; i32 width = settings->floating_width; i32 height = settings->floating_height; struct string fmt = LIT( "{\n" " \"window\": {\n" " \"minimized\": %F,\n" " \"maximized\": %F,\n" " \"fullscreen\": %F,\n" " \"x\": %F,\n" " \"y\": %F,\n" " \"width\": %F,\n" " \"height\": %F\n" " }\n" "}\n" ); struct string formatted = string_format(arena, fmt, FMT_STR(minimized), FMT_STR(maximized), FMT_STR(fullscreen), FMT_SINT(x), FMT_SINT(y), FMT_SINT(width), FMT_SINT(height)); return formatted; } struct sys_window_settings *settings_deserialize(struct arena *arena, struct string src, struct string *error_out) { __prof; struct temp_arena scratch = scratch_begin(arena); struct string error = ZI; struct json_error json_error = ZI; struct sys_window_settings *settings = arena_push_zero(arena, struct sys_window_settings); struct json_parse_result parse_res = json_from_string(scratch.arena, src); if (parse_res.errors.count > 0) { json_error = *parse_res.errors.first; goto abort; } struct json *root = parse_res.root; if (!root) { error = LIT("Root object not found."); goto abort; } struct json *window = root->child_first; if (!window || window->type != JSON_TYPE_OBJECT || !string_eq(window->key, LIT("window"))) { error = LIT("\"window\" object not found"); goto abort; } b32 found_maximized = false; b32 found_fullscreen = false; b32 found_x = false; b32 found_y = false; b32 found_width = false; b32 found_height = false; for (struct json *child = window->child_first; child; child = child->next) { struct string key = child->key; if (string_eq(key, LIT("maximized"))) { if (child->type != JSON_TYPE_BOOL) { error = LIT("Expected boolean for \"maximized\""); goto abort; } if (child->value.boolean) { settings->flags |= SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED; } found_maximized = true; } else if (string_eq(key, LIT("fullscreen"))) { if (child->type != JSON_TYPE_BOOL) { error = LIT("Expected boolean for \"fulscreen\""); goto abort; } if (child->value.boolean) { settings->flags |= SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN; } found_fullscreen = true; } else if (string_eq(key, LIT("x"))) { if (child->type != JSON_TYPE_NUMBER) { error = LIT("Expected number for \"x\""); goto abort; } settings->floating_x = math_round_to_int(child->value.number); found_x = true; } else if (string_eq(key, LIT("y"))) { if (child->type != JSON_TYPE_NUMBER) { error = LIT("Expected number for \"y\""); goto abort; } settings->floating_y = math_round_to_int(child->value.number); found_y = true; } else if (string_eq(key, LIT("width"))) { if (child->type != JSON_TYPE_NUMBER) { error = LIT("Expected number for \"width\""); goto abort; } settings->floating_width = math_round_to_int(child->value.number); found_width = true; } else if (string_eq(key, LIT("height"))) { if (child->type != JSON_TYPE_NUMBER) { error = LIT("Expected number for \"height\""); goto abort; } settings->floating_height = math_round_to_int(child->value.number); found_height = true; } } if (!found_maximized) { error = LIT("Missing \"maximized\""); goto abort; } if (!found_fullscreen) { error = LIT("Missing \"fullscreen\""); goto abort; } if (!found_x) { error = LIT("Missing \"x\""); goto abort; } if (!found_y) { error = LIT("Missing \"y\""); goto abort; } if (!found_width) { error = LIT("Missing \"width\""); goto abort; } if (!found_height) { error = LIT("Missing \"height\""); goto abort; } abort: if (error_out && (error.len > 0 || json_error.msg.len > 0)) { if (json_error.msg.len > 0) { *error_out = string_format(arena, LIT("%F\n(%F:%F)"), FMT_STR(json_error.msg), FMT_UINT(json_error.start), FMT_UINT(json_error.end)); } else { *error_out = string_copy(arena, error); } } scratch_end(scratch); return settings; }