@@ -26,6 +26,7 @@ typedef enum { | |||||
} IZ_AppInitializeResult; | } IZ_AppInitializeResult; | ||||
IZ_AppInitializeResult IZ_AppInitialize(struct IZ_App* app, u8 argc, const char* argv[]) { | 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_LogInterceptWSMessages(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE); | ||||
IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "global", "Starting %s...", IZ_APP_NAME); | 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_InputTeardown(&app->input_state); | ||||
IZ_VideoTeardown(&app->video_state); | IZ_VideoTeardown(&app->video_state); | ||||
IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "global", "Stopping %s...", IZ_APP_NAME); | IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "global", "Stopping %s...", IZ_APP_NAME); | ||||
IZ_LogTeardown(); | |||||
SDL_Quit(); | SDL_Quit(); | ||||
} | } | ||||
@@ -24,3 +24,36 @@ errno_t IZ_fopen(FILE** file, const char* filename, const char* mode) { | |||||
return *file == NULL ? 1 : 0; | return *file == NULL ? 1 : 0; | ||||
#endif | #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 | #define IZ_IO_H | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdbool.h> | |||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include "../compat/IZ_windows.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_fopen(FILE**, const char*, const char*); | ||||
errno_t IZ_mkdir(const char*); | |||||
bool IZ_isdir(const char*); | |||||
#endif | #endif |
@@ -32,11 +32,38 @@ bool IZ_LogIsSupportedTerminal() { | |||||
#endif | #endif | ||||
} | } | ||||
bool IZ_LogIsSupportedColor() { | |||||
bool IZ_LogIsSupportedColor(FILE* s) { | |||||
#ifdef IZ_WINDOWS | #ifdef IZ_WINDOWS | ||||
return _isatty(_fileno(stdout)) && IZ_LogIsSupportedTerminal(); | |||||
return _isatty(_fileno(s)) && IZ_LogIsSupportedTerminal(); | |||||
#else | #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 | #endif | ||||
} | } | ||||
@@ -48,12 +75,12 @@ void IZ_LogError(const char* context, const char* fmt, ...) { | |||||
vsnprintf(buffer, sizeof(buffer), fmt, args); | vsnprintf(buffer, sizeof(buffer), fmt, args); | ||||
va_end(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; | 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 | #endif | ||||
} | } | ||||
@@ -65,24 +92,24 @@ void IZ_LogInfo(IZ_LogCategory category, const char* context, const char* fmt, . | |||||
vsnprintf(buffer, sizeof(buffer), fmt, args); | vsnprintf(buffer, sizeof(buffer), fmt, args); | ||||
va_end(args); | va_end(args); | ||||
if (IZ_LogIsSupportedColor()) { | |||||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||||
switch (category) { | switch (category) { | ||||
default: | default: | ||||
case IZ_LOG_CATEGORY_GENERIC: | 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; | break; | ||||
case IZ_LOG_CATEGORY_GLOBAL: | 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; | break; | ||||
case IZ_LOG_CATEGORY_INPUT: | 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; | break; | ||||
} | } | ||||
return; | 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 | #endif | ||||
} | } | ||||
@@ -94,16 +121,16 @@ void IZ_LogWarn(bool is_critical, const char* context, const char* fmt, ...) { | |||||
vsnprintf(buffer, sizeof(buffer), fmt, args); | vsnprintf(buffer, sizeof(buffer), fmt, args); | ||||
va_end(args); | va_end(args); | ||||
if (IZ_LogIsSupportedColor()) { | |||||
if (IZ_LogIsSupportedColor(stdout_dest)) { | |||||
if (is_critical) { | 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 { | } 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; | 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 | #endif | ||||
} | } | ||||
@@ -114,11 +141,12 @@ void IZ_Log(const char* context, const char* fmt, ...) { | |||||
va_start(args, fmt); | va_start(args, fmt); | ||||
vsnprintf(buffer, sizeof(buffer), fmt, args); | vsnprintf(buffer, sizeof(buffer), fmt, args); | ||||
va_end(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; | 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 | #endif | ||||
} | } |
@@ -22,6 +22,8 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <time.h> | #include <time.h> | ||||
#include "../timer/IZ_timer.h" | #include "../timer/IZ_timer.h" | ||||
#include "../io/IZ_io.h" | |||||
#include "../stdinc/IZ_string.h" | |||||
typedef enum { | typedef enum { | ||||
IZ_LOG_CATEGORY_INPUT, | IZ_LOG_CATEGORY_INPUT, | ||||
@@ -29,9 +31,14 @@ typedef enum { | |||||
IZ_LOG_CATEGORY_GENERIC, | IZ_LOG_CATEGORY_GENERIC, | ||||
} IZ_LogCategory; | } 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 | #endif |
@@ -12,6 +12,8 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | |||||
IZ_memset(app, 0, sizeof(IZ_App)); | IZ_memset(app, 0, sizeof(IZ_App)); | ||||
signal(SIGINT, IZ_AppHandleSignal); | signal(SIGINT, IZ_AppHandleSignal); | ||||
IZ_LogInitialize("server"); | |||||
// IZ_LogInterceptWSMessages(app->config.log_level); | // IZ_LogInterceptWSMessages(app->config.log_level); | ||||
IZ_LogInterceptWSMessages(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE); | 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) { | void IZ_AppTeardown(IZ_App* app) { | ||||
IZ_RepoTeardown(&app->repo_state); | IZ_RepoTeardown(&app->repo_state); | ||||
IZ_WSServerTeardown(&app->net_state.binding); | IZ_WSServerTeardown(&app->net_state.binding); | ||||
lwsl_user("Server closed. Bye!\n"); | |||||
IZ_LogTeardown(); | |||||
} | } | ||||
void IZ_AppPrintHelpOptions() { | void IZ_AppPrintHelpOptions() { | ||||
@@ -67,3 +67,20 @@ char* IZ_TimerNow() { | |||||
sprintf(buffer, "%s.%03dZ", formatted, milliseconds < 0 ? 0 : milliseconds % 1000); | sprintf(buffer, "%s.%03dZ", formatted, milliseconds < 0 ? 0 : milliseconds % 1000); | ||||
return buffer; | 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. | * Gets the start timestamp. | ||||
* @sa IZ_TIMER_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. | * Gets the number of microseconds since the application timer has been started. | ||||
* @return The number of microseconds. | * @return The number of microseconds. | ||||
* @sa IZ_TimerElapsed() | * @sa IZ_TimerElapsed() | ||||
*/ | */ | ||||
unsigned int IZ_TimerElapsedRaw(); | |||||
unsigned int IZ_TimerElapsedRaw(void); | |||||
/** | /** | ||||
* Gets the formatted elapsed time since the application timer has been started. | * Gets the formatted elapsed time since the application timer has been started. | ||||
* @return The formatted elapsed time. | * @return The formatted elapsed time. | ||||
* @sa IZ_TimerElapsedRaw() | * @sa IZ_TimerElapsedRaw() | ||||
*/ | */ | ||||
char* IZ_TimerElapsed(); | |||||
char* IZ_TimerElapsed(void); | |||||
/** | /** | ||||
* Gets the formatted time in the current instant. | * Gets the formatted time in the current instant. | ||||
* @return 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 | #endif |