rewrite json parser to be dumber

This commit is contained in:
jacob 2024-04-01 15:09:14 -05:00
parent fec692b434
commit 900e841228
8 changed files with 1056 additions and 1292 deletions

View File

@ -145,6 +145,7 @@ target_precompile_headers(powerplay_exe PRIVATE src/common.h)
set(COMPILER_FLAGS " set(COMPILER_FLAGS "
-fno-strict-aliasing \ -fno-strict-aliasing \
-fno-finite-loops \ -fno-finite-loops \
-fwrapv \
-msse4.2 \ -msse4.2 \
") ")
@ -175,9 +176,10 @@ if (RTC)
message(FATAL_ERROR "CRTLIB (C runtime library) Must be enabled when compiling with RTC (runtime checks)") message(FATAL_ERROR "CRTLIB (C runtime library) Must be enabled when compiling with RTC (runtime checks)")
endif() endif()
# NOTE: Adress sanitizer is disabled for now because for some reason it's screwing up viewing local variables while debugging. # NOTE: Adress sanitizer is disabled for now because for some reason it's screwing up viewing local variables while debugging.
# set(COMPILER_FLAGS "${COMPILER_FLAGS} -DRTC=1") set(COMPILER_FLAGS "${COMPILER_FLAGS} -DRTC=1")
# set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=undefined -fno-sanitize=alignment -DRTC=1") set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=undefined -fsanitize-trap=undefined -DRTC=1")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize=alignment -DRTC=1") # set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=undefined -DRTC=1")
# set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=address -fsanitize=undefined -DRTC=1")
# set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -DRTC=1") # set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -DRTC=1")
endif() endif()

100
src/app.c
View File

@ -20,8 +20,24 @@
#include "util.h" #include "util.h"
#include "settings.h" #include "settings.h"
#include "draw.h" #include "draw.h"
#include "math.h"
#define WRITE_DIR "power_play" #define WRITE_DIR "power_play"
#define SETTINGS_FILENAME "settings.json"
#if RTC
# if DEVELOPER
# define WINDOW_TITLE "Debug (Developer Build)"
# else
# define WINDOW_TITLE "Debug"
# endif
#else
# if DEVELOPER
# define WINDOW_TITLE "Power Play (Developer Build)"
# else
# define WINDOW_TITLE "Power Play"
# endif
#endif
GLOBAL struct { GLOBAL struct {
struct arena arena; struct arena arena;
@ -63,6 +79,30 @@ struct string app_write_path_cat(struct arena *arena, struct string filename)
return string_cat(arena, L.write_path, filename); return string_cat(arena, L.write_path, filename);
} }
/* ========================== *
* Default settings
* ========================== */
INTERNAL struct sys_window_settings default_window_settings(struct sys_window *window)
{
__prof;
struct v2 monitor_size = sys_window_get_monitor_size(window);
i32 width = 1280;
i32 height = math_round(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT));
i32 x = math_round(monitor_size.x / 2.f - width / 2);
i32 y = math_round(monitor_size.y / 2.f - height / 2);
return (struct sys_window_settings) {
.title = WINDOW_TITLE,
.floating_x = x,
.floating_y = y,
.floating_width = width,
.floating_height = height
};
}
/* ========================== * /* ========================== *
* Entry point * Entry point
* ========================== */ * ========================== */
@ -91,9 +131,8 @@ void app_entry_point(void)
L.arena = arena_alloc(GIGABYTE(64)); L.arena = arena_alloc(GIGABYTE(64));
L.write_path = initialize_write_directory(&L.arena, STR(WRITE_DIR)); L.write_path = initialize_write_directory(&L.arena, STR(WRITE_DIR));
{
/* Startup base systems */ /* Startup base systems */
{
/* Startup logging */ /* Startup logging */
{ {
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
@ -111,11 +150,44 @@ void app_entry_point(void)
/* Create window */ /* Create window */
struct sys_window window = sys_window_alloc(); struct sys_window window = sys_window_alloc();
{
/* Read window settings from file */ /* Read window settings from file */
struct sys_window_settings window_settings = settings_default_window_settings(&window); {
settings_read_from_file(&window_settings); struct temp_arena scratch = scratch_begin_no_conflict();
struct sys_window_settings window_settings = default_window_settings(&window);
struct string settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
logf_info("Looking for settings file \"%F\"", FMT_STR(settings_path));
if (sys_is_file(settings_path)) {
logf_info("Settings file found");
struct sys_file settings_file = sys_file_open_read(settings_path);
struct buffer file_data = sys_file_read_all(scratch.arena, settings_file);
sys_file_close(settings_file);
logf_info("Deserializing settings file data: %F", FMT_STR(STRING_FROM_BUFFER(file_data)));
struct string error = { 0 };
struct sys_window_settings *res = settings_deserialize(scratch.arena, file_data, &error);
if (error.len > 0) {
logf_info("Failed to load settings file with error - %F", FMT_STR(error));
struct string msg = string_format(scratch.arena,
STR(
"Failed to loading settings file \"%F\":\n"
"------------\n"
"%F\n"
"------------\n"
"To stop this error from appearing, either Fix the issue above or delete the file from the system."
),
FMT_STR(settings_path),
FMT_STR(error));
sys_panic(msg);
} else {
logf_info("Settings file loaded successfully");
window_settings = *res;
}
}
string_copy_buff(BUFFER_FROM_ARRAY(window_settings.title), STR(WINDOW_TITLE));
sys_window_update_settings(&window, &window_settings); sys_window_update_settings(&window, &window_settings);
scratch_end(scratch);
} }
/* Startup systems */ /* Startup systems */
@ -153,8 +225,24 @@ void app_entry_point(void)
work_shutdown(); work_shutdown();
/* Write window settings to file */ /* Write window settings to file */
{
struct temp_arena scratch = scratch_begin_no_conflict();
struct string window_settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
struct sys_window_settings settings = sys_window_get_settings(&window); struct sys_window_settings settings = sys_window_get_settings(&window);
settings_write_to_file(&settings); struct buffer buff = settings_serialize(scratch.arena, &settings);
logf_info("Serialized window settings: %F", FMT_STR(STRING_FROM_BUFFER(buff)));
logf_info("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
struct sys_file settings_file = sys_file_open_write(window_settings_path);
sys_file_write(settings_file, buff);
sys_file_close(settings_file);
logf_info("Finished writing settings file");
scratch_end(scratch);
}
logf_info("Program exited normally"); logf_info("Program exited normally");
} }

View File

@ -9,8 +9,8 @@
#define arena_push_array(a, type, n) ((type *)_arena_push_bytes((a), (sizeof(type) * (n)), ALIGNOF(type))) #define arena_push_array(a, type, n) ((type *)_arena_push_bytes((a), (sizeof(type) * (n)), ALIGNOF(type)))
#define arena_push_array_zero(a, type, n) ((type *)_arena_push_bytes_zero((a), (sizeof(type) * (n)), ALIGNOF(type))) #define arena_push_array_zero(a, type, n) ((type *)_arena_push_bytes_zero((a), (sizeof(type) * (n)), ALIGNOF(type)))
#define arena_pop(a, type) ((type *)_arena_pop((a), sizeof(type))) #define arena_pop(a, type, dest) _arena_pop_struct((a), sizeof(type), dest)
#define arena_pop_array(a, type, n) ((type *)_arena_pop((a), sizeof(type) * (n))) #define arena_pop_array(a, type, n, dest) _arena_pop_struct((a), sizeof(type) * (n), dest)
/* Returns a pointer to where the next allocation would be (at alignment of type). /* Returns a pointer to where the next allocation would be (at alignment of type).
* Equivalent arena_push but without actually allocating anything. */ * Equivalent arena_push but without actually allocating anything. */
@ -40,18 +40,23 @@ INLINE void *_arena_push_bytes_zero(struct arena *arena, u64 size, u64 align)
return p; return p;
} }
INLINE void *_arena_pop_to(struct arena *arena, u64 pos) INLINE void _arena_pop_to(struct arena *arena, u64 pos)
{ {
ASSERT(arena->pos >= pos); ASSERT(arena->pos >= pos);
ASAN_POISON(arena->base + pos, arena->pos - pos); ASAN_POISON(arena->base + pos, arena->pos - pos);
arena->pos = pos; arena->pos = pos;
return (void *)(arena->base + arena->pos);
} }
INLINE void *_arena_pop(struct arena *arena, u64 size) INLINE void _arena_pop_struct(struct arena *arena, u64 size, void *copy_dest)
{ {
ASSERT(arena->pos >= size); ASSERT(arena->pos >= size);
return _arena_pop_to(arena, arena->pos - size);
u64 new_pos = arena->pos - size;
void *src = (void *)(arena->base + new_pos);
MEMCPY(copy_dest, src, size);
ASAN_POISON(arena->base + new_pos, arena->pos - new_pos);
arena->pos = new_pos;
} }
INLINE struct temp_arena arena_temp_begin(struct arena *arena) INLINE struct temp_arena arena_temp_begin(struct arena *arena)

View File

@ -86,7 +86,8 @@ INTERNAL void recalculate_world_xform_recurse(struct entity *parent)
u64 stack_count = 1; u64 stack_count = 1;
while (stack_count > 0) { while (stack_count > 0) {
/* Pull from top of stack */ /* Pull from top of stack */
struct stack_node node = *arena_pop(scratch.arena, struct stack_node); struct stack_node node;
arena_pop(scratch.arena, struct stack_node, &node);
--stack_count; --stack_count;
/* Calculate child world xform */ /* Calculate child world xform */

1799
src/json.c

File diff suppressed because it is too large Load Diff

View File

@ -2,142 +2,48 @@
#define JSON_H #define JSON_H
enum json_type { enum json_type {
JSON_TYPE_INVALID,
JSON_TYPE_STRING,
JSON_TYPE_NULL, JSON_TYPE_NULL,
JSON_TYPE_BOOL, JSON_TYPE_BOOL,
JSON_TYPE_NUMBER,
JSON_TYPE_STRING,
JSON_TYPE_ARRAY, JSON_TYPE_ARRAY,
JSON_TYPE_OBJECT, JSON_TYPE_OBJECT
JSON_TYPE_NUMBER
}; };
struct json_object_entry; struct json {
struct json_ir_parent_data {
u32 child_count;
struct json_ir *child_first;
struct json_ir *child_last;
};
/* Intermediate representation of JSON hierarchy tree in memory. Used for mutating
* JSON in parsing stage or for creating new objects. Should be manipulated via the
* API. */
struct json_ir {
enum json_type type; enum json_type type;
struct json_ir *next_child;
struct string key; struct string key;
struct json *parent;
struct json *next;
struct json *child_first;
struct json *child_last;
union { union {
struct json_ir_parent_data children;
b32 boolean;
struct string string; struct string string;
f64 number; f64 number;
} val;
};
/* Final representation of JSON hierarchy. Should be manipulated via the API. */
struct json_val {
enum json_type type;
u32 child_count;
union {
void *object_table;
struct json_val *array_children;
b32 boolean; b32 boolean;
struct string *string; } value;
f64 number;
} val;
}; };
struct json_object_entry { struct json_error {
struct string key; struct string msg;
struct json_val value; u64 start;
u64 end;
struct json_error *next;
}; };
/* Parse */ struct json_error_list {
const struct json_ir *json_parse(struct arena *arena, struct buffer bytes, struct string **error); u64 count;
struct json_error *first;
struct json_error *last;
};
/* Format */ struct json_parse_result {
const struct json_val *json_format(struct arena *arena, const struct json_ir *ir); struct json *root;
const struct json_val *json_parse_and_format(struct arena *arena, struct buffer bytes, struct string **error); struct json_error_list errors;
};
/* Index */ struct json_parse_result json_from_string(struct arena *arena, struct string src);
const struct json_val *json_array_get(const struct json_val *a, u32 index);
const struct json_val *json_object_get(const struct json_val *obj, struct string key);
const struct json_object_entry *json_object_get_index(const struct json_val *obj, u32 index);
/* Dump */
struct string json_dump_to_string(struct arena *arena, const struct json_val *val, u32 indent);
/* Write */
struct json_ir *json_ir_object(struct arena *arena);
struct json_ir *json_ir_number(struct arena *arena, f64 n);
struct json_ir *json_ir_bool(struct arena *arena, b32 b);
struct json_ir *json_ir_object_set(struct json_ir *obj, struct string key, struct json_ir *value);
/* ========================== *
* Type util
* ========================== */
INLINE b32 json_is_object(const struct json_val *v)
{
return v && v->type == JSON_TYPE_OBJECT;
}
INLINE b32 json_is_string(const struct json_val *v)
{
return v && v->type == JSON_TYPE_STRING;
}
INLINE b32 json_is_number(const struct json_val *v)
{
return v && v->type == JSON_TYPE_NUMBER;
}
INLINE b32 json_is_array(const struct json_val *v)
{
return v && v->type == JSON_TYPE_ARRAY;
}
INLINE b32 json_is_bool(const struct json_val *v)
{
return v && v->type == JSON_TYPE_BOOL;
}
INLINE b32 json_is_null(const struct json_val *v)
{
return v && v->type == JSON_TYPE_NULL;
}
/* ========================== *
* Val util
* ========================== */
INLINE struct string json_string(const struct json_val *v)
{
ASSERT(json_is_string(v));
return *v->val.string;
}
INLINE f64 json_number(const struct json_val *v)
{
ASSERT(json_is_number(v));
return v->val.number;
}
INLINE b32 json_bool(const struct json_val *v)
{
ASSERT(json_is_bool(v));
return v->val.boolean;
}
/* ========================== *
* Parent util
* ========================== */
INLINE u32 json_child_count(const struct json_val *v)
{
ASSERT(json_is_object(v) || json_is_array(v));
return v->child_count;
}
#endif #endif

View File

@ -1,158 +1,156 @@
#include "settings.h" #include "settings.h"
#include "sys.h"
#include "json.h" #include "json.h"
#include "scratch.h"
#include "string.h" #include "string.h"
#include "app.h" #include "arena.h"
#include "scratch.h"
#include "math.h" #include "math.h"
/* TODO: struct buffer settings_serialize(struct arena *arena, const struct sys_window_settings *settings)
* Rework the whole settings system to be not so rigid. {
* - Multi-threaded __prof;
* - Current settings state is readable & modifiable at any time
* - Can be done w/ a settings_open / settings_close block
* - Allow for dot notation in settings queries (should probably be implemented in the json layer).
* - "." denotes subindexing, IE: settings_get("window.width") (numbers can also be implemented for arrays).
* - "\." escapable
*/
#define SETTINGS_FILENAME "settings.json" struct string minimized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED ? STR("true") : STR("false");
struct string maximized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED ? STR("true") : STR("false");
struct string fullscreen = settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN ? STR("true") : STR("false");
i32 x = settings->floating_x;
i32 y = settings->floating_y;
i32 width = settings->floating_width;
i32 height = settings->floating_height;
INTERNAL struct buffer serialize_window_settings(struct arena *arena, const struct sys_window_settings *settings) struct string fmt = STR(
"{\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 BUFFER_FROM_STRING(formatted);
}
struct sys_window_settings *settings_deserialize(struct arena *arena, struct buffer src, struct string *error_out)
{ {
__prof; __prof;
struct temp_arena scratch = scratch_begin(arena); struct temp_arena scratch = scratch_begin(arena);
struct json_ir *root_obj = json_ir_object(scratch.arena);
struct json_ir *window_settings_obj = json_ir_object_set(root_obj, STR("window"), json_ir_object(scratch.arena));
json_ir_object_set(window_settings_obj, STR("minimized"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED));
json_ir_object_set(window_settings_obj, STR("maximized"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED));
json_ir_object_set(window_settings_obj, STR("fullscreen"), json_ir_bool(scratch.arena, settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN));
json_ir_object_set(window_settings_obj, STR("x"), json_ir_number(scratch.arena, settings->floating_x));
json_ir_object_set(window_settings_obj, STR("y"), json_ir_number(scratch.arena, settings->floating_y));
json_ir_object_set(window_settings_obj, STR("width"), json_ir_number(scratch.arena, settings->floating_width));
json_ir_object_set(window_settings_obj, STR("height"), json_ir_number(scratch.arena, settings->floating_height));
const struct json_val *formatted = json_format(scratch.arena, root_obj);
struct buffer buff = BUFFER_FROM_STRING(json_dump_to_string(arena, formatted, 2));
scratch_end(scratch);
return buff;
}
INTERNAL void deserialize_window_settings(struct buffer json_bytes, struct sys_window_settings *settings)
{
__prof;
struct temp_arena scratch = scratch_begin_no_conflict();
struct string error = { 0 }; struct string error = { 0 };
struct json_error json_error = { 0 };
if (json_bytes.size <= 0) { struct sys_window_settings *settings = arena_push_zero(arena, struct sys_window_settings);
goto end; struct json_parse_result parse_res = json_from_string(scratch.arena, STRING_FROM_BUFFER(src));
if (parse_res.errors.count > 0) {
json_error = *parse_res.errors.first;
goto abort;
} }
struct string *parse_error = NULL; struct json *root = parse_res.root;
const struct json_val *root_json = json_parse_and_format(scratch.arena, json_bytes, &parse_error); if (!root) {
if (parse_error) { error = STR("Root object not found.");
error = *parse_error; goto abort;
goto end;
} }
const struct json_val *window_settings_json = json_object_get(root_json, STR("window")); struct json *window = root->child_first;
if (!window_settings_json || !json_is_object(window_settings_json)) { if (!window || window->type != JSON_TYPE_OBJECT || !string_eq(window->key, STR("window"))) {
goto end; error = STR("\"window\" object not found");
goto abort;
} }
const struct json_val *maximized = json_object_get(window_settings_json, STR("maximized")); b32 found_maximized = false;
const struct json_val *fullscreen = json_object_get(window_settings_json, STR("fullscreen")); b32 found_fullscreen = false;
const struct json_val *width = json_object_get(window_settings_json, STR("width")); b32 found_x = false;
const struct json_val *height = json_object_get(window_settings_json, STR("height")); b32 found_y = false;
const struct json_val *x = json_object_get(window_settings_json, STR("x")); b32 found_width = false;
const struct json_val *y = json_object_get(window_settings_json, STR("y")); b32 found_height = false;
for (struct json *child = window->child_first; child; child = child->next) {
struct string key = child->key;
settings->floating_x = json_is_number(x) ? (i32)clamp_f64(json_number(x), I32_MIN, I32_MAX) : settings->floating_x; if (string_eq(key, STR("maximized"))) {
settings->floating_y = json_is_number(y) ? (i32)clamp_f64(json_number(y), I32_MIN, I32_MAX) : settings->floating_y; if (child->type != JSON_TYPE_BOOL) {
settings->floating_width = json_is_number(width) ? (i32)clamp_f64(json_number(width), I32_MIN, I32_MAX) : settings->floating_width; error = STR("Expected boolean for \"maximized\"");
settings->floating_height = json_is_number(height) ? (i32)clamp_f64(json_number(height), I32_MIN, I32_MAX) : settings->floating_height; goto abort;
settings->flags = json_is_bool(maximized) ? (json_bool(maximized) ? (settings->flags | SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED) : (settings->flags & ~SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED)) : settings->flags; }
settings->flags = json_is_bool(fullscreen) ? (json_bool(fullscreen) ? (settings->flags | SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN) : (settings->flags & ~SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN)) : settings->flags; if (child->value.boolean) {
settings->flags |= SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED;
}
found_maximized = true;
} else if (string_eq(key, STR("fullscreen"))) {
if (child->type != JSON_TYPE_BOOL) {
error = STR("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, STR("x"))) {
if (child->type != JSON_TYPE_NUMBER) {
error = STR("Expected number for \"x\"");
goto abort;
}
settings->floating_x = math_round(child->value.number);
found_x = true;
} else if (string_eq(key, STR("y"))) {
if (child->type != JSON_TYPE_NUMBER) {
error = STR("Expected number for \"y\"");
goto abort;
}
settings->floating_y = math_round(child->value.number);
found_y = true;
} else if (string_eq(key, STR("width"))) {
if (child->type != JSON_TYPE_NUMBER) {
error = STR("Expected number for \"width\"");
goto abort;
}
settings->floating_width = math_round(child->value.number);
found_width = true;
} else if (string_eq(key, STR("height"))) {
if (child->type != JSON_TYPE_NUMBER) {
error = STR("Expected number for \"height\"");
goto abort;
}
settings->floating_height = math_round(child->value.number);
found_height = true;
}
}
if (!found_maximized) { error = STR("Missing \"maximized\""); goto abort; }
if (!found_fullscreen) { error = STR("Missing \"fullscreen\""); goto abort; }
if (!found_x) { error = STR("Missing \"x\""); goto abort; }
if (!found_y) { error = STR("Missing \"y\""); goto abort; }
if (!found_width) { error = STR("Missing \"width\""); goto abort; }
if (!found_height) { error = STR("Missing \"height\""); goto abort; }
end: abort:
if (error.len > 0) { if (error_out && (error.len > 0 || json_error.msg.len > 0)) {
sys_message_box( if (json_error.msg.len > 0) {
SYS_MESSAGE_BOX_KIND_WARNING, *error_out = string_format(arena,
string_format( STR("%F\n(%F:%F)"),
scratch.arena, FMT_STR(json_error.msg),
STR("Error loading settings file:\n%F"), FMT_UINT(json_error.start),
FMT_STR(error) FMT_UINT(json_error.end));
) } else {
); *error_out = string_copy(arena, error);
} }
scratch_end(scratch);
}
struct sys_window_settings settings_default_window_settings(struct sys_window *window)
{
__prof;
struct v2 monitor_size = sys_window_get_monitor_size(window);
i32 width = 1280;
i32 height = math_round(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT));
i32 x = math_round(monitor_size.x / 2.f - width / 2);
i32 y = math_round(monitor_size.y / 2.f - height / 2);
return (struct sys_window_settings) {
#if RTC
# if DEVELOPER
.title = "Debug (Developer Build)",
# else
.title = "Debug",
# endif
#else
# if DEVELOPER
.title = "Power Play (Developer Build)",
# else
.title = "Power Play",
# endif
#endif
.floating_x = x,
.floating_y = y,
.floating_width = width,
.floating_height = height
};
}
void settings_read_from_file(struct sys_window_settings *default_settings)
{
__prof;
struct temp_arena scratch = scratch_begin_no_conflict();
/* Read window settings file if it exists */
struct string window_settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
if (sys_is_file(window_settings_path)) {
struct sys_file settings_file = sys_file_open_read(window_settings_path);
struct buffer file_data = sys_file_read_all(scratch.arena, settings_file);
sys_file_close(settings_file);
deserialize_window_settings(file_data, default_settings);
}
scratch_end(scratch);
}
void settings_write_to_file(const struct sys_window_settings *settings)
{
__prof;
struct temp_arena scratch = scratch_begin_no_conflict();
/* Write window settings to file */
struct buffer settings_file_data = serialize_window_settings(scratch.arena, settings);
if (settings_file_data.size > 0) {
struct string window_settings_path = app_write_path_cat(scratch.arena, STR(SETTINGS_FILENAME));
struct sys_file settings_file = sys_file_open_write(window_settings_path);
sys_file_write(settings_file, settings_file_data);
sys_file_close(settings_file);
} }
scratch_end(scratch); scratch_end(scratch);
return settings;
} }

View File

@ -1,10 +1,9 @@
#ifndef SETTINGS_H #ifndef SETTINGS_H
#define SETTINGS_H #define SETTINGS_H
struct sys_window; struct sys_window_settings;
struct sys_window_settings settings_default_window_settings(struct sys_window *window); struct buffer settings_serialize(struct arena *arena, const struct sys_window_settings *settings);
void settings_read_from_file(struct sys_window_settings *default_settings); struct sys_window_settings *settings_deserialize(struct arena *arena, struct buffer src, struct string *error_out);
void settings_write_to_file(const struct sys_window_settings *settings);
#endif #endif