generated from AfonsoCMSousa/CPP-Template
Added file IO operations, and argument parcing
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#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)
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef LOGGER_H_INCLUDED
|
||||
#define LOGGER_H_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#define MKDIR(path) _mkdir(path)
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#define MKDIR(path) mkdir(path, 0777)
|
||||
#endif
|
||||
|
||||
#define LOG_LEVEL_INFO (1 << 0)
|
||||
#define LOG_LEVEL_WARN (1 << 1)
|
||||
#define LOG_LEVEL_ERROR (1 << 2)
|
||||
#define LOG_LEVEL_SUCCESS (1 << 3)
|
||||
#define LOG_COLOR_OUT (1 << 4)
|
||||
#define LOG_ONLY_ERROR (1 << 5)
|
||||
#define LOG_FILE (1 << 6)
|
||||
#define LOG_TIME_STAMP (1 << 7)
|
||||
|
||||
#define COLOR_RED "\x1b[31m"
|
||||
#define COLOR_GREEN "\x1b[32m"
|
||||
#define COLOR_YELLOW "\x1b[33m"
|
||||
#define COLOR_BLUE "\x1b[34m"
|
||||
#define COLOR_RESET "\x1b[0m"
|
||||
|
||||
unsigned int flogf(unsigned short flags, const char *Format, ...);
|
||||
|
||||
void get_executable_path(char *buffer, size_t size);
|
||||
|
||||
#endif // LOGGER_H_INCLUDED
|
||||
Reference in New Issue
Block a user