mirror of
https://github.com/thunderbrewhq/squall.git
synced 2025-12-12 10:32:29 +00:00
commit
32f8213fef
4 changed files with 711 additions and 0 deletions
16
storm/Common.hpp
Normal file
16
storm/Common.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef STORM_COMMON_HPP
|
||||
#define STORM_COMMON_HPP
|
||||
|
||||
|
||||
#define DECLARE_STRICT_HANDLE(name) \
|
||||
typedef struct name##__ { \
|
||||
int unused; \
|
||||
}* name
|
||||
|
||||
#define DECLARE_DERIVED_HANDLE(name, base) \
|
||||
typedef struct name##__ : public base##__ { \
|
||||
int unused; \
|
||||
}* name
|
||||
|
||||
|
||||
#endif
|
||||
606
storm/Log.cpp
Normal file
606
storm/Log.cpp
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
#include "storm/Log.hpp"
|
||||
#include "storm/Thread.hpp"
|
||||
#include "storm/Error.hpp"
|
||||
#include "storm/Memory.hpp"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(WHOA_SYSTEM_LINUX)
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define STORM_LOG_MAX_CHANNELS 4
|
||||
#define STORM_LOG_MAX_BUFFER 0x10000
|
||||
#define STORM_LOG_FLUSH_POINT 0xC000
|
||||
|
||||
|
||||
typedef struct _LOG {
|
||||
HSLOG log;
|
||||
_LOG* next;
|
||||
char filename[STORM_MAX_PATH];
|
||||
FILE* file;
|
||||
uint32_t flags;
|
||||
size_t bufferused;
|
||||
size_t pendpoint;
|
||||
int32_t indent;
|
||||
int32_t timeStamp;
|
||||
char buffer[STORM_LOG_MAX_BUFFER];
|
||||
} LOG;
|
||||
|
||||
|
||||
static uint64_t lasttime = 0;
|
||||
static size_t timestrlen = 0;
|
||||
static char timestr[64] = { '\0' };
|
||||
|
||||
static SCritSect* s_critsect[STORM_LOG_MAX_CHANNELS] = { nullptr };
|
||||
static SCritSect* s_defaultdir_critsect = nullptr;
|
||||
|
||||
static LOG* s_loghead[STORM_LOG_MAX_CHANNELS] = { nullptr };
|
||||
static HSLOG s_sequence = 0;
|
||||
|
||||
static char s_defaultdir[STORM_MAX_PATH] = { '\0' };
|
||||
static bool s_logsysteminit = false;
|
||||
|
||||
|
||||
static LOG* LockLog(HSLOG log, HLOCKEDLOG* lockedhandle, bool createifnecessary) {
|
||||
if (!log) {
|
||||
*lockedhandle = (HLOCKEDLOG)-1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t index = reinterpret_cast<size_t>(log) & 3;
|
||||
s_critsect[index]->Enter();
|
||||
*lockedhandle = (HLOCKEDLOG)index;
|
||||
|
||||
LOG* result = s_loghead[index];
|
||||
LOG** p_next = &s_loghead[index];
|
||||
|
||||
while (result && result->log != log) {
|
||||
p_next = &result->next;
|
||||
result = result->next;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (createifnecessary) {
|
||||
result = (LOG*)SMemAlloc(sizeof(LOG), __FILE__, __LINE__, 0);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
s_critsect[index]->Leave();
|
||||
*lockedhandle = (HLOCKEDLOG)-1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*p_next = result;
|
||||
result->log = log;
|
||||
result->next = nullptr;
|
||||
result->filename[0] = '\0';
|
||||
result->file = nullptr;
|
||||
result->bufferused = 0;
|
||||
result->pendpoint = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void UnlockLog(HLOCKEDLOG lockedhandle) {
|
||||
s_critsect[reinterpret_cast<size_t>(lockedhandle)]->Leave();
|
||||
}
|
||||
|
||||
static void UnlockDeleteLog(LOG* logptr, HLOCKEDLOG lockedhandle) {
|
||||
size_t index = reinterpret_cast<size_t>(lockedhandle);
|
||||
LOG* log = s_loghead[index];
|
||||
LOG** p_next = &s_loghead[index];
|
||||
|
||||
while (log && log != logptr) {
|
||||
p_next = &log->next;
|
||||
log = log->next;
|
||||
}
|
||||
|
||||
if (log) {
|
||||
*p_next = log->next;
|
||||
SMemFree(log);
|
||||
}
|
||||
|
||||
s_critsect[index]->Leave();
|
||||
}
|
||||
|
||||
static void FlushLog(LOG* logptr) {
|
||||
if (!logptr->bufferused) {
|
||||
return;
|
||||
}
|
||||
|
||||
STORM_ASSERT(logptr->file);
|
||||
fwrite(logptr->buffer, 1, logptr->bufferused, logptr->file);
|
||||
fflush(logptr->file);
|
||||
logptr->bufferused = 0;
|
||||
logptr->pendpoint = 0;
|
||||
}
|
||||
|
||||
static const char* PrependDefaultDir(char* newfilename, uint32_t newfilenamesize, const char* filename) {
|
||||
if (!filename || !filename[0] || filename[1] == ':' || SStrChr(filename, '\\') || SStrChr(filename, '/')) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
s_defaultdir_critsect->Enter();
|
||||
|
||||
if (s_defaultdir[0]) {
|
||||
SStrCopy(newfilename, s_defaultdir, newfilenamesize);
|
||||
SStrPack(newfilename, filename, newfilenamesize);
|
||||
} else {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
GetModuleFileName(NULL, newfilename, newfilenamesize);
|
||||
char* slash = SStrChrR(newfilename, '\\');
|
||||
if (slash) {
|
||||
slash[0] = '\0';
|
||||
}
|
||||
|
||||
SStrPack(newfilename, "\\", newfilenamesize);
|
||||
SStrPack(newfilename, filename, newfilenamesize);
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_LINUX)
|
||||
char buffer[PATH_MAX];
|
||||
if (!realpath("/proc/self/exe", buffer)) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
char* slash = SStrChrR(buffer, '/');
|
||||
if (slash) {
|
||||
slash[0] = '\0';
|
||||
}
|
||||
|
||||
SStrCopy(newfilename, buffer, newfilenamesize);
|
||||
SStrPack(newfilename, "/", newfilenamesize);
|
||||
SStrPack(newfilename, filename, newfilenamesize);
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
newfilename[0] = '\0';
|
||||
|
||||
char path[PATH_MAX] = {0};
|
||||
char actualPath[PATH_MAX] = {0};
|
||||
uint32_t size = PATH_MAX;
|
||||
if (_NSGetExecutablePath(path, &size) == 0) {
|
||||
if (!realpath(path, actualPath)) {
|
||||
actualPath[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
char* slash = SStrChrR(actualPath, '/');
|
||||
if (slash) {
|
||||
slash[0] = '\0';
|
||||
}
|
||||
|
||||
SStrCopy(newfilename, actualPath, newfilenamesize);
|
||||
SStrPack(newfilename, "/", newfilenamesize);
|
||||
SStrPack(newfilename, filename, newfilenamesize);
|
||||
#endif
|
||||
}
|
||||
|
||||
s_defaultdir_critsect->Leave();
|
||||
return newfilename;
|
||||
}
|
||||
|
||||
static size_t PathGetRootChars(const char* path) {
|
||||
if (path[0] == '/') {
|
||||
if (!SStrCmpI(path, "/Volumes/", 9)) {
|
||||
const char* offset = SStrChr(path + 9, '/');
|
||||
if (offset) {
|
||||
return offset - path + 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SStrLen(path) < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path[1] == ':') {
|
||||
return (path[2] == '\\') ? 3 : 2;
|
||||
}
|
||||
|
||||
if (path[0] != '\\' || path[1] != '\\') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* slash1 = SStrChr(path + 2, '\\');
|
||||
if (!slash1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* slash2 = SStrChr(slash1 + 1, '\\');
|
||||
if (!slash2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return slash2 - path + 1;
|
||||
}
|
||||
|
||||
static void PathStripFilename(char* path) {
|
||||
char* slash = SStrChrR(path, '/');
|
||||
char* backslash = SStrChrR(path, '\\');
|
||||
if (slash <= backslash) {
|
||||
slash = backslash;
|
||||
}
|
||||
|
||||
if (!slash) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* relative = &path[PathGetRootChars(path)];
|
||||
if (slash >= relative) {
|
||||
slash[1] = 0;
|
||||
} else {
|
||||
relative[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void PathConvertSlashes(char* path) {
|
||||
while (*path) {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
if (*path == '/') {
|
||||
*path = '\\';
|
||||
}
|
||||
#else
|
||||
if (*path == '\\') {
|
||||
*path = '/';
|
||||
}
|
||||
#endif
|
||||
path++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CreateFileDirectory(const char* path) {
|
||||
STORM_ASSERT(path);
|
||||
|
||||
char buffer[STORM_MAX_PATH];
|
||||
SStrCopy(buffer, path, STORM_MAX_PATH);
|
||||
PathStripFilename(buffer);
|
||||
|
||||
char* relative = &buffer[PathGetRootChars(buffer)];
|
||||
PathConvertSlashes(relative);
|
||||
|
||||
for (size_t i = 0; relative[i]; ++i) {
|
||||
if (relative[i] != '\\' && relative[i] != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
char slash = relative[i];
|
||||
relative[i] = '\0';
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
CreateDirectory(buffer, NULL);
|
||||
#else
|
||||
mkdir(buffer, 0755);
|
||||
#endif
|
||||
relative[i] = slash;
|
||||
}
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
return CreateDirectory(buffer, NULL);
|
||||
#else
|
||||
return !mkdir(buffer, 0755);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool OpenLogFile(const char* filename, FILE** file, uint32_t flags) {
|
||||
*file = nullptr;
|
||||
|
||||
if (filename && filename[0]) {
|
||||
char newfilename[STORM_MAX_PATH];
|
||||
PrependDefaultDir(newfilename, STORM_MAX_PATH, filename);
|
||||
CreateFileDirectory(newfilename);
|
||||
*file = fopen(newfilename, (flags & SLOG_FLAG_APPEND) ? "a" : "w");
|
||||
return (*file != nullptr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void OutputIndent(LOG* logptr) {
|
||||
int32_t indent = logptr->indent;
|
||||
if (indent > 0) {
|
||||
if (indent >= 128) {
|
||||
indent = 128;
|
||||
}
|
||||
memset(&logptr->buffer[logptr->bufferused], ' ', indent);
|
||||
logptr->buffer[indent + logptr->bufferused] = 0;
|
||||
logptr->bufferused += indent;
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputReturn(LOG* logptr) {
|
||||
// strcpy(&logptr->buffer[logptr->bufferused], "\r\n");
|
||||
// logptr->bufferused += 2;
|
||||
|
||||
// No need to write "\r\n" with fopen() in text mode
|
||||
logptr->buffer[logptr->bufferused] = '\n';
|
||||
logptr->bufferused++;
|
||||
}
|
||||
|
||||
static void OutputTime(LOG* logptr, bool show) {
|
||||
if (logptr->timeStamp == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t ticks = 0;
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
ticks = GetTickCount64();
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_LINUX)
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
|
||||
ticks = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
ticks = mach_absolute_time();
|
||||
#endif
|
||||
|
||||
if (ticks != lasttime) {
|
||||
lasttime = ticks;
|
||||
|
||||
time_t t = time(nullptr);
|
||||
struct tm* ts = localtime(&t);
|
||||
// No milliseconds for now
|
||||
timestrlen = SStrPrintf(timestr,
|
||||
sizeof(timestr),
|
||||
"%d/%d %02d:%02d:%02d.%03d ",
|
||||
ts->tm_mon + 1,
|
||||
ts->tm_mday,
|
||||
ts->tm_hour,
|
||||
ts->tm_min,
|
||||
ts->tm_sec,
|
||||
0);
|
||||
}
|
||||
|
||||
if (show) {
|
||||
memcpy(&logptr->buffer[logptr->bufferused], timestr, timestrlen);
|
||||
} else {
|
||||
memset(&logptr->buffer[logptr->bufferused], ' ', timestrlen);
|
||||
}
|
||||
logptr->bufferused += timestrlen;
|
||||
logptr->buffer[logptr->bufferused] = '\0';
|
||||
}
|
||||
|
||||
static bool PrepareLog(LOG* logptr) {
|
||||
if (logptr->file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (OpenLogFile(logptr->filename, &logptr->file, logptr->flags)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
logptr->filename[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
void SLogInitialize() {
|
||||
if (s_logsysteminit) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < STORM_LOG_MAX_CHANNELS; ++i) {
|
||||
s_critsect[i] = new SCritSect();
|
||||
}
|
||||
|
||||
s_defaultdir_critsect = new SCritSect();
|
||||
|
||||
s_logsysteminit = true;
|
||||
}
|
||||
|
||||
int SLogIsInitialized() {
|
||||
return s_logsysteminit ? 1 : 0;
|
||||
}
|
||||
|
||||
void SLogDestroy() {
|
||||
for (size_t i = 0; i < STORM_LOG_MAX_CHANNELS; ++i) {
|
||||
s_critsect[i]->Enter();
|
||||
LOG* log = s_loghead[i];
|
||||
while (log) {
|
||||
if (log->file) {
|
||||
FlushLog(log);
|
||||
fclose(log->file);
|
||||
}
|
||||
LOG* next = log->next;
|
||||
SMemFree(log);
|
||||
log = next;
|
||||
}
|
||||
s_loghead[i] = nullptr;
|
||||
s_critsect[i]->Leave();
|
||||
delete s_critsect[i];
|
||||
}
|
||||
|
||||
delete s_defaultdir_critsect;
|
||||
s_logsysteminit = false;
|
||||
}
|
||||
|
||||
int SLogCreate(const char* filename, uint32_t flags, HSLOG* log) {
|
||||
STORM_ASSERT(filename);
|
||||
STORM_ASSERT(*filename);
|
||||
STORM_ASSERT(log);
|
||||
|
||||
FILE* file = nullptr;
|
||||
HLOCKEDLOG lockedhandle;
|
||||
|
||||
*log = 0;
|
||||
|
||||
if (flags & SLOG_FLAG_NO_FILE) {
|
||||
filename = "";
|
||||
flags &= ~SLOG_FLAG_OPEN_FILE;
|
||||
}
|
||||
|
||||
if ((flags & SLOG_FLAG_OPEN_FILE) == 0 || OpenLogFile(filename, &file, flags)) {
|
||||
s_sequence = reinterpret_cast<HSLOG>(reinterpret_cast<size_t>(s_sequence) + 1);
|
||||
*log = s_sequence;
|
||||
LOG* result = LockLog(s_sequence, &lockedhandle, true);
|
||||
if (result) {
|
||||
result->file = file;
|
||||
SStrCopy(result->filename, filename, STORM_MAX_PATH);
|
||||
result->flags = flags;
|
||||
result->timeStamp = 1;
|
||||
result->indent = 0;
|
||||
UnlockLog(lockedhandle);
|
||||
return 1;
|
||||
} else {
|
||||
*log = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SLogClose(HSLOG log) {
|
||||
if (!s_logsysteminit) {
|
||||
return;
|
||||
}
|
||||
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (!logptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (logptr->file) {
|
||||
FlushLog(logptr);
|
||||
fclose(logptr->file);
|
||||
}
|
||||
|
||||
UnlockDeleteLog(logptr, lockedhandle);
|
||||
}
|
||||
|
||||
void SLogFlush(HSLOG log) {
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (logptr) {
|
||||
if (logptr->file) {
|
||||
FlushLog(logptr);
|
||||
}
|
||||
UnlockLog(lockedhandle);
|
||||
}
|
||||
}
|
||||
|
||||
void SLogFlushAll() {
|
||||
for (size_t i = 0; i < STORM_LOG_MAX_CHANNELS; ++i) {
|
||||
s_critsect[i]->Enter();
|
||||
for (LOG* log = s_loghead[i]; log; log = log->next) {
|
||||
if (log->file) {
|
||||
FlushLog(log);
|
||||
}
|
||||
}
|
||||
s_critsect[i]->Leave();
|
||||
}
|
||||
}
|
||||
|
||||
void SLogGetDefaultDirectory(char* dirname, size_t dirnamesize) {
|
||||
s_defaultdir_critsect->Enter();
|
||||
SStrCopy(dirname, s_defaultdir, dirnamesize);
|
||||
s_defaultdir_critsect->Leave();
|
||||
}
|
||||
|
||||
void SLogSetDefaultDirectory(const char* dirname) {
|
||||
s_defaultdir_critsect->Enter();
|
||||
size_t size = SStrCopy(s_defaultdir, dirname, STORM_MAX_PATH);
|
||||
PathConvertSlashes(s_defaultdir);
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
char slash = '\\';
|
||||
#else
|
||||
char slash = '/';
|
||||
#endif
|
||||
if (size < STORM_MAX_PATH - 1 && s_defaultdir[size - 1] != slash) {
|
||||
s_defaultdir[size] = slash;
|
||||
s_defaultdir[size + 1] = 0;
|
||||
}
|
||||
s_defaultdir_critsect->Leave();
|
||||
}
|
||||
|
||||
int32_t SLogSetAbsIndent(HSLOG log, int32_t indent) {
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (logptr) {
|
||||
int32_t result = logptr->indent;
|
||||
logptr->indent = indent;
|
||||
UnlockLog(lockedhandle);
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SLogSetIndent(HSLOG log, int32_t deltaIndent) {
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (logptr) {
|
||||
int32_t result = logptr->indent;
|
||||
logptr->indent = result + deltaIndent;
|
||||
UnlockLog(lockedhandle);
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SLogSetTimestamp(HSLOG log, int32_t timeStamp) {
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (logptr) {
|
||||
logptr->timeStamp = timeStamp;
|
||||
UnlockLog(lockedhandle);
|
||||
}
|
||||
}
|
||||
|
||||
void SLogVWrite(HSLOG log, const char* format, va_list arglist) {
|
||||
HLOCKEDLOG lockedhandle;
|
||||
LOG* logptr = LockLog(log, &lockedhandle, false);
|
||||
if (!logptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PrepareLog(logptr)) {
|
||||
OutputTime(logptr, true);
|
||||
OutputIndent(logptr);
|
||||
|
||||
int count = vsnprintf(
|
||||
&logptr->buffer[logptr->bufferused],
|
||||
STORM_LOG_MAX_BUFFER - logptr->bufferused,
|
||||
format,
|
||||
arglist);
|
||||
if (count > 0) {
|
||||
logptr->bufferused += count;
|
||||
}
|
||||
|
||||
OutputReturn(logptr);
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// if (g_opt.echotooutputdebugstring)
|
||||
OutputDebugString(&logptr->buffer[logptr->pendpoint]);
|
||||
#endif
|
||||
|
||||
logptr->pendpoint = logptr->bufferused;
|
||||
if (logptr->bufferused >= STORM_LOG_FLUSH_POINT) {
|
||||
FlushLog(logptr);
|
||||
}
|
||||
}
|
||||
UnlockLog(lockedhandle);
|
||||
}
|
||||
|
||||
void SLogWrite(HSLOG log, const char* format, ...) {
|
||||
va_list arglist;
|
||||
va_start(arglist, format);
|
||||
SLogVWrite(log, format, arglist);
|
||||
}
|
||||
38
storm/Log.hpp
Normal file
38
storm/Log.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef STORM_LOG_HPP
|
||||
#define STORM_LOG_HPP
|
||||
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
|
||||
#include "storm/Common.hpp"
|
||||
#include "storm/String.hpp"
|
||||
|
||||
|
||||
enum : uint32_t {
|
||||
SLOG_FLAG_DEFAULT = 0, // Create or open log file with first SLogWrite() call
|
||||
SLOG_FLAG_OPEN_FILE = 1, // Create or open log file with SLogCreate()
|
||||
SLOG_FLAG_NO_FILE = 2, // Don't use log file (use OutputDebugString or console only)
|
||||
SLOG_FLAG_APPEND = 4 // Don't truncate existing log file
|
||||
};
|
||||
|
||||
DECLARE_STRICT_HANDLE(HSLOG);
|
||||
DECLARE_STRICT_HANDLE(HLOCKEDLOG);
|
||||
|
||||
|
||||
void SLogInitialize();
|
||||
int SLogIsInitialized();
|
||||
void SLogDestroy();
|
||||
int SLogCreate(const char* filename, uint32_t flags, HSLOG* log);
|
||||
void SLogClose(HSLOG log);
|
||||
void SLogFlush(HSLOG log);
|
||||
void SLogFlushAll();
|
||||
void SLogGetDefaultDirectory(char* dirname, size_t dirnamesize);
|
||||
void SLogSetDefaultDirectory(const char* dirname);
|
||||
int32_t SLogSetAbsIndent(HSLOG log, int32_t indent);
|
||||
int32_t SLogSetIndent(HSLOG log, int32_t deltaIndent);
|
||||
void SLogVWrite(HSLOG log, const char* format, va_list arglist);
|
||||
void SLogWrite(HSLOG log, const char* format, ...);
|
||||
|
||||
|
||||
#endif
|
||||
51
test/Log.cpp
Normal file
51
test/Log.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "storm/Log.hpp"
|
||||
#include "test/Test.hpp"
|
||||
|
||||
|
||||
TEST_CASE("SLogInitialize", "[log]") {
|
||||
SECTION("constructs correctly") {
|
||||
SLogInitialize();
|
||||
REQUIRE(SLogIsInitialized() == 1);
|
||||
SLogDestroy();
|
||||
}
|
||||
|
||||
SECTION("destructs correctly") {
|
||||
SLogInitialize();
|
||||
SLogDestroy();
|
||||
REQUIRE(SLogIsInitialized() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SLogCreate", "[log]") {
|
||||
SECTION("creates new log handle") {
|
||||
SLogInitialize();
|
||||
|
||||
HSLOG log;
|
||||
REQUIRE(SLogCreate("test.log", SLOG_FLAG_DEFAULT, &log) == 1);
|
||||
REQUIRE(log != 0);
|
||||
|
||||
SLogDestroy();
|
||||
}
|
||||
|
||||
SECTION("creates new log file") {
|
||||
SLogInitialize();
|
||||
|
||||
HSLOG log;
|
||||
REQUIRE(SLogCreate("test.log", SLOG_FLAG_OPEN_FILE, &log) == 1);
|
||||
REQUIRE(log != 0);
|
||||
|
||||
SLogDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SLogWrite", "[log]") {
|
||||
SLogInitialize();
|
||||
|
||||
HSLOG log;
|
||||
REQUIRE(SLogCreate("test.log", SLOG_FLAG_DEFAULT, &log) == 1);
|
||||
REQUIRE(log != 0);
|
||||
|
||||
SLogWrite(log, "SLogWrite Test");
|
||||
|
||||
SLogDestroy();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue