Files
core_zero/tjp/core/log/Util.inl
Timothy Prepscius 996151a56a flatten 20260225
2026-02-25 12:43:06 -05:00

171 lines
3.5 KiB
C++
Executable File

// License: Modified MIT (NON-AI)
// See the LICENSE file in the root directory for license information.
// Copyright 2025 Timothy Prepscius
#pragma once
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <stdio.h>
#include "../algorithm/set_has.hpp"
#include "../algorithm/is_in.hpp"
namespace tjp::core::log::detail {
TJP_CORE_HEADER_ONLY_INLINE
long timeSinceEpochMillisec()
{
using namespace std::chrono;
return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count() % 1000000;
}
TJP_CORE_HEADER_ONLY_INLINE
bool detectIfColorIsAvailable()
{
// is the stdout redirected, if so no color
if (getenv("FORCE_COLOR"))
return true;
if (!isatty(fileno(stdout)))
return false;
const char* term = getenv("TERM");
if (!term)
return false;
// Some terminals support color
std::string_view term_(term);
if (term_ == "dumb")
return false;
return true;
}
using ThreadID = uint64_t;
ThreadID getCurrentThreadID();
TJP_CORE_HEADER_ONLY_INLINE
ThreadID getCurrentThreadID ()
{
#ifdef WIN32
return GetCurrentThreadId();
#else
return (ThreadID)pthread_self();
#endif
}
TJP_CORE_HEADER_ONLY_INLINE
char * GetTimeStamp (char *data, int size, char marker=0)
{
#ifdef WIN32
__time64_t ltime;
_time64( &ltime );
char *timestr = _ctime64(&ltime);
// auto threadID = getCurrentThreadID();
#else
std::time_t t = std::time(nullptr);
char timestr[128];
std::strftime(timestr, size, "%Y%m%d_%H:%M:%S", std::localtime(&t));
// auto threadID = getCurrentThreadID();
#endif
snprintf (data, size, "%s.%06ld", timestr, timeSinceEpochMillisec());
if (marker)
for (auto *c=data; *c; ++c)
if (*c == ':' || *c == '.')
*c = marker;
return data;
}
TJP_CORE_HEADER_ONLY_INLINE
char * __GetLogStamp__ (char *data, bool colorize)
{
char timeStamp[128];
GetTimeStamp(timeStamp, std::size(timeStamp));
auto threadID = getCurrentThreadID();
auto dataSize = 256;
if (colorize)
{
// all of the threadIDs are divisible by 128, so we use 127
auto color = (int)threadID % 127 + 1;
#if defined(SYS_LINUX) || defined(SYS_ANDROID)
snprintf (data, dataSize, "%s \033[38;5;%dm%lx\033[0m | ", timeStamp, color, threadID);
#else
snprintf (data, dataSize, "%s \033[38;5;%dm%llx\033[0m | ", timeStamp, color, threadID);
#endif
}
else
{
#if defined(SYS_LINUX) || defined(SYS_ANDROID)
snprintf (data, dataSize, "%s %lx | ", timeStamp, threadID);
#else
snprintf (data, dataSize, "%s %llx | ", timeStamp, threadID);
#endif
}
return data;
}
TJP_CORE_HEADER_ONLY_INLINE
std::string methodName(const char *prettyFunction_)
{
if (!prettyFunction_)
return "[]";
std::string_view prettyFunction(prettyFunction_);
auto end = prettyFunction.find('(');
if (end == std::string_view::npos)
end = 0;
auto begin = end;
auto stack = 0;
decltype(begin) skipEnd = 0;
decltype(begin) skipBegin = 0;
for (begin = end; begin > 0; begin--)
{
if (prettyFunction[begin] == '>')
{
if (stack == 0)
skipEnd = begin;
stack++;
}
if (prettyFunction[begin] == '<')
{
stack--;
if (stack == 0)
skipBegin = begin;
}
if (prettyFunction[begin] == ' ' && stack == 0)
break;
}
while (begin < end && is_in(prettyFunction[begin], ' ', '&', '*'))
begin = begin+1;
std::string part;
if (skipBegin != skipEnd)
part = std::string(prettyFunction.substr(begin,skipBegin-begin+1)) + std::string(prettyFunction.substr(skipEnd, end-skipEnd));
else
part = prettyFunction.substr(begin,end-begin);
if (part.size() > 30)
return part.substr(part.size() - 30);
return part;
}
} // namespace