#include "libhectic.h" void set_output_color_mode(ColorMode mode) { color_mode = mode; } // ------------ // -- Logger -- // ------------ const char* log_level_to_string(LogLevel level) { switch (level) { case LOG_LEVEL_DEBUG: return "DEBUG"; case LOG_LEVEL_LOG: return "LOG"; case LOG_LEVEL_INFO: return "INFO"; case LOG_LEVEL_NOTICE: return "NOTICE"; case LOG_LEVEL_WARN: return "WARN"; case LOG_LEVEL_EXCEPTION: return "EXCEPTION"; default: return "UNKNOWN"; } } LogLevel log_level_from_string(const char *level_str) { if (!level_str) return LOG_LEVEL_INFO; if (strcmp(level_str, "DEBUG") == 0) return LOG_LEVEL_DEBUG; else if (strcmp(level_str, "LOG") == 0) return LOG_LEVEL_LOG; else if (strcmp(level_str, "INFO") == 0) return LOG_LEVEL_INFO; else if (strcmp(level_str, "NOTICE") == 0) return LOG_LEVEL_NOTICE; else if (strcmp(level_str, "WARN") == 0) return LOG_LEVEL_WARN; else if (strcmp(level_str, "EXCEPTION") == 0) return LOG_LEVEL_EXCEPTION; else return LOG_LEVEL_INFO; } LogLevel current_log_level = LOG_LEVEL_INFO; void logger_level_reset() { current_log_level = LOG_LEVEL_INFO; } void logger_level(LogLevel level) { current_log_level = level; } void init_logger(void) { current_log_level = log_level_from_string(getenv("LOG_LEVEL")); } char* log_message(LogLevel level, int line, const char *format, ...) { if (level < current_log_level) { return NULL; } time_t now = time(NULL); struct tm tm_info; localtime_r(&now, &tm_info); static char timeStr[20]; strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_info); fprintf(stderr, "%s %d %s: ", timeStr, line, log_level_to_string(level)); va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); return timeStr; } // ----------- // -- arena -- // ----------- Arena arena_init(size_t size) { Arena arena; arena.begin = malloc(size); memset(arena.begin, 0, size); arena.current = arena.begin; arena.capacity = size; return arena; } void *arena_alloc_or_null(Arena *arena, size_t size) { if (arena->begin == 0) { *arena = arena_init(ARENA_DEFAULT_SIZE); } size_t current = (size_t)arena->current - (size_t)arena->begin; // TODO(yukkop): maybe -1 if (arena->capacity <= current && current < size) { return NULL; } return arena; } void arena_reset(Arena *arena) { arena->current = arena->begin; } void arena_free(Arena *arena) { free(arena->begin); } void *arena_alloc(Arena *arena, size_t size) { void *mem = arena_alloc_or_null(arena, size); if (!mem) { raise_exception("Arena out of memory"); exit(1); } return mem; }