legatt 32f4597c4d Base frontend module
- Naming style migrated to camel-case
- P7lib logger sources added
- Vcpkg manifest, CMake presets and build moved to root
- SDL2, Vulkan and RmlUi dependencies added
- Logger LOG macro added
- Logger  configuration
- SDL2 window configuration
- Vulkan configuration
- RmlUi configuration
- SDL event loop
2025-08-08 00:07:32 +03:00

310 lines
10 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// This header file provide functionality to deliver data to file /
////////////////////////////////////////////////////////////////////////////////
#ifndef CLTEXT_H
#define CLTEXT_H
#include "ClTextSink.h"
#include "ClTextConsole.h"
#include "ClTextFile.h"
#include "ClTextSyslog.h"
#include "Formatter.h"
////////////////////////////////////////////////////////////////////////////////
struct sTraceDescEx
: public sTraceDesc
{
tUINT8 *pBuffer;
tUINT32 dwSize;
tXCHAR *pFormat;
sP7Trace_Arg *pArgs;
tUINT32 dwArgsLen;
CFormatter *pFormatter;
sTraceDescEx(const sP7Trace_Format *i_pFormat,
CFormatter::sBuffer *i_pBuffer,
tBOOL i_bBigEndian);
~sTraceDescEx();
};
////////////////////////////////////////////////////////////////////////////////
struct sP7TraceMod
{
eP7Trace_Level eVerbosity;
tXCHAR pName[P7TRACE_MODULE_NAME_LENGTH];
size_t szName;
};
////////////////////////////////////////////////////////////////////////////////
struct sThread
{
tUINT32 dwThreadID; //Thread ID
tUINT64 qwStart; //High resolution timer value start
tUINT64 qwStop; //High resolution timer value stop
tXCHAR pName[P7TRACE_THREAD_NAME_LENGTH]; //Thread name
size_t szName;
};
////////////////////////////////////////////////////////////////////////////////
struct sRbThread
{
sThread *pThread;
sRbThread *pNext;
sRbThread(sThread *i_pThread, sRbThread *i_pNext = NULL)
{
pThread = i_pThread;
pNext = i_pNext;
}
~sRbThread()
{
if (pThread)
{
delete pThread;
pThread = NULL;
}
if (pNext)
{
delete pNext;
pNext = NULL;
}
}
};
////////////////////////////////////////////////////////////////////////////////
class CThreads_Tree:
public CRBTree<sRbThread*, tUINT32>
{
protected:
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey < i_pData::key)
//FALSE - otherwise
tBOOL Is_Key_Less(tUINT32 i_dwKey, sRbThread *i_pData)
{
return (i_dwKey < i_pData->pThread->dwThreadID) ? TRUE : FALSE;
}
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey == i_pData::key)
//FALSE - otherwise
tBOOL Is_Qual(tUINT32 i_dwKey, sRbThread *i_pData)
{
return (i_dwKey == i_pData->pThread->dwThreadID) ? TRUE : FALSE;
}
};
////////////////////////////////////////////////////////////////////////////////
class CTxtChannel
{
protected:
//Contains a 64-bit value representing the number of 100-nanosecond intervals
//since January 1, 1601 (UTC). In windows we use FILETIME structure for
//representing
tUINT64 m_qwStreamTime;
//Hi resolution timer value, we get this value when we retrieve current time.
//using difference between this value and timer value for every trace we can
//calculate time of the trace event with hi resolution
tUINT64 m_qwTimer_Value;
//timer's count heartbeats in second
tUINT64 m_qwTimer_Frequency;
tUINT64 m_qwFlags;
CBList<sTraceDescEx*> m_cDesc;
CBList<sP7TraceMod*> m_cModules;
CThreads_Tree m_cThreads;
tXCHAR *m_pText;
size_t m_szText;
tUINT64 m_qwTimeLast;
tXCHAR m_pName[P7TRACE_NAME_LENGTH];
size_t m_szName;
CFormatter::sBuffer *m_pBuffer;
tBOOL m_bBig_Endian;
//Time conversion for Linux
//http://stackoverflow.com/questions/2408976/struct-timeval-to-printable-format
public:
CTxtChannel(const sP7Trace_Info *i_pInfo, tBOOL i_bBig_Endian);
~CTxtChannel();
void PutFormat(const sP7Trace_Format *i_pDesc);
void PutModule(const sP7Trace_Module *i_pMod);
void RegisterThread(const sP7Trace_Thread_Start *i_pStart);
void UnregisterThread(const sP7Trace_Thread_Stop *i_pStop);
tBOOL Format(sP7Trace_Data* i_pData, CClTextSink::sLog &o_rLog);
};
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// CClText
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class CClText:
public CClient
{
public:
typedef void (*fnFormat)(CClText *i_pClient);
protected:
struct sFormat
{
tXCHAR *pStr;
size_t szStr;
fnFormat pFormat;
sFormat *pNext;
};
struct sBuffer
{
tUINT8 *pBuffer;
size_t szUsed;
sBuffer(size_t i_szBuffer)
{
pBuffer = (tUINT8*)malloc(i_szBuffer);
szUsed = 0;
}
~sBuffer()
{
if (pBuffer)
{
free(pBuffer);
pBuffer = NULL;
}
szUsed = 0;
}
};
private:
tINT32 volatile m_lReject_Mem;
tINT32 volatile m_lReject_Con;
tINT32 volatile m_lReject_Int;
CMEvent m_cEvThread;
tBOOL m_bThread;
CThShell::tTHREAD m_hThread;
CMEvent m_cEvData;
volatile tBOOL m_bNoData;
CBList<sBuffer*> m_cBuffer_Empty;
CBList<sBuffer*> m_cBuffer_Ready;
sBuffer *m_pBuffer_Current;
tUINT32 m_dwBuffer_Size;
tUINT32 m_dwBuffers_Count;
tBOOL m_bBig_Endian;
tUINT8 *m_pChunk;
size_t m_szChunkMax;
size_t m_szChunkUsd;
CTxtChannel *m_pTxtCh[USER_PACKET_CHANNEL_ID_MAX_SIZE];
CClTextSink::sLog m_sLog;
sFormat *m_pFormat;
tXCHAR *m_pMsg;
tXCHAR *m_pMsgCur;
size_t m_szMsg;
CClTextSink *m_pSink;
tBOOL m_bSinkExternal;
public:
CClText(tXCHAR **i_pArgs, tINT32 i_iCount);
virtual ~CClText();
private:
eClient_Status Init_Base(tXCHAR **i_pArgs, tINT32 i_iCount);
eClient_Status Init_Pool(tXCHAR **i_pArgs, tINT32 i_iCount);
eClient_Status Init_Backend(tXCHAR **i_pArgs, tINT32 i_iCount);
eClient_Status Init_Thread(tXCHAR **i_pArgs, tINT32 i_iCount);
eClient_Status ParseFormat(const tXCHAR *i_pFormat);
sFormat *AddFormatNode(const tXCHAR *i_pPrefix,
size_t i_szPrefix,
fnFormat i_pFn);
public:
eClient_Status Sent(tUINT32 i_dwChannel_ID,
sP7C_Data_Chunk *i_pChunks,
tUINT32 i_dwCount,
tUINT32 i_dwSize
);
tBOOL Get_Info(sP7C_Info *o_pInfo);
tBOOL Close();
void Flush();
private:
eClient_Status Parse_Buffer(tUINT8 *i_pBuffer, size_t i_szBuffer);
eClient_Status Parse_Packet(tUINT32 i_dwChannel, tUINT8 *i_pPacket, size_t i_szPacket);
static THSHELL_RET_TYPE THSHELL_CALL_TYPE Static_Routine(void *i_pContext)
{
CClText *l_pRoutine = static_cast<CClText *>(i_pContext);
if (l_pRoutine)
{
l_pRoutine->Routine();
}
CThShell::Cleanup();
return THSHELL_RET_OK;
}
void Routine();
public:
static void FormatChannel(CClText *i_pClient);
static void FormatMessageId(CClText *i_pClient);
static void FormatMessageIndex(CClText *i_pClient);
static void FormatTimeFull(CClText *i_pClient);
static void FormatTimeMedium(CClText *i_pClient);
static void FormatTimeShort(CClText *i_pClient);
static void FormatTimeDiff(CClText *i_pClient);
static void FormatTimeCount(CClText *i_pClient);
static void FormatLevel(CClText *i_pClient);
static void FormatThreadId(CClText *i_pClient);
static void FormatThreadName(CClText *i_pClient);
static void FormatCpuCore(CClText *i_pClient);
static void FormatModuleId(CClText *i_pClient);
static void FormatModuleName(CClText *i_pClient);
static void FormatFilePath(CClText *i_pClient);
static void FormatFileName(CClText *i_pClient);
static void FormatFileLine(CClText *i_pClient);
static void FormatFunction(CClText *i_pClient);
static void FormatMsg(CClText *i_pClient);
};
#endif //CLTEXT_H