diff --git a/VERSION b/VERSION index ee90284..9084fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.4 +1.1.0 diff --git a/src/log/log.c b/src/log/log.c new file mode 100644 index 0000000..6573df1 --- /dev/null +++ b/src/log/log.c @@ -0,0 +1,99 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#include "log.h" +#include "../common/aliases/aliases.h" +#include "../common/assert/assert.h" +#include "../os/file/file.h" + +#define LOG_LEVEL_STR_LENGTH 8 +#define LOG_PREFIX_BUF_LENGTH 16 + +typedef struct { + WFile *outlog; + WFile *errlog; + LogLevel level; +} LogConfig; + +wapp_intern LogConfig LOG_CONFIG = { + .level = WAPP_LOG_DEBUG, +}; +wapp_intern Str8RO LOG_LEVEL_STRINGS[COUNT_LOG_LEVEL] = { + [WAPP_LOG_FATAL] = wapp_str8_lit_ro_initialiser_list("[ FATAL ] "), + [WAPP_LOG_CRITICAL] = wapp_str8_lit_ro_initialiser_list("[ CRITICAL ] "), + [WAPP_LOG_ERROR] = wapp_str8_lit_ro_initialiser_list("[ ERROR ] "), + [WAPP_LOG_WARNING] = wapp_str8_lit_ro_initialiser_list("[ WARNING ] "), + [WAPP_LOG_INFO] = wapp_str8_lit_ro_initialiser_list("[ INFO ] "), + [WAPP_LOG_DEBUG] = wapp_str8_lit_ro_initialiser_list("[ DEBUG ] "), +}; + +wapp_intern void _write_log_line(WFile *fp, const Logger *logger, Str8 msg, LogLevel level); + +void wapp_log_set_level(LogLevel level) { + LOG_CONFIG.level = level; +} + +void wapp_log_configure(WFile *outlog, WFile *errlog, LogLevel level) { + LOG_CONFIG.outlog = outlog; + LOG_CONFIG.errlog = errlog; + LOG_CONFIG.level = level; +} + +Logger wapp_log_make_logger(Str8 name) { + return (Logger){ .name = name }; +} + +void wapp_log_debug(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_DEBUG) { return; } + + WFile *fp = LOG_CONFIG.outlog != NULL ? LOG_CONFIG.outlog : wapp_file_stdout(); + _write_log_line(fp, logger, msg, WAPP_LOG_DEBUG); +} + +void wapp_log_info(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_INFO) { return; } + + WFile *fp = LOG_CONFIG.outlog != NULL ? LOG_CONFIG.outlog : wapp_file_stdout(); + _write_log_line(fp, logger, msg, WAPP_LOG_INFO); +} + +void wapp_log_warning(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_WARNING) { return; } + + WFile *fp = LOG_CONFIG.outlog != NULL ? LOG_CONFIG.outlog : wapp_file_stdout(); + _write_log_line(fp, logger, msg, WAPP_LOG_WARNING); +} + +void wapp_log_error(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_ERROR) { return; } + + WFile *fp = LOG_CONFIG.errlog != NULL ? LOG_CONFIG.errlog : wapp_file_stderr(); + _write_log_line(fp, logger, msg, WAPP_LOG_ERROR); +} + +void wapp_log_critical(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_CRITICAL) { return; } + + WFile *fp = LOG_CONFIG.errlog != NULL ? LOG_CONFIG.errlog : wapp_file_stderr(); + _write_log_line(fp, logger, msg, WAPP_LOG_CRITICAL); +} + +void wapp_log_fatal(const Logger *logger, Str8 msg) { + wapp_debug_assert(logger != NULL, "`logger` should not be NULL"); + if (LOG_CONFIG.level < WAPP_LOG_FATAL) { return; } + + WFile *fp = LOG_CONFIG.errlog != NULL ? LOG_CONFIG.errlog : wapp_file_stderr(); + _write_log_line(fp, logger, msg, WAPP_LOG_FATAL); +} + +wapp_intern void _write_log_line(WFile *fp, const Logger *logger, Str8 msg, LogLevel level) { + wapp_file_write((void *)LOG_LEVEL_STRINGS[level].buf, fp, LOG_LEVEL_STRINGS[level].size); + wapp_file_write((void *)logger->name.buf, fp, logger->name.size); + wapp_file_write((void *)": ", fp, 2); + wapp_file_write((void *)msg.buf, fp, msg.size); + wapp_file_write((void *)"\n", fp, 1); +} diff --git a/src/log/log.h b/src/log/log.h new file mode 100644 index 0000000..f6605d1 --- /dev/null +++ b/src/log/log.h @@ -0,0 +1,34 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef LOG_H +#define LOG_H + +#include "../os/file/file.h" +#include "../base/strings/str8/str8.h" + +typedef enum { + WAPP_LOG_FATAL, + WAPP_LOG_CRITICAL, + WAPP_LOG_ERROR, + WAPP_LOG_WARNING, + WAPP_LOG_INFO, + WAPP_LOG_DEBUG, + + COUNT_LOG_LEVEL, +} LogLevel; + +typedef struct { + Str8 name; +} Logger; + +void wapp_log_set_level(LogLevel level); +void wapp_log_configure(WFile *outlog, WFile *errlog, LogLevel level); +Logger wapp_log_make_logger(Str8 name); +void wapp_log_debug(const Logger *logger, Str8 msg); +void wapp_log_info(const Logger *logger, Str8 msg); +void wapp_log_warning(const Logger *logger, Str8 msg); +void wapp_log_error(const Logger *logger, Str8 msg); +void wapp_log_critical(const Logger *logger, Str8 msg); +void wapp_log_fatal(const Logger *logger, Str8 msg); + +#endif // !LOG_H diff --git a/src/log/wapp_log.c b/src/log/wapp_log.c new file mode 100644 index 0000000..64376ed --- /dev/null +++ b/src/log/wapp_log.c @@ -0,0 +1,10 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef WAPP_LOG_C +#define WAPP_LOG_C + +#include "log.c" +#include "../base/wapp_base.c" +#include "../os/wapp_os.c" + +#endif // !WAPP_LOG_C diff --git a/src/log/wapp_log.h b/src/log/wapp_log.h new file mode 100644 index 0000000..a8dcdcd --- /dev/null +++ b/src/log/wapp_log.h @@ -0,0 +1,11 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef WAPP_LOG_H +#define WAPP_LOG_H + +#include "log.h" +#include "../common/wapp_common.h" +#include "../base/wapp_base.h" +#include "../os/wapp_os.h" + +#endif // !WAPP_LOG_H diff --git a/src/os/file/file.h b/src/os/file/file.h index 0aa707f..48ee7e3 100644 --- a/src/os/file/file.h +++ b/src/os/file/file.h @@ -34,9 +34,18 @@ typedef enum { FILE_SEEK_ORIGIN_COUNT, } FileSeekOrigin; +// Return value should not be cached as it's not guaranteed to remain the same. Always call +// wapp_file_stdin to get the standard input stream wapp_extern WFile *wapp_file_stdin(void); + +// Return value should not be cached as it's not guaranteed to remain the same. Always call +// wapp_file_stdout to get the standard output stream wapp_extern WFile *wapp_file_stdout(void); + +// Return value should not be cached as it's not guaranteed to remain the same. Always call +// wapp_file_stderr to get the standard error stream wapp_extern WFile *wapp_file_stderr(void); + WFile *wapp_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode); i64 wapp_file_get_current_position(WFile *file); i64 wapp_file_seek(WFile *file, i64 offset, FileSeekOrigin origin); diff --git a/src/os/shell/termcolour/termcolour.h b/src/os/shell/termcolour/termcolour.h index e89bbcb..24076b1 100644 --- a/src/os/shell/termcolour/termcolour.h +++ b/src/os/shell/termcolour/termcolour.h @@ -12,6 +12,8 @@ BEGIN_C_LINKAGE #endif // !WAPP_PLATFORM_CPP +// TODO (Abdelrahman): Look into moving away from stdio in the implementation + void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour); void wapp_shell_termcolour_clear_colour(void); diff --git a/src/wapp.c b/src/wapp.c index 44ac8a9..9dc22ab 100644 --- a/src/wapp.c +++ b/src/wapp.c @@ -6,8 +6,9 @@ #include "wapp.h" #include "base/wapp_base.c" #include "os/wapp_os.c" +#include "log/wapp_log.c" #include "prng/wapp_prng.c" -#include "uuid/uuid.c" +#include "uuid/wapp_uuid.c" #include "testing/wapp_testing.c" #endif // !WAPP_C diff --git a/src/wapp.h b/src/wapp.h index 32f7ed0..14957fe 100644 --- a/src/wapp.h +++ b/src/wapp.h @@ -6,6 +6,7 @@ #include "common/wapp_common.h" #include "base/wapp_base.h" #include "os/wapp_os.h" +#include "log/wapp_log.h" #include "prng/wapp_prng.h" #include "uuid/wapp_uuid.h" #include "testing/wapp_testing.h"