colla/os.c
alessandro bason a66e58193f .
2025-06-24 17:47:08 +02:00

235 lines
6.2 KiB
C

#include "os.h"
#if COLLA_WIN
#include "win/os_win32.c"
#else
#error "platform not supported yet"
#endif
// == HANDLE ====================================
oshandle_t os_handle_zero(void) {
return (oshandle_t){0};
}
bool os_handle_match(oshandle_t a, oshandle_t b) {
return a.data == b.data;
}
bool os_handle_valid(oshandle_t handle) {
return !os_handle_match(handle, os_handle_zero());
}
// == LOGGING ===================================
os_log_colour_e log__level_to_colour(os_log_level_e level) {
os_log_colour_e colour = LOG_COL_RESET;
switch (level) {
case LOG_DEBUG: colour = LOG_COL_BLUE; break;
case LOG_INFO: colour = LOG_COL_GREEN; break;
case LOG_WARN: colour = LOG_COL_YELLOW; break;
case LOG_ERR: colour = LOG_COL_MAGENTA; break;
case LOG_FATAL: colour = LOG_COL_RED; break;
default: break;
}
return colour;
}
void os_log_print(os_log_level_e level, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
os_log_printv(level, fmt, args);
va_end(args);
}
void os_log_printv(os_log_level_e level, const char *fmt, va_list args) {
const char *level_str = "";
switch (level) {
case LOG_DEBUG: level_str = "DEBUG"; break;
case LOG_INFO: level_str = "INFO"; break;
case LOG_WARN: level_str = "WARN"; break;
case LOG_ERR: level_str = "ERR"; break;
case LOG_FATAL: level_str = "FATAL"; break;
default: break;
}
os_log_set_colour(log__level_to_colour(level));
if (level != LOG_BASIC) {
fmt_print("[%s]: ", level_str);
}
os_log_set_colour(LOG_COL_RESET);
fmt_printv(fmt, args);
fmt_print("\n");
if (level == LOG_FATAL) {
os_abort(1);
}
}
// == FILE ======================================
void os_file_split_path(strview_t path, strview_t *dir, strview_t *name, strview_t *ext) {
usize dir_lin = strv_rfind(path, '/', 0);
usize dir_win = strv_rfind(path, '\\', 0);
dir_lin = dir_lin != STR_NONE ? dir_lin : 0;
dir_win = dir_win != STR_NONE ? dir_win : 0;
usize dir_pos = MAX(dir_lin, dir_win);
usize ext_pos = strv_rfind(path, '.', 0);
if (dir) {
*dir = strv_sub(path, 0, dir_pos);
}
if (name) {
*name = strv_sub(path, dir_pos ? dir_pos + 1 : 0, ext_pos);
}
if (ext) {
*ext = strv_sub(path, ext_pos, SIZE_MAX);
}
}
bool os_file_putc(oshandle_t handle, char c) {
return os_file_write(handle, &c, sizeof(c)) == sizeof(c);
}
bool os_file_puts(oshandle_t handle, strview_t str) {
return os_file_write(handle, str.buf, str.len) == str.len;
}
bool os_file_print(arena_t scratch, oshandle_t handle, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
bool result = os_file_printv(scratch, handle, fmt, args);
va_end(args);
return result;
}
bool os_file_printv(arena_t scratch, oshandle_t handle, const char *fmt, va_list args) {
str_t s = str_fmtv(&scratch, fmt, args);
return os_file_puts(handle, strv(s));
}
usize os_file_read_buf(oshandle_t handle, buffer_t *buf) {
return os_file_read(handle, buf->data, buf->len);
}
usize os_file_write_buf(oshandle_t handle, buffer_t buf) {
return os_file_write(handle, buf.data, buf.len);
}
buffer_t os_file_read_all(arena_t *arena, strview_t path) {
oshandle_t fp = os_file_open(path, FILEMODE_READ);
if (!os_handle_valid(fp)) {
err("could not open file: %v", path);
return (buffer_t){0};
}
buffer_t out = os_file_read_all_fp(arena, fp);
os_file_close(fp);
return out;
}
buffer_t os_file_read_all_fp(arena_t *arena, oshandle_t handle) {
if (!os_handle_valid(handle)) return (buffer_t){0};
buffer_t out = {0};
out.len = os_file_size(handle);
out.data = alloc(arena, u8, out.len);
usize read = os_file_read_buf(handle, &out);
if (read != out.len) {
err("os_file_read_all_fp: read failed, should be %zu but is %zu", out.len, read);
arena_pop(arena, out.len);
return (buffer_t){0};
}
return out;
}
str_t os_file_read_all_str(arena_t *arena, strview_t path) {
oshandle_t fp = os_file_open(path, FILEMODE_READ);
if (!os_handle_valid(fp)) {
err("could not open file %v: %v", path, os_get_error_string(os_get_last_error()));
return STR_EMPTY;
}
str_t out = os_file_read_all_str_fp(arena, fp);
os_file_close(fp);
return out;
}
str_t os_file_read_all_str_fp(arena_t *arena, oshandle_t handle) {
if (!os_handle_valid(handle)) {
return STR_EMPTY;
}
str_t out = STR_EMPTY;
out.len = os_file_size(handle);
out.buf = alloc(arena, u8, out.len + 1);
usize read = os_file_read(handle, out.buf, out.len);
if (read != out.len) {
err("os_file_read_all_str_fp: read failed, should be %zu but is %zu", out.len, read);
arena_pop(arena, out.len + 1);
return STR_EMPTY;
}
return out;
}
bool os_file_write_all(strview_t name, buffer_t buffer) {
oshandle_t fp = os_file_open(name, FILEMODE_WRITE);
bool result = os_file_write_all_fp(fp, buffer);
os_file_close(fp);
return result;
}
bool os_file_write_all_fp(oshandle_t handle, buffer_t buffer) {
return os_file_write(handle, buffer.data, buffer.len) == buffer.len;
}
bool os_file_write_all_str(strview_t name, strview_t data) {
oshandle_t fp = os_file_open(name, FILEMODE_WRITE);
bool result = os_file_write_all_str_fp(fp, data);
os_file_close(fp);
return result;
}
bool os_file_write_all_str_fp(oshandle_t handle, strview_t data) {
return os_file_write(handle, data.buf, data.len) == data.len;
}
u64 os_file_time(strview_t path) {
oshandle_t fp = os_file_open(path, FILEMODE_READ);
u64 result = os_file_time_fp(fp);
os_file_close(fp);
return result;
}
bool os_file_has_changed(strview_t path, u64 last_change) {
u64 timestamp = os_file_time(path);
return timestamp > last_change;
}
// == PROCESS ===================================
bool os_run_cmd(arena_t scratch, os_cmd_t *cmd, os_env_t *optional_env) {
oshandle_t proc = os_run_cmd_async(scratch, cmd, optional_env);
return os_handle_valid(proc) ? os_process_wait(proc, OS_WAIT_INFINITE, NULL) : false;
}
// == VMEM ======================================
usize os_pad_to_page(usize byte_count) {
usize page_size = os_get_system_info().page_size;
if (byte_count == 0) {
return page_size;
}
usize padding = page_size - (byte_count & (page_size - 1));
if (padding == page_size) {
padding = 0;
}
return byte_count + padding;
}