@@ -26,6 +26,7 @@ typedef enum { | |||
} IZ_AppInitializeResult; | |||
IZ_AppInitializeResult IZ_AppInitialize(struct IZ_App* app, u8 argc, const char* argv[]) { | |||
IZ_LogInitialize("game"); | |||
IZ_LogInterceptWSMessages(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE); | |||
IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "global", "Starting %s...", IZ_APP_NAME); | |||
@@ -76,6 +77,7 @@ void IZ_AppTeardown(struct IZ_App* app) { | |||
IZ_InputTeardown(&app->input_state); | |||
IZ_VideoTeardown(&app->video_state); | |||
IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "global", "Stopping %s...", IZ_APP_NAME); | |||
IZ_LogTeardown(); | |||
SDL_Quit(); | |||
} | |||
@@ -24,3 +24,36 @@ errno_t IZ_fopen(FILE** file, const char* filename, const char* mode) { | |||
return *file == NULL ? 1 : 0; | |||
#endif | |||
} | |||
errno_t IZ_mkdir(const char* path) { | |||
#if defined IZ_WINDOWS | |||
if (!CreateDirectory(path, NULL)) { | |||
return GetLastError(); | |||
} | |||
return 0; | |||
#else | |||
mkdir(path, 0777); | |||
return 0; | |||
#endif | |||
} | |||
bool IZ_isdir(const char* path) { | |||
#if defined IZ_WINDOWS | |||
DWORD dwAttrib = GetFileAttributes(path); | |||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && | |||
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); | |||
#else | |||
struct stat s; | |||
int err = stat("/path/to/possible_dir", &s); | |||
if(-1 == err) { | |||
if(ENOENT == errno) { | |||
return false; | |||
} | |||
perror("stat"); | |||
exit(1);\ | |||
return; | |||
} | |||
return (S_ISDIR(s.st_mode)) | |||
#endif | |||
} |
@@ -2,6 +2,7 @@ | |||
#define IZ_IO_H | |||
#include <stdio.h> | |||
#include <stdbool.h> | |||
#include <stdarg.h> | |||
#include "../compat/IZ_windows.h" | |||
@@ -9,4 +10,8 @@ int IZ_sprintf(char*, size_t, const char*, ...); | |||
errno_t IZ_fopen(FILE**, const char*, const char*); | |||
errno_t IZ_mkdir(const char*); | |||
bool IZ_isdir(const char*); | |||
#endif |
@@ -32,11 +32,38 @@ bool IZ_LogIsSupportedTerminal() { | |||
#endif | |||
} | |||
bool IZ_LogIsSupportedColor() { | |||
bool IZ_LogIsSupportedColor(FILE* s) { | |||
#ifdef IZ_WINDOWS | |||
return _isatty(_fileno(stdout)) && IZ_LogIsSupportedTerminal(); | |||
return _isatty(_fileno(s)) && IZ_LogIsSupportedTerminal(); | |||
#else | |||
return isatty(fileno(stdout)) && IZ_LogIsSupportedTerminal(); | |||
return isatty(fileno(s)) && IZ_LogIsSupportedTerminal(); | |||
#endif | |||
} | |||
void IZ_LogInitialize(const char* context) { | |||
#ifdef IZ_DEBUG | |||
stdout_dest = stdout; | |||
stderr_dest = stderr; | |||
#else | |||
const char* log_dir = "logs"; | |||
if (!IZ_isdir(log_dir)) { | |||
IZ_mkdir(log_dir); | |||
} | |||
char stdout_filename[128] = ""; | |||
char stderr_filename[128] = ""; | |||
char* now = IZ_TimerNowPathSafe(); | |||
// fixme | |||
sprintf(stdout_filename, "%s/out-%s-%s.log", log_dir, context, now); | |||
sprintf(stderr_filename, "%s/err-%s-%s.log", log_dir, context, now); | |||
IZ_fopen(&stdout_dest, stdout_filename, "a"); | |||
IZ_fopen(&stderr_dest, stderr_filename, "a"); | |||
#endif | |||
} | |||
void IZ_LogTeardown() { | |||
#ifndef IZ_DEBUG | |||
fclose(stdout_dest); | |||
#endif | |||
} | |||
@@ -48,12 +75,12 @@ void IZ_LogError(const char* context, const char* fmt, ...) { | |||
vsnprintf(buffer, sizeof(buffer), fmt, args); | |||
va_end(args); | |||
if (IZ_LogIsSupportedColor()) { | |||
fprintf(stdout, RED "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||
fprintf(stdout_dest, RED "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
return; | |||
} | |||
fprintf(stderr, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stderr_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
#endif | |||
} | |||
@@ -65,24 +92,24 @@ void IZ_LogInfo(IZ_LogCategory category, const char* context, const char* fmt, . | |||
vsnprintf(buffer, sizeof(buffer), fmt, args); | |||
va_end(args); | |||
if (IZ_LogIsSupportedColor()) { | |||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||
switch (category) { | |||
default: | |||
case IZ_LOG_CATEGORY_GENERIC: | |||
fprintf(stdout, CYN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, CYN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
break; | |||
case IZ_LOG_CATEGORY_GLOBAL: | |||
fprintf(stdout, MAG "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, MAG "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
break; | |||
case IZ_LOG_CATEGORY_INPUT: | |||
fprintf(stdout, WHT "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, WHT "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
break; | |||
} | |||
return; | |||
} | |||
fprintf(stdout, "%24s" " %s\n", IZ_LOG_DATE_FUNCTION(), buffer); | |||
fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
#endif | |||
} | |||
@@ -94,16 +121,16 @@ void IZ_LogWarn(bool is_critical, const char* context, const char* fmt, ...) { | |||
vsnprintf(buffer, sizeof(buffer), fmt, args); | |||
va_end(args); | |||
if (IZ_LogIsSupportedColor()) { | |||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||
if (is_critical) { | |||
fprintf(stdout, GRN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, GRN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
} else { | |||
fprintf(stdout, YEL "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, YEL "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
} | |||
return; | |||
} | |||
fprintf(stdout, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
#endif | |||
} | |||
@@ -114,11 +141,12 @@ void IZ_Log(const char* context, const char* fmt, ...) { | |||
va_start(args, fmt); | |||
vsnprintf(buffer, sizeof(buffer), fmt, args); | |||
va_end(args); | |||
if (IZ_LogIsSupportedColor()) { | |||
fprintf(stdout, BLU "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||
fprintf(stdout_dest, BLU "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
return; | |||
} | |||
fprintf(stdout, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); | |||
fflush(stdout_dest); | |||
#endif | |||
} |
@@ -22,6 +22,8 @@ | |||
#include <stdio.h> | |||
#include <time.h> | |||
#include "../timer/IZ_timer.h" | |||
#include "../io/IZ_io.h" | |||
#include "../stdinc/IZ_string.h" | |||
typedef enum { | |||
IZ_LOG_CATEGORY_INPUT, | |||
@@ -29,9 +31,14 @@ typedef enum { | |||
IZ_LOG_CATEGORY_GENERIC, | |||
} IZ_LogCategory; | |||
void IZ_LogError(const char* context, const char* fmt, ...); | |||
void IZ_LogInfo(IZ_LogCategory category, const char* context, const char* fmt, ...); | |||
void IZ_LogWarn(bool is_critical, const char* context, const char* fmt, ...); | |||
void IZ_Log(const char* context, const char* fmt, ...); | |||
static FILE* stdout_dest; | |||
static FILE* stderr_dest; | |||
void IZ_LogInitialize(const char*); | |||
void IZ_LogError(const char*, const char*, ...); | |||
void IZ_LogInfo(IZ_LogCategory, const char*, const char*, ...); | |||
void IZ_LogWarn(bool, const char*, const char*, ...); | |||
void IZ_Log(const char*, const char*, ...); | |||
void IZ_LogTeardown(void); | |||
#endif |
@@ -12,6 +12,8 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | |||
IZ_memset(app, 0, sizeof(IZ_App)); | |||
signal(SIGINT, IZ_AppHandleSignal); | |||
IZ_LogInitialize("server"); | |||
// IZ_LogInterceptWSMessages(app->config.log_level); | |||
IZ_LogInterceptWSMessages(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE); | |||
@@ -38,7 +40,7 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | |||
void IZ_AppTeardown(IZ_App* app) { | |||
IZ_RepoTeardown(&app->repo_state); | |||
IZ_WSServerTeardown(&app->net_state.binding); | |||
lwsl_user("Server closed. Bye!\n"); | |||
IZ_LogTeardown(); | |||
} | |||
void IZ_AppPrintHelpOptions() { | |||
@@ -67,3 +67,20 @@ char* IZ_TimerNow() { | |||
sprintf(buffer, "%s.%03dZ", formatted, milliseconds < 0 ? 0 : milliseconds % 1000); | |||
return buffer; | |||
} | |||
/** | |||
* Gets the formatted time in the current instant that can be safely added in file paths. | |||
* @return The formatted time in the current instant. | |||
*/ | |||
char* IZ_TimerNowPathSafe() { | |||
struct timespec t; | |||
clock_gettime(CLOCK_REALTIME, &t); | |||
static char buffer[32]; | |||
unsigned int seconds = t.tv_sec; | |||
unsigned int milliseconds = t.tv_nsec / 1000000; | |||
static char formatted[32]; | |||
time_t current_time = seconds; | |||
strftime(formatted, sizeof(formatted), "%Y%m%d%H%M%S", gmtime(¤t_time)); | |||
sprintf(buffer, "%s%03d", formatted, milliseconds < 0 ? 0 : milliseconds % 1000); | |||
return buffer; | |||
} |
@@ -17,26 +17,32 @@ static time_t IZ_TIMER_START_TIMESTAMP = 0; | |||
* Gets the start timestamp. | |||
* @sa IZ_TIMER_START_TIMESTAMP | |||
*/ | |||
void IZ_TimerStart(); | |||
void IZ_TimerStart(void); | |||
/** | |||
* Gets the number of microseconds since the application timer has been started. | |||
* @return The number of microseconds. | |||
* @sa IZ_TimerElapsed() | |||
*/ | |||
unsigned int IZ_TimerElapsedRaw(); | |||
unsigned int IZ_TimerElapsedRaw(void); | |||
/** | |||
* Gets the formatted elapsed time since the application timer has been started. | |||
* @return The formatted elapsed time. | |||
* @sa IZ_TimerElapsedRaw() | |||
*/ | |||
char* IZ_TimerElapsed(); | |||
char* IZ_TimerElapsed(void); | |||
/** | |||
* Gets the formatted time in the current instant. | |||
* @return The formatted time in the current instant. | |||
*/ | |||
char* IZ_TimerNow(); | |||
char* IZ_TimerNow(void); | |||
/** | |||
* Gets the formatted time in the current instant that can be safely added in file paths. | |||
* @return The formatted time in the current instant. | |||
*/ | |||
char* IZ_TimerNowPathSafe(void); | |||
#endif |