mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-11 03:08:41 +00:00
238 lines
6.2 KiB
C
238 lines
6.2 KiB
C
/**
|
|
* Jingga
|
|
*
|
|
* @copyright Jingga
|
|
* @license OMS License 2.0
|
|
* @version 1.0.0
|
|
* @link https://jingga.app
|
|
*/
|
|
#ifndef TOS_LOG_H
|
|
#define TOS_LOG_H
|
|
|
|
#include "../stdlib/Types.h"
|
|
#include "../compiler/CompilerUtils.h"
|
|
#include "../utils/StringUtils.h"
|
|
#include "../platform/win32/TimeUtils.h"
|
|
|
|
#define LOG_DATA_ARRAY 5
|
|
|
|
#ifndef LOG_LEVEL
|
|
#define LOG_LEVEL 0
|
|
#endif
|
|
|
|
#ifndef MAX_LOG_LENGTH
|
|
#define MAX_LOG_LENGTH 256
|
|
#endif
|
|
|
|
#ifndef MAX_LOG_MESSAGES
|
|
#define MAX_LOG_MESSAGES 256
|
|
#endif
|
|
|
|
#if _WIN32
|
|
static HANDLE _log_fp;
|
|
#elif __linux__
|
|
static int32 _log_fp;
|
|
#endif
|
|
|
|
struct LogMemory {
|
|
byte* memory;
|
|
|
|
uint64 size;
|
|
uint64 pos;
|
|
};
|
|
static LogMemory* _log_memory = NULL;
|
|
|
|
enum LogDataType {
|
|
LOG_DATA_NONE,
|
|
LOG_DATA_VOID,
|
|
LOG_DATA_BYTE,
|
|
LOG_DATA_INT32,
|
|
LOG_DATA_UINT32,
|
|
LOG_DATA_INT64,
|
|
LOG_DATA_UINT64,
|
|
LOG_DATA_CHAR,
|
|
LOG_DATA_CHAR_STR,
|
|
LOG_DATA_FLOAT32,
|
|
LOG_DATA_FLOAT64
|
|
};
|
|
|
|
struct LogMessage {
|
|
const char* file;
|
|
const char* function;
|
|
int32 line;
|
|
uint64 time;
|
|
char* message;
|
|
};
|
|
|
|
struct LogData {
|
|
LogDataType type;
|
|
void* value;
|
|
};
|
|
|
|
struct LogDataArray{
|
|
LogData data[LOG_DATA_ARRAY];
|
|
};
|
|
|
|
// @bug This probably requires thread safety
|
|
byte* log_get_memory()
|
|
{
|
|
if (_log_memory->pos + MAX_LOG_LENGTH > _log_memory->size) {
|
|
_log_memory->pos = 0;
|
|
}
|
|
|
|
byte* offset = (byte *) (_log_memory->memory + _log_memory->pos);
|
|
memset((void *) offset, 0, MAX_LOG_LENGTH);
|
|
|
|
_log_memory->pos += MAX_LOG_LENGTH;
|
|
|
|
return offset;
|
|
}
|
|
|
|
void log_to_file()
|
|
{
|
|
// we don't log an empty log pool
|
|
if (!_log_memory || _log_memory->pos == 0 || !_log_fp) {
|
|
return;
|
|
}
|
|
|
|
#if _WIN32
|
|
DWORD written;
|
|
WriteFile(
|
|
_log_fp,
|
|
(char *) _log_memory->memory,
|
|
(uint32) _log_memory->pos,
|
|
&written,
|
|
NULL
|
|
);
|
|
#else
|
|
if (_log_fp < 0) {
|
|
return;
|
|
}
|
|
|
|
write(
|
|
_log_fp,
|
|
(char *) _log_memory->memory,
|
|
(uint32) _log_memory->pos
|
|
);
|
|
#endif
|
|
}
|
|
|
|
void log(const char* str, bool should_log, const char* file, const char* function, int32 line)
|
|
{
|
|
if (!should_log || !_log_memory) {
|
|
return;
|
|
}
|
|
|
|
int64 len = str_length(str);
|
|
while (len > 0) {
|
|
LogMessage* msg = (LogMessage *) log_get_memory();
|
|
|
|
// Fill file
|
|
msg->file = file;
|
|
msg->function = function;
|
|
msg->line = line;
|
|
msg->message = (char *) (msg + 1);
|
|
msg->time = system_time();
|
|
|
|
int32 message_length = (int32) OMS_MIN(MAX_LOG_LENGTH - sizeof(LogMessage) - 1, len);
|
|
|
|
memcpy(msg->message, str, message_length);
|
|
msg->message[message_length] = '\0';
|
|
str += message_length;
|
|
len -= MAX_LOG_LENGTH - sizeof(LogMessage);
|
|
|
|
if (_log_memory->size - _log_memory->pos < MAX_LOG_LENGTH) {
|
|
log_to_file();
|
|
_log_memory->pos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void log(const char* format, LogDataArray data, bool should_log, const char* file, const char* function, int32 line)
|
|
{
|
|
ASSERT_SIMPLE(str_length(format) + str_length(file) + str_length(function) + 50 < MAX_LOG_LENGTH);
|
|
|
|
if (!should_log || !_log_memory) {
|
|
return;
|
|
}
|
|
|
|
if (data.data[0].type == LOG_DATA_VOID) {
|
|
log(format, should_log, file, function, line);
|
|
return;
|
|
}
|
|
|
|
LogMessage* msg = (LogMessage *) log_get_memory();
|
|
msg->file = file;
|
|
msg->function = function;
|
|
msg->line = line;
|
|
msg->message = (char *) (msg + 1);
|
|
msg->time = system_time();
|
|
|
|
char temp_format[MAX_LOG_LENGTH];
|
|
str_copy_short(msg->message, format);
|
|
|
|
for (int32 i = 0; i < LOG_DATA_ARRAY; ++i) {
|
|
if (data.data[i].type == LOG_DATA_VOID) {
|
|
break;
|
|
}
|
|
|
|
str_copy_short(temp_format, msg->message);
|
|
|
|
switch (data.data[i].type) {
|
|
case LOG_DATA_NONE: {
|
|
} break;
|
|
case LOG_DATA_BYTE: {
|
|
sprintf_fast_iter(msg->message, temp_format, (int32) *((byte *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_INT32: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((int32 *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_UINT32: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((uint32 *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_INT64: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((int64 *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_UINT64: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((uint64 *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_CHAR: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((char *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_CHAR_STR: {
|
|
sprintf_fast_iter(msg->message, temp_format, (const char *) data.data[i].value);
|
|
} break;
|
|
case LOG_DATA_FLOAT32: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((f32 *) data.data[i].value));
|
|
} break;
|
|
case LOG_DATA_FLOAT64: {
|
|
sprintf_fast_iter(msg->message, temp_format, *((f64 *) data.data[i].value));
|
|
} break;
|
|
default: {
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_log_memory->size - _log_memory->pos < MAX_LOG_LENGTH) {
|
|
log_to_file();
|
|
_log_memory->pos = 0;
|
|
}
|
|
}
|
|
|
|
#define LOG(should_log, str) log((str), (should_log), __FILE__, __func__, __LINE__)
|
|
#define LOG_FORMAT(should_log, format, ...) log((format), LogDataArray{__VA_ARGS__}, (should_log), __FILE__, __func__, __LINE__)
|
|
#define LOG_TO_FILE() log_to_file()
|
|
|
|
#if LOG_LEVEL == 2
|
|
#define LOG_LEVEL_1(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
|
|
#define LOG_LEVEL_2(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
|
|
#elif LOG_LEVEL == 1
|
|
#define LOG_LEVEL_1(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
|
|
#define LOG_LEVEL_2(format, ...) ((void) 0)
|
|
#elif LOG_LEVEL == 0
|
|
#define LOG_LEVEL_1(format, ...) ((void) 0)
|
|
#define LOG_LEVEL_2(format, ...) ((void) 0)
|
|
#endif
|
|
|
|
#endif |