230 lines
6.2 KiB
C++

#include "logger.h"
#include <sys/stat.h> // For mkdir
#include <errno.h> // For errno
// By declaring this function here, we make it private. you cant access it outside of this file
void get_executable_path(char *buffer, size_t size)
{
#ifdef _WIN32
// On Windows, we use GetModuleFileName
GetModuleFileName(NULL, buffer, (DWORD)size);
// Strip the filename from the path
char *last_slash = strrchr(buffer, '\\');
if (last_slash)
*last_slash = '\0';
#else
// On Linux, we can just do "./"
// or use readlink("/proc/self/exe", buffer, size) to get the full path
// but for simplicity, we just use "./"
if (size > 2)
{
strncpy(buffer, "./", size - 1);
buffer[size - 1] = '\0';
}
else
{
fprintf(stderr, "Buffer size is too small\n");
exit(EXIT_FAILURE);
}
#endif
}
/** \brief A simple print funcion to help easely print to the screen
*
* \param unsigned short flags
* \param const char *Format
* \param ...
* \return unsigned int (number of printed chars)
*
*/
unsigned int flogf(unsigned short flags, const char *Format, ...)
{
va_list args;
va_start(args, Format);
unsigned int char_counter = 0;
static unsigned char isFileDeclared = 0; // false
char filepath[256];
FILE *selected_std = stdout;
if (isFileDeclared)
{
selected_std = fopen(filepath, "a");
}
time_t RAW_TIME = time(NULL);
struct tm *time_info;
time_info = localtime(&RAW_TIME);
if ((flags & LOG_FILE) && !isFileDeclared)
{
char exe_path[512];
get_executable_path(exe_path, sizeof(exe_path));
#if defined(_WIN32)
sprintf(filepath, "%s\\logs\\log_%02d-%02d-%4d.txt",
exe_path,
time_info->tm_mday,
time_info->tm_mon + 1, // months start at 0
time_info->tm_year + 1900);
#else
sprintf(filepath, "%slogs/log_%02d-%02d-%4d.txt",
exe_path,
time_info->tm_mday,
time_info->tm_mon + 1, // months start at 0
time_info->tm_year + 1900);
#endif
// Ensure the logs directory exists
char logs_dir[512];
#if defined(_WIN32)
sprintf(logs_dir, "%s\\logs", exe_path);
_mkdir(logs_dir); // Windows-specific mkdir
#else
sprintf(logs_dir, "%s/logs", exe_path);
if (mkdir(logs_dir, 0755) == -1 && errno != EEXIST)
{
perror("Error creating logs directory");
return 0;
}
#endif
// Create file if it doesn't exist
selected_std = fopen(filepath, "a");
if (!selected_std)
{
fprintf(stdout, "ERROR OPENING LOG FILE\n");
selected_std = stdout;
return 0;
}
printf("Loging to file: \"%s\"\n", filepath);
fprintf(selected_std, "\n%02d:%02d:%02d - NEW ENTRY \n-------------------------------------------------\n",
time_info->tm_hour,
time_info->tm_min,
time_info->tm_sec);
isFileDeclared = 1;
}
if ((flags & LOG_TIME_STAMP))
{
fprintf(selected_std, "%02d:%02d:%02d - ",
time_info->tm_hour,
time_info->tm_min,
time_info->tm_sec);
}
else
{
fprintf(selected_std, " ");
}
if (flags & LOG_LEVEL_WARN)
{
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_YELLOW);
}
fprintf(selected_std, "[WARNING]: \t");
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_RESET);
}
}
else if (flags & LOG_LEVEL_ERROR)
{
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_RED);
}
fprintf(selected_std, "[ERROR]: \t");
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_RESET);
}
}
else if (flags & LOG_LEVEL_INFO)
{
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_BLUE);
}
fprintf(selected_std, "[INFO]: \t");
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_RESET);
}
}
else if (flags & LOG_LEVEL_SUCCESS)
{
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_GREEN);
}
fprintf(selected_std, "[SUCCESS]: \t");
if (flags & LOG_COLOR_OUT)
{
fprintf(selected_std, COLOR_RESET);
}
}
while (*Format)
{
if (*Format == '%')
{
*Format++; // find out if its a d, s, f, etc.
switch (*Format)
{
case 'd': // Integer
fprintf(selected_std, "%d", va_arg(args, int));
break;
case 'f': // Floating-point
fprintf(selected_std, "%f", va_arg(args, double));
break;
case 's': // String
fprintf(selected_std, "%s", va_arg(args, char *));
break;
case 'c': // Character
fprintf(selected_std, "%c", va_arg(args, int));
break;
case 'x': // Hexadecimal
fprintf(selected_std, "%x", va_arg(args, unsigned int));
break;
case 'p': // Pointer
fprintf(selected_std, "%p", va_arg(args, void *));
break;
case '%': // Literal '%'
fprintf(selected_std, "%%");
break;
default: // Unknown specifier
fprintf(selected_std, "%%");
fprintf(selected_std, "%c", *Format);
break;
}
}
else
{
fprintf(selected_std, "%c", *Format);
}
*Format++; // iterate over the format text
char_counter++;
}
if (flags & LOG_FILE)
fclose(selected_std);
va_end(args);
return char_counter;
} // wrapper (global)