From e24186fc1917c5e8b91924af0c3c7c55816ff5d6 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 25 Jan 2021 22:01:00 +0100 Subject: Introducing MIC --- src/platform_posix.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/platform_posix.c (limited to 'src/platform_posix.c') diff --git a/src/platform_posix.c b/src/platform_posix.c new file mode 100644 index 0000000..7c2fb6c --- /dev/null +++ b/src/platform_posix.c @@ -0,0 +1,171 @@ +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include + +#include "app.h" + +// +// PlatformAPI Implementation. +// + +size_t +platform_read_file(const char *path, char *memory) { + size_t file_size = 0; + FILE *fp = fopen(path, "rb"); + if (!fp) { + return 0; + } + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + rewind(fp); + fread(memory, 1, file_size, fp); + fclose(fp); + memory[file_size] = '\0'; + return file_size; +} + +void +platform_log(const char *format, ...) { + // Print date. + time_t raw_time = time(NULL); + struct tm *tm = localtime(&raw_time); + char date[64]; + strftime(date, sizeof(date), "%Y-%M-%d | %H:%M:%S", tm); + printf("%s | ", date); + + // Print message. + va_list args; + va_start(args, format); + vprintf(format, args); + + printf("\n"); + va_end(args); +} + +void +platform_sleep(size_t microseconds) { + usleep(microseconds); +} + +#if defined(LIB_NAME) && defined(LIB_DIR) + +// +// Dynamic linking with hot code reload. +// + +#include +#include +#include + +static ino_t lib_id; +static void * lib_handle; + +static const char *lib_path = LIB_DIR "/" LIB_NAME; + +static bool +load_lib(AppAPI *api) { + struct stat st; + if (stat(lib_path, &st) != 0) { + return false; + } + + if (lib_id != st.st_ino) { + void *handle = dlopen(lib_path, RTLD_NOW); + if (!handle) { + lib_handle = NULL; + lib_id = 0; + return false; + } + lib_handle = handle; + lib_id = st.st_ino; + + const AppAPI *app_api = dlsym(lib_handle, "APP_API"); + if (app_api == NULL) { + dlclose(lib_handle); + lib_handle = NULL; + lib_id = 0; + return false; + } + *api = *app_api; + } + + return true; +} + +static bool +_app_reload(AppAPI *api, AppState *state, PlatformAPI platform) { + struct stat st; + if (stat(lib_path, &st) == 0 && lib_id != st.st_ino) { + if (lib_handle) { + api->unload(state, platform); + dlclose(lib_handle); + } + + if (!load_lib(api)) { + return false; + } + api->reload(state, platform); + } + + return true; +} + +static bool +_app_init(AppAPI *api, AppState *state, PlatformAPI platform) { + if (!load_lib(api)) { + fprintf(stderr, "error: can't open app library file: %s\n", lib_path); + return false; + } + api->init(state, platform); + return true; +} + +static void +_app_destroy(AppAPI *api, AppState *state, PlatformAPI platform) { + api->destroy(state, platform); + if (lib_handle) { + dlclose(lib_handle); + lib_handle = NULL; + lib_id = 0; + } +} + +#else + +// +// Static linking of app code. +// + +extern const AppAPI APP_API; + +static bool +_app_reload() { + return true; +} + +static bool +_app_init(AppAPI *api, AppState *state, PlatformAPI platform) { + *api = APP_API; + api->init(state, platform); + return true; +} + +static void +_app_destroy(AppAPI *api, AppState *state, PlatformAPI platform) { + api->destroy(state, platform); +} + +#endif + +const PlatformAPI PLATFORM_API = { + .read_file = platform_read_file, + .malloc = malloc, + .free = free, + .calloc = calloc, + .realloc = realloc, + .log = platform_log, + .sleep = platform_sleep, +}; -- cgit v1.2.1