power_play/src/settings.c

158 lines
5.7 KiB
C

#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;
}