Initial commit

This commit is contained in:
2026-04-03 00:22:39 -05:00
commit eca1e8c458
945 changed files with 218160 additions and 0 deletions

306
ZUtil/ZLog.cpp Normal file
View File

@@ -0,0 +1,306 @@
#include <ZUtil/ZLog.hpp>
#include <ZUtil/ZAlloc.hpp>
#include <iostream>
#include <fstream>
#include <stdarg.h>
#include <algorithm>
////////////////////////////////////
/* Static Variable Initialization */
////////////////////////////////////
ZMutex ZLog::LogLock;
bool ZLog::bIsInitialized = false;
ZArray< ZPair<std::ofstream*, bool> > ZLog::LogFiles;
ZArray< ZPtr<ZLogDelegate> > ZLog::Delegates;
ZString ZLog::LogFileRoot;
uint64_t* ZLog::UserTick = NULL;
uint64_t* ZLog::UserUpdate = NULL;
uint64_t ZLog::TickEstimate = 0;
uint64_t ZLog::UpdateFrameEstimate = 0;
///////////////////////////
/* Local Helper Function */
///////////////////////////
void writeHeader(std::ofstream& logfile, const char* filename)
{
logfile << filename << " : ZUtil version " << ZUTIL_VERSION_STRING << " default log file\n\n";
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
logfile << "+------------+------------+\n";
logfile << "| Time (sec) | Update No. |\n";
logfile << "+------------+------------+\n";
#endif
}
void writeFooter(std::ofstream& logfile)
{
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
logfile << "+------------+------------+\n";
#endif
}
int logAssertHandler(const char* _msg, void *_arg)
{
URFP(_arg);
//Log it!
SystemLogError("Assertion Failed: \n");
SystemLogError(_msg);
//Let the error propagate
return 0;
}
/////////////////////////////////
/* Static Function Declaration */
/////////////////////////////////
void ZLog::Init(const ZString& _logFileRoot, const ZString& _defaultLogFile, uint64_t* _ticks /*= NULL*/, uint64_t* _update /*= NULL*/)
{
std::ofstream *logfile;
//Save our root path
ZLog::LogFileRoot = _logFileRoot;
//Create a default log file
ZString logFilePath = ZLog::LogFileRoot + _defaultLogFile;
logfile = znew_notrack std::ofstream();
logfile->open(logFilePath.Data(), std::ios::out);
while (logfile->fail()) {
logFilePath += "_";
logfile->open(logFilePath.Data(), std::ios::out);
}
//Write the header
writeHeader(*logfile, _defaultLogFile.Data());
//Add the default log file to the set
ZLog::LogFiles.Reserve(16);
ZLog::LogFiles.Clear();
ZLog::LogFiles.PushBack(ZPair<std::ofstream*, bool>(logfile, true));
//Set our SST_Assert handlers
SST_OS_SetDebugAssertHandler(logAssertHandler, NULL);
SST_OS_SetRuntimeAssertHandler(logAssertHandler, NULL);
ZLog::UserTick = _ticks;
ZLog::UserUpdate = _update;
//We're ready to rock and roll
ZLog::bIsInitialized = true;
}
void ZLog::Shutdown()
{
ZArray< ZPair<std::ofstream*, bool> >::Iterator itr;
//Iterate and close out
for (itr = ZLog::LogFiles.Begin(); itr != ZLog::LogFiles.End(); itr++)
{
writeFooter(*((*itr).First));
(*itr).First->close();
(*itr).Second = false;
zdelete (*itr).First;
}
//Flush standard outputs
std::cout.flush();
std::cerr.flush();
//Clear our set of log files
ZLog::LogFiles.Clear();
}
void ZLog::AddLoggingDelegate(ZPtr<ZLogDelegate> _delegate)
{
ZLog::LogLock.Acquire();
ZLog::Delegates.PushBack(_delegate);
ZLog::LogLock.Release();
}
ZLogFile ZLog::CreateLogFile(const ZString& _fileName)
{
ZLogFile handle;
std::ofstream *file;
//See if we can early out
if (!ZLog::bIsInitialized)
{
std::cerr << "Attempted to create log file (Before call to Init) : " << _fileName.Data() << std::endl;
return (ZLogFile)0;
}
ZString logFilePath = ZLog::LogFileRoot + _fileName;
//Synchronized Section
{
//Scoped lock
ZLock scopedLock(ZLog::LogLock);
file = znew_notrack std::ofstream();
if (file == NULL)
{
fprintf(stderr, "Failed to create log file %s!\n", _fileName.Data());
return (ZLogFile)0;
}
file->open(logFilePath.Data(), std::ios::out);
if (!file->is_open())
{
//Nope nope nope
fprintf(stderr, "Failed to open log file %s!\n", _fileName.Data());
zdelete file;
return (ZLogFile)0;
}
else
{
//Write the header
writeHeader(*file, _fileName.Data());
//This will give us the index where it will be going
handle = ZLog::LogFiles.Size();
//Add to the set of streams already activated
ZLog::LogFiles.PushBack(ZPair<std::ofstream*, bool>(file, true));
}
}
return handle;
}
void ZLog::Resume( ZLogFile _logFile )
{
//Scoped Lock
ZLock scopedLock(ZLog::LogLock);
ZASSERT_RUNTIME((size_t)_logFile < LogFiles.Size(), "Cannot resume logging to file: file does not exist!");
ZLog::LogFiles[_logFile].Second = true;
}
void ZLog::Suspend( ZLogFile _logFile )
{
//Scoped Lock
ZLock scopedLock(ZLog::LogLock);
ZASSERT_RUNTIME((size_t)_logFile < LogFiles.Size(), "Cannot resume logging to file: file does not exist!");
ZLog::LogFiles[_logFile].Second = false;
}
void ZLog::Printf(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char *_function, const char *_str, ...)
{
URFP(_function);
va_list args;
//Check for easy out
if (!ZLog::bIsInitialized)
return;
//Make sure we're null terminated
char string[32768];
MemSetChar(string, 0, 32768);
va_start(args, _str);
#ifdef _MSC_VER
vsnprintf_s(string, sizeof(string)-1, sizeof(string)-1, _str, args);
#else
vsnprintf(string, sizeof(string)-1, _str, args);
#endif
//Write using our existing write function
ZLog::WriteLine(_type, _file, _ticks, _updateFrame, string);
va_end(args);
}
void ZLog::WriteLine(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char *_str)
{
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
char time[32];
char update[32];
#endif
//See if we can early out (should warn)
if (!ZLog::bIsInitialized)
{
std::cerr << "Logging Output (Before call to Init): " << _str << std::endl;
return;
}
//Synchronized Section
{
//Scoped Lock
ZLock scopedLock(ZLog::LogLock);
ZASSERT_RUNTIME((size_t)_file < LogFiles.Size(), "Cannot log to file: file not created!");
//Get the file and find out if activated
std::ofstream *logfile = ZLog::LogFiles[_file].First;
bool enabled = ZLog::LogFiles[_file].Second;
//If we are not currently enabled, we are no longer needed
if (!enabled)
return;
//Get our best guesses
if (ZLog::UserTick != NULL) {
ZLog::TickEstimate = *ZLog::UserTick;
} else if (_ticks > ZLog::TickEstimate) {
ZLog::TickEstimate = _ticks;
}
if (ZLog::UserUpdate != NULL) {
ZLog::UpdateFrameEstimate = *ZLog::UserUpdate;
} else if (_updateFrame > ZLog::UpdateFrameEstimate) {
ZLog::UpdateFrameEstimate = _updateFrame;
}
ZASSERT_UTIL(logfile != NULL, "ZLog Error: logfile is NULL!");
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
//If we are at detailed (or higher) log level, then log the extra details, then the string
if (_ticks == 0 && _updateFrame == 0 && ZLog::UserTick == NULL && ZLog::UserUpdate == NULL) {
sprintf(time, "?%11.3f", ((float)ZLog::TickEstimate) / 1000.0f);
sprintf(update, "?%11lu", ZLog::UpdateFrameEstimate);
} else {
sprintf(time, "%12.3f", ((float)ZLog::TickEstimate) / 1000.0f);
sprintf(update, "%12lu", ZLog::UpdateFrameEstimate);
}
std::cout << _str << std::endl;
*logfile << "|" << time << "|" << update << "| " << /*ZConcurrency::GetThreadName() << ": " << */_str << std::endl;
#else
std::cout << _str << std::endl;
*logfile << _str << std::endl;
#endif //ZLOG_LEVEL >= ZLOG_LEVEL_DETAILED
//Let the delegates know what happened
for (ZArray< ZPtr<ZLogDelegate> >::Iterator i = ZLog::Delegates.Begin(); i != ZLog::Delegates.End(); i++)
(*i)->Execute(_type, _file, _str);
}
}