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

1337 lines
48 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 of text formatting using var. args. /
////////////////////////////////////////////////////////////////////////////////
#ifndef FORMATTER_H
#define FORMATTER_H
#include <stdint.h>
#define FORMATTER_NO_WIDTH 0
#define FORMATTER_ARG_WIDTH -1
#define FORMATTER_NO_PRECISION 0
#define FORMATTER_ARG_PRECISION -1
#define FORMATTER_MAX_WIDTH 1024
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#if !defined(UINTMAX_MAX)
typedef uint64_t uintmax_t;
#define UINTMAX_MAX 0xffffffffffffffffU
#endif
#if !defined(INTMAX_MAX)
typedef int64_t intmax_t;
#define INTMAX_MIN (-0x7fffffffffffffff - 1)
#define INTMAX_MAX 0x7fffffffffffffff
#endif
#if !defined(min)
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
////////////////////////////////////////////////////////////////////////////////
class CFormatter
{
public:
////////////////////////////////////////////////////////////////////////////
struct sBuffer
{
tINT32 volatile lReference;
tXCHAR *pBuffer;
size_t szBuffer;
////////////////////////////////////////////////////////////////////////
sBuffer(size_t i_szBuffer)
: lReference(1)
, pBuffer(NULL)
, szBuffer(i_szBuffer)
{
if (szBuffer)
{
szBuffer = 256;
}
pBuffer = (tXCHAR*)malloc(szBuffer * sizeof(tXCHAR));
}
////////////////////////////////////////////////////////////////////////
tBOOL Realloc(size_t i_szSize)
{
tXCHAR *l_pTmp = (tXCHAR*)realloc(pBuffer, i_szSize * sizeof(tXCHAR));
if (l_pTmp)
{
pBuffer = l_pTmp;
szBuffer = i_szSize;
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////
virtual tINT32 Add_Ref()
{
return ATOMIC_INC(&lReference);
}
////////////////////////////////////////////////////////////////////////
virtual tINT32 Release()
{
tINT32 l_lResult = ATOMIC_DEC(&lReference);
if ( 0 >= l_lResult )
{
delete this;
}
return l_lResult;
}
protected:
////////////////////////////////////////////////////////////////////////
virtual ~sBuffer()
{
if (pBuffer)
{
free(pBuffer);
pBuffer = NULL;
}
szBuffer = 0;
}
};//struct sBuffer
protected:
union uValue
{
tINT8 i8;
tUINT8 u8;
tINT16 i16;
tUINT16 u16;
tINT32 i32;
tUINT32 u32;
tINT64 i64;
tUINT64 u64;
intmax_t iMax;
uintmax_t uMax;
tDOUBLE d64;
tUINT8 pData[32];
};
enum eSize
{
eSize32,
eSize64,
eSizehh,
eSizeh,
eSizew,
eSizeL,
eSizell,
eSizel,
eSizeI,
eSizez,
eSizej,
eSizet,
eSizeUnk
};
enum eType
{
eTypeDouble,
eTypeString,
eTypeChar,
eTypeIntDec,
eTypeUintDec,
eTypeUintHex,
eTypeUintHEX,
eTypeUintOct,
eTypePointer,
eTypeUintBin,
eTypeNone,
eTypeMax
};
////////////////////////////////////////////////////////////////////////////
struct sArg
{
tBOOL bFlagLeftAlign;
tBOOL bFlagSign;
tBOOL bFlagGrid;
tXCHAR cPadding;
tXCHAR *pPrefix;
size_t szPrefix;
CFormatter::eSize eSize;
CFormatter::eType eType;
tINT32 iWidth; //0 - no width, -1 - use argument to specify width
tINT32 iPrecision; //-2 no precision, -1 - use argument to specify precision
tXCHAR *pDouble; //format string for double
sArg *pNext;
////////////////////////////////////////////////////////////////////////
sArg()
{
bFlagLeftAlign = bFlagSign = bFlagGrid = FALSE;
cPadding = TM(' ');
pPrefix = NULL;
szPrefix = 0;
eSize = eSizeUnk;
eType = eTypeNone;
iWidth = FORMATTER_NO_WIDTH;
iPrecision = FORMATTER_NO_PRECISION;
pDouble = NULL;
pNext = NULL;
}
////////////////////////////////////////////////////////////////////////
~sArg()
{
if (pPrefix)
{
free(pPrefix);
pPrefix = NULL;
}
if (pDouble)
{
free(pDouble);
pDouble = NULL;
}
if (pNext)
{
delete pNext;
pNext = NULL;
}
}
};//sArg
sArg *m_pArgHead;
sBuffer *m_pBuffer;
sP7Trace_Arg *m_pArgs;
size_t m_szArgs;
tBOOL m_bError;
tBOOL m_bLittleEndian;
public:
////////////////////////////////////////////////////////////////////////////
//CFormatter
CFormatter(const tXCHAR *i_pFormat,
sP7Trace_Arg *i_pArgs,
size_t i_szArgs,
CFormatter::sBuffer *i_pBuffer = NULL
)
: m_pArgHead(NULL)
, m_pBuffer(i_pBuffer)
, m_pArgs(i_pArgs)
, m_szArgs(i_szArgs)
, m_bError(FALSE)
, m_bLittleEndian(TRUE)
{
const tXCHAR *l_pCursor = i_pFormat;
const tXCHAR *l_pHead = i_pFormat;
const tXCHAR *l_pPercent = i_pFormat;
sArg *l_pTail = NULL;
sArg *l_pArg = NULL;
size_t l_szArgs = 0;
if (!m_pBuffer)
{
m_pBuffer = new sBuffer(1024);
}
else
{
m_pBuffer->Add_Ref();
}
while (*l_pCursor)
{
if (TM('%') == *l_pCursor)
{
l_pCursor++;
if (TM('%') != *l_pCursor)
{
l_pPercent = l_pCursor - 1;
l_pArg = AddArg(l_pHead, (size_t)(l_pCursor - l_pHead - 1));
}
}
if (l_pArg)
{
///////////////////////////////////////////////////////////////
//Flags
while (1) //check flags
{
if (TM('+') == *l_pCursor)
{
l_pArg->bFlagSign = TRUE;
l_pCursor++;
}
else if (TM('-') == *l_pCursor)
{
l_pArg->bFlagLeftAlign = TRUE;
l_pCursor++;
}
else if (TM(' ') == *l_pCursor)
{
l_pCursor++;
}
else if (TM('#') == *l_pCursor)
{
l_pArg->bFlagGrid = TRUE;
l_pCursor++;
}
else if (TM('0') == *l_pCursor)
{
l_pArg->cPadding = TM('0');
l_pCursor++;
}
else if (TM('\'') == *l_pCursor)
{
//ignored for a while
}
else
{
break;
}
}
///////////////////////////////////////////////////////////////
//width
tINT32 l_iWidth = 0;
if (TM('*') == *l_pCursor)
{
l_iWidth = FORMATTER_ARG_WIDTH;
l_pCursor ++;
}
else while ( (TM('0') <= *l_pCursor)
&& (TM('9') >= *l_pCursor)
)
{
l_iWidth = l_iWidth * 10 + ((*l_pCursor) - TM('0'));
l_pCursor++;
}
if (0 != l_iWidth)
{
l_pArg->iWidth = l_iWidth;
}
///////////////////////////////////////////////////////////////
//precision
if (TM('.') == *l_pCursor)
{
l_pCursor ++;
if (TM('*') == *l_pCursor)
{
l_pArg->iPrecision = FORMATTER_ARG_PRECISION;
l_pCursor ++;
}
else
{
tINT32 l_iPrecision = 0;
while ( (TM('0') <= *l_pCursor)
&& (TM('9') >= *l_pCursor)
)
{
l_iPrecision = l_iPrecision * 10 + ((*l_pCursor) - TM('0'));
l_pCursor++;
}
if (l_iPrecision)
{
l_pArg->iPrecision = l_iPrecision;
}
}
}
///////////////////////////////////////////////////////////////
//size
l_pArg->eSize = GetSize(l_pCursor);
///////////////////////////////////////////////////////////////
//type
tBOOL l_bFound = FALSE;
if ( (TM('d') == *l_pCursor)
|| (TM('i') == *l_pCursor)
)
{
l_pArg->eType = eTypeIntDec;
l_bFound = TRUE;
}
else if (TM('x') == *l_pCursor)
{
l_pArg->eType = eTypeUintHex;
l_bFound = TRUE;
}
else if (TM('X') == *l_pCursor)
{
l_pArg->eType = eTypeUintHEX;
l_bFound = TRUE;
}
else if (TM('u') == *l_pCursor)
{
l_pArg->eType = eTypeUintDec;
l_bFound = TRUE;
}
else if ( (TM('c') == *l_pCursor)
|| (TM('C') == *l_pCursor)
)
{
l_pArg->eType = eTypeChar;
l_bFound = TRUE;
}
else if ( (TM('s') == *l_pCursor)
|| (TM('S') == *l_pCursor)
)
{
l_pArg->eType = eTypeString;
l_bFound = TRUE;
}
else if (TM('b') == *l_pCursor)
{
l_pArg->eType = eTypeUintBin;
l_bFound = TRUE;
}
else if ( (TM('a') == *l_pCursor)
|| (TM('A') == *l_pCursor)
|| (TM('f') == *l_pCursor)
|| (TM('e') == *l_pCursor)
|| (TM('E') == *l_pCursor)
|| (TM('g') == *l_pCursor)
|| (TM('G') == *l_pCursor)
)
{
size_t l_szLength = (size_t)(l_pCursor - l_pPercent + 2);
l_pArg->pDouble = (tXCHAR*)malloc(l_szLength * sizeof(tXCHAR));
if (l_pArg->pDouble)
{
memcpy(l_pArg->pDouble, l_pPercent, (l_szLength - 1) * sizeof(tXCHAR));
l_pArg->pDouble[l_szLength - 1] = 0;
}
l_bFound = TRUE;
l_pArg->eType = eTypeDouble;
}
else if (TM('o') == *l_pCursor)
{
l_pArg->eType = eTypeUintOct;
l_bFound = TRUE;
}
else if (TM('p') == *l_pCursor)//(TM('n') == *l_pCursor) ->>Ignored, not supported
{
l_pArg->bFlagGrid = TRUE;
l_pArg->eType = eTypePointer;
l_bFound = TRUE;
}
if (l_bFound)
{
l_szArgs ++;
if (FORMATTER_ARG_PRECISION == l_pArg->iPrecision) l_szArgs ++;
if (FORMATTER_ARG_WIDTH == l_pArg->iWidth) l_szArgs ++;
l_pHead = l_pCursor + 1;
if (!l_pTail)
{
m_pArgHead = l_pArg;
}
else
{
l_pTail->pNext = l_pArg;
}
l_pTail = l_pArg;
l_pCursor++;
}
else if (l_pArg)
{
delete l_pArg;
}
l_pArg = NULL;
}//if (l_pArg)
else
{
l_pCursor++;
}
}
if (l_pArg)
{
delete l_pArg;
l_pArg = NULL;
}
if (l_pCursor != l_pHead)
{
l_pArg = AddArg(l_pHead, (size_t)(l_pCursor - l_pHead));
if (!l_pTail)
{
m_pArgHead = l_pArg;
}
else
{
l_pTail->pNext = l_pArg;
}
}
if (l_szArgs != m_szArgs)
{
m_bError = TRUE;
}
}//CFormatter
////////////////////////////////////////////////////////////////////////////
//~CFormatter
virtual ~CFormatter()
{
if (m_pArgHead)
{
delete m_pArgHead;
m_pArgHead = NULL;
}
if (m_pBuffer)
{
m_pBuffer->Release();
m_pBuffer = NULL;
}
m_pArgs = NULL;
m_szArgs = 0;
}//~CFormatter
////////////////////////////////////////////////////////////////////////////
//EnableBigEndian
void EnableBigEndian()
{
m_bLittleEndian = FALSE;
}
#define FORMAT_SIGN\
if (l_bMinus) {*l_pIter++ = TM('-');}\
else if (l_pArg->bFlagSign) {*l_pIter++ = TM('+');}\
#define FORMAT_X_PREFIX\
if (l_pArg->bFlagGrid) {*l_pIter++ = TM('0'); *l_pIter++ = TM('x');}\
#define FORMAT_0_PREFIX\
if (l_pArg->bFlagGrid) {*l_pIter++ = TM('0');}\
#define FORMAT_B_PREFIX\
if (l_pArg->bFlagGrid) {*l_pIter++ = TM('b');}\
#define FORMAT_NO_SIGN
#define FORMAT_NO_PREFIX
#define FORMAT_DIGIT(i_uBase, i_pDigits, SIGN_MACRO, PREFIX_MACRO)\
l_pDigit = m_pBuffer->pBuffer + m_pBuffer->szBuffer - 1;\
l_pTail = l_pDigit;\
*l_pDigit = TM('0');\
if (l_uValue.uMax) l_pDigit++;\
while(l_uValue.uMax)\
{\
*(--l_pDigit) = *(i_pDigits + (size_t)(l_uValue.uMax % i_uBase));\
l_uValue.uMax /= i_uBase;\
}\
l_szAdd = (size_t)(l_pTail - l_pDigit + 1);\
l_iPrecision -= (tINT32)l_szAdd;\
l_iWidth -= (tINT32)l_szAdd;\
if (0 < l_iPrecision) l_iWidth -= l_iPrecision;\
if (0 < l_iWidth) l_szAdd += l_iWidth;\
if (0 < l_iPrecision) l_szAdd += l_iPrecision;\
if ((l_szReturn + l_szAdd + 8) >= i_szBuffer)\
{\
l_bError = TRUE;\
break;\
}\
l_pIter = o_pBuffer + l_szReturn;\
if (FALSE == l_pArg->bFlagLeftAlign)\
{\
if (TM(' ') == l_pArg->cPadding)\
{\
while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding; \
}\
SIGN_MACRO\
PREFIX_MACRO\
if (TM('0') == l_pArg->cPadding)\
{\
while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding; \
}\
while (0 < l_iPrecision--) *l_pIter++ = TM('0'); \
l_szAdd = (size_t)(l_pTail - l_pDigit + 1);\
memcpy(l_pIter, l_pDigit, sizeof(tXCHAR) * l_szAdd);\
l_pIter += l_szAdd;\
}\
else\
{\
SIGN_MACRO\
PREFIX_MACRO\
while (0 < l_iPrecision--) *l_pIter++ = TM('0'); \
if (TM('0') == l_pArg->cPadding)\
{\
while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding; \
}\
l_szAdd = (size_t)(l_pTail - l_pDigit + 1);\
memcpy(l_pIter, l_pDigit, sizeof(tXCHAR) * l_szAdd);\
l_pIter += l_szAdd;\
if (TM(' ') == l_pArg->cPadding)\
{\
while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding; \
}\
}\
l_szReturn = (size_t)(l_pIter - o_pBuffer);\
//#define FORMAT_DIGIT
#define COPY_STR(SRC_TYPE, DST_TYPE)\
l_pIter = o_pBuffer + l_szReturn;\
l_pTail = o_pBuffer + i_szBuffer - 4;\
l_iReturn = 0;\
while (*(SRC_TYPE*)i_pValues)\
{\
if ((l_pTail - l_pIter) > 2)\
{\
*l_pIter++ = (DST_TYPE)*(SRC_TYPE*)i_pValues; \
l_iReturn++;\
}\
else\
{\
l_iReturn = -1;\
break;\
}\
i_pValues += sizeof(SRC_TYPE);\
}\
i_pValues += sizeof(SRC_TYPE);\
//#define COPY_STR
#define COPY_ARG(DstVar, SrcSignificantSize, SrcTotalSize)\
if (m_bLittleEndian)\
{\
memcpy(&(DstVar), i_pValues, min((SrcSignificantSize), (SrcTotalSize)));\
}\
else\
{\
memcpy(((tUINT8*)&(DstVar)) + (sizeof(DstVar) - (SrcSignificantSize)), \
i_pValues + ((SrcTotalSize) - (SrcSignificantSize)), \
SrcSignificantSize\
);\
}\
//#define COPY_ARG
////////////////////////////////////////////////////////////////////////////
//Format
tINT32 Format(tXCHAR *o_pBuffer,
size_t i_szBuffer,
const tUINT8 *i_pValues
)
{
const static tXCHAR g_pHEX[] = TM("0123456789ABCDEF");
const static tXCHAR g_pHex[] = TM("0123456789abcdef");
const static size_t g_pSize[P7TRACE_ARGS_COUNT] = {0, //P7TRACE_ARG_TYPE_UNK
1, //P7TRACE_ARG_TYPE_CHAR, P7TRACE_ARG_TYPE_INT8
2, //P7TRACE_ARG_TYPE_CHAR16
2, //P7TRACE_ARG_TYPE_INT16
4, //P7TRACE_ARG_TYPE_INT32
8, //P7TRACE_ARG_TYPE_INT64
8, //P7TRACE_ARG_TYPE_DOUBLE
0, //P7TRACE_ARG_TYPE_PVOID
0, //P7TRACE_ARG_TYPE_USTR16
0, //P7TRACE_ARG_TYPE_STRA
0, //P7TRACE_ARG_TYPE_USTR8
0, //P7TRACE_ARG_TYPE_USTR32
4, //P7TRACE_ARG_TYPE_CHAR32
sizeof(uintmax_t), //P7TRACE_ARG_TYPE_INTMAX
};
sP7Trace_Arg *l_pP7Args = m_pArgs;
size_t l_szReturn = 0;
tBOOL l_bError = FALSE;
sArg *l_pArg = m_pArgHead;
tINT32 l_iWidth;
tINT32 l_iPrecision;
uValue l_uValue;
tXCHAR *l_pDigit;
tXCHAR *l_pTail;
tXCHAR *l_pIter;
size_t l_szAdd;
if (m_bError)
{
return PSPrint(o_pBuffer, i_szBuffer, TM("Format string error"));
}
while(l_pArg)
{
//Copy text prefix
if (l_pArg->pPrefix)
{
if ((l_szReturn + l_pArg->szPrefix) < i_szBuffer)
{
memcpy(o_pBuffer + l_szReturn, l_pArg->pPrefix, l_pArg->szPrefix * sizeof(tXCHAR));
l_szReturn += l_pArg->szPrefix;
}
else
{
l_bError = TRUE;
break;
}
}
//Retrieving width and precision
l_iWidth = l_pArg->iWidth;
l_iPrecision = l_pArg->iPrecision;
if (FORMATTER_ARG_WIDTH == l_iWidth)
{
COPY_ARG(l_iWidth, sizeof(tINT32), l_pP7Args->bSize);
i_pValues += l_pP7Args->bSize;
l_pP7Args ++;
if (0 > l_iWidth)
{ l_iWidth = 0; }
else if (FORMATTER_MAX_WIDTH < l_iWidth)
{ l_iWidth = FORMATTER_MAX_WIDTH;}
}
if (FORMATTER_ARG_PRECISION == l_iPrecision)
{
COPY_ARG(l_iPrecision, sizeof(tINT32), l_pP7Args->bSize);
i_pValues += l_pP7Args->bSize;
l_pP7Args ++;
if (0 > l_iPrecision)
{ l_iPrecision = 0; }
else if (FORMATTER_MAX_WIDTH < l_iPrecision)
{ l_iPrecision = FORMATTER_MAX_WIDTH;}
}
if (eTypeIntDec == l_pArg->eType)
{
tBOOL l_bMinus = FALSE;
if (P7TRACE_ARG_TYPE_INT32 == l_pP7Args->bType)
{
tINT32 l_iVal = 0;
COPY_ARG(l_iVal, sizeof(tINT32), l_pP7Args->bSize);
l_uValue.iMax = l_iVal;
}
else if (P7TRACE_ARG_TYPE_INT64 == l_pP7Args->bType)
{
tINT64 l_iVal = 0ll;
COPY_ARG(l_iVal, sizeof(tINT64), l_pP7Args->bSize);
l_uValue.iMax = l_iVal;
}
else if (P7TRACE_ARG_TYPE_INT16 == l_pP7Args->bType)
{
tINT16 l_iVal = 0;
COPY_ARG(l_iVal, sizeof(tINT16), l_pP7Args->bSize);
l_uValue.iMax = l_iVal;
}
else if (P7TRACE_ARG_TYPE_INT8 == l_pP7Args->bType)
{
tINT8 l_iVal = 0;
COPY_ARG(l_iVal, sizeof(tINT8), l_pP7Args->bSize);
l_uValue.iMax = l_iVal;
}
else //if (P7TRACE_ARG_TYPE_INTMAX == l_pP7Args->bType)
{
intmax_t l_iVal = 0ll;
memcpy(&l_iVal, i_pValues, min(g_pSize[l_pP7Args->bType], l_pP7Args->bSize));
l_uValue.iMax = l_iVal;
}
if (0 > l_uValue.iMax)
{
l_bMinus = TRUE;
l_iWidth --;
l_uValue.iMax = -l_uValue.iMax;
}
if (l_pArg->bFlagSign) l_iWidth --;
FORMAT_DIGIT(10ull, g_pHEX, FORMAT_SIGN, FORMAT_NO_PREFIX);
}
else if (eTypeUintDec == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
FORMAT_DIGIT(10ull, g_pHEX, FORMAT_NO_SIGN, FORMAT_NO_PREFIX);
}
else if (eTypeUintHex == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
if (l_pArg->bFlagGrid) {l_iWidth -=2;} //0x
FORMAT_DIGIT(16ull, g_pHex, FORMAT_NO_SIGN, FORMAT_X_PREFIX);
}
else if (eTypeUintHEX == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
if (l_pArg->bFlagGrid) {l_iWidth -=2;} //0x
FORMAT_DIGIT(16ull, g_pHEX, FORMAT_NO_SIGN, FORMAT_X_PREFIX);
//Code snippet for test
//l_pDigit = m_pBuffer->pBuffer + m_pBuffer->szBuffer - 1;
//l_pTail = l_pDigit;
//*l_pDigit = TM('0');
//
//if (l_uValue.uMax) l_pDigit++;
//while(l_uValue.uMax)
//{
// *(--l_pDigit) =*(g_pHEX + (size_t)(l_uValue.uMax % 16));
// l_uValue.uMax /= 16;
//}
//
//l_szAdd = (size_t)(l_pTail - l_pDigit + 1);
//l_iPrecision -= (tINT32)l_szAdd;
//l_iWidth -= (tINT32)l_szAdd;
//if (0 < l_iPrecision) l_iWidth -= l_iPrecision;
//
//if (0 < l_iWidth) l_szAdd += l_iWidth;
//if (0 < l_iPrecision) l_szAdd += l_iPrecision;
//
//if ((l_szReturn + l_szAdd + 1) >= i_szBuffer)
//{
// l_bError = TRUE;
// break;
//}
//
//l_pIter = o_pBuffer + l_szReturn;
//
//if (FALSE == l_pArg->bFlagLeftAlign)
//{
// if (TM(' ') == l_pArg->cPadding)
// {
// while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding;
// }
//
// //if (l_bMinus) {*l_pIter++ = TM('-'); l_iWidth --;}
// //else if (l_pArg->bFlagSign) {*l_pIter++ = TM('+'); l_iWidth --;}
// if (l_pArg->bFlagGrid) {*l_pIter++ = TM('0'); *l_pIter++ = TM('x');}
//
// if (TM('0') == l_pArg->cPadding)
// {
// while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding;
// }
// while (0 < l_iPrecision--) *l_pIter++ = TM('0');
//
// l_szAdd = (size_t)(l_pTail - l_pDigit + 1);
// memcpy(l_pIter, l_pDigit, sizeof(tXCHAR) * l_szAdd);
// l_pIter += l_szAdd;
//}
//else
//{
// //if (l_bMinus) {*l_pIter++ = TM('-'); l_iWidth --;}
// //else if (l_pArg->bFlagSign) {*l_pIter++ = TM('+'); l_iWidth --;}
// if (l_pArg->bFlagGrid) {*l_pIter++ = TM('0'); *l_pIter++ = TM('x');}
//
// while (0 < l_iPrecision--) *l_pIter++ = TM('0');
//
// if (TM('0') == l_pArg->cPadding)
// {
// while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding;
// }
//
// l_szAdd = (size_t)(l_pTail - l_pDigit + 1);
// memcpy(l_pIter, l_pDigit, sizeof(tXCHAR) * l_szAdd);
// l_pIter += l_szAdd;
//
// if (TM(' ') == l_pArg->cPadding)
// {
// while (0 < l_iWidth--) *l_pIter++ = l_pArg->cPadding;
// }
//}
//
//l_szReturn = (size_t)(l_pIter - o_pBuffer);
}
else if (eTypeUintBin == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
if (l_pArg->bFlagGrid) {l_iWidth --;}//b
FORMAT_DIGIT(2ull, g_pHEX, FORMAT_NO_SIGN, FORMAT_B_PREFIX);
}
else if (eTypeString == l_pArg->eType)
{
tINT32 l_iReturn = -1;
if (P7TRACE_ARG_TYPE_USTR16 == l_pP7Args->bType)
{
#ifdef UTF8_ENCODING
l_iReturn = Convert_UTF16_To_UTF8((tWCHAR*)i_pValues,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
//move var_arg pointer
while (*(tWCHAR*)i_pValues) i_pValues += sizeof(tWCHAR);
i_pValues += sizeof(tWCHAR);
#else //UTF-16
COPY_STR(tWCHAR, tWCHAR);
#endif
}
else if (P7TRACE_ARG_TYPE_STRA == l_pP7Args->bType)
{
COPY_STR(tACHAR, tXCHAR);
}
else if (P7TRACE_ARG_TYPE_USTR8 == l_pP7Args->bType)
{
#ifdef UTF8_ENCODING
COPY_STR(tACHAR, tXCHAR);
#else
l_iReturn = Convert_UTF8_To_UTF16((tACHAR*)i_pValues,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
//move var_arg pointer
while (*(tACHAR*)i_pValues) i_pValues += sizeof(tACHAR);
i_pValues += sizeof(tACHAR);
#endif
}
else if (P7TRACE_ARG_TYPE_USTR32 == l_pP7Args->bType)
{
#ifdef UTF8_ENCODING
l_iReturn = Convert_UTF32_To_UTF8((tUINT32*)i_pValues,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
#else
l_iReturn = Convert_UTF32_To_UTF16((tUINT32*)i_pValues,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
#endif
//move var_arg pointer
while (*(tUINT32*)i_pValues) i_pValues += sizeof(tUINT32);
i_pValues += sizeof(tUINT32);
}
if ( (l_iReturn >= 0) && ((size_t)(l_iReturn + 8) < (i_szBuffer - l_szReturn)) )
{ l_szReturn += (size_t)l_iReturn; }
else { l_bError = TRUE; break; }
}
else if (eTypeChar == l_pArg->eType)
{
//7 bytes max for UTF-8 + zero
if ((i_szBuffer - l_szReturn) < 7) {l_bError = TRUE; break;}
if (P7TRACE_ARG_TYPE_CHAR == l_pP7Args->bType)
{
tINT8 l_iVal = 0;
COPY_ARG(l_iVal, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
*(o_pBuffer + l_szReturn++) = l_iVal;
}
else if (P7TRACE_ARG_TYPE_CHAR16 == l_pP7Args->bType)
{
tINT16 l_iVal = 0;
COPY_ARG(l_iVal, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
#ifdef UTF8_ENCODING
tWCHAR l_pWstr[2] = {(tWCHAR)l_iVal, 0};
l_szReturn += (size_t)Convert_UTF16_To_UTF8((tWCHAR*)l_pWstr,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
#else
*(o_pBuffer + l_szReturn++) = l_iVal;
#endif
}
else if (P7TRACE_ARG_TYPE_CHAR32 == l_pP7Args->bType)
{
tUINT32 l_pVal[2] = {0, 0};
COPY_ARG(l_pVal[0], g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
#ifdef UTF8_ENCODING
l_szReturn += (size_t)Convert_UTF32_To_UTF8((tUINT32*)l_pVal,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
#else
l_szReturn += (size_t)Convert_UTF32_To_UTF16((tUINT32*)l_pVal,
o_pBuffer + l_szReturn,
(tUINT32)(i_szBuffer - l_szReturn)
);
#endif
}
}
else if (eTypePointer == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, l_pP7Args->bSize, l_pP7Args->bSize);
l_iWidth -=2; //0x
FORMAT_DIGIT(16ull, g_pHEX, FORMAT_NO_SIGN, FORMAT_X_PREFIX);
}
else if (eTypeDouble == l_pArg->eType)
{
tINT32 l_iCount;
memcpy(&l_uValue.d64, i_pValues, l_pP7Args->bSize);
if ( (FORMATTER_ARG_WIDTH == l_pArg->iWidth)
&& (FORMATTER_ARG_PRECISION == l_pArg->iPrecision)
)
{
l_iCount = PSPrint(o_pBuffer + l_szReturn,
i_szBuffer - l_szReturn,
l_pArg->pDouble,
l_iWidth,
l_iPrecision,
l_uValue.d64
);
}
else if (FORMATTER_ARG_PRECISION == l_pArg->iPrecision)
{
l_iCount = PSPrint(o_pBuffer + l_szReturn,
i_szBuffer - l_szReturn,
l_pArg->pDouble,
l_iPrecision,
l_uValue.d64
);
}
else if (FORMATTER_ARG_WIDTH == l_pArg->iPrecision)
{
l_iCount = PSPrint(o_pBuffer + l_szReturn,
i_szBuffer - l_szReturn,
l_pArg->pDouble,
l_iWidth,
l_uValue.d64
);
}
else
{
l_iCount = PSPrint(o_pBuffer + l_szReturn,
i_szBuffer - l_szReturn,
l_pArg->pDouble,
l_uValue.d64
);
}
if (0 < l_iCount)
{
l_szReturn += (size_t)l_iCount;
}
else
{
l_bError = TRUE;
break;
}
}
else if (eTypeUintOct == l_pArg->eType)
{
l_uValue.uMax = 0ull;
COPY_ARG(l_uValue.uMax, g_pSize[l_pP7Args->bType], l_pP7Args->bSize);
if (l_pArg->bFlagGrid) {l_iWidth --;}//0
FORMAT_DIGIT(8ull, g_pHEX, FORMAT_NO_SIGN, FORMAT_0_PREFIX);
}
l_pArg = l_pArg->pNext;
i_pValues += l_pP7Args->bSize; //for strings it is 0
l_pP7Args ++;
} //while(l_pArg)
if (l_szReturn < i_szBuffer)
{
o_pBuffer[l_szReturn] = 0;
}
return (!l_bError) ? (tINT32)l_szReturn : -1;
}//Format
////////////////////////////////////////////////////////////////////////////
//Print - test function, print format string back to buffer
// tBOOL Print(tXCHAR *o_pBuffer, size_t i_szBuffer)
// {
// size_t l_szOffs = 0;
// sArg *l_pArg = m_pArgHead;
// tBOOL l_bReturn = TRUE;
// size_t l_szDouble = 0;
//
// while (l_pArg)
// {
// l_szDouble = (l_pArg->pDouble) ? PStrLen(l_pArg->pDouble) : 0;
//
// if ((i_szBuffer - l_szOffs) < (l_pArg->szPrefix + l_szDouble + 64))
// {
// l_bReturn = FALSE;
// break;
// }
//
// if (l_pArg->pPrefix)
// {
// memcpy(o_pBuffer + l_szOffs, l_pArg->pPrefix, l_pArg->szPrefix * sizeof(tXCHAR));
// l_szOffs += l_pArg->szPrefix;
// }
//
// if (eTypeDouble == l_pArg->eType)
// {
// if (l_szDouble)
// {
// PStrCpy(o_pBuffer + l_szOffs, i_szBuffer-l_szOffs, l_pArg->pDouble);
// l_szOffs += l_szDouble;
// }
// else
// {
// l_bReturn = FALSE;
// break;
// }
// }
// else if (eTypeNone != l_pArg->eType)
// {
// o_pBuffer[l_szOffs++] = TM('%');
//
// if (l_pArg->bFlagSign) { o_pBuffer[l_szOffs++] = TM('+'); }
// if (l_pArg->bFlagLeftAlign) { o_pBuffer[l_szOffs++] = TM('-'); }
// if (l_pArg->bFlagBlankPrefix) { o_pBuffer[l_szOffs++] = TM(' '); }
// if (l_pArg->bFlagGrid) { o_pBuffer[l_szOffs++] = TM('#'); }
// if (l_pArg->bFlagZeroPrefix) { o_pBuffer[l_szOffs++] = TM('0'); }
//
// if (FORMATTER_NO_WIDTH == l_pArg->iWidth) {}
// else if (FORMATTER_ARG_WIDTH == l_pArg->iWidth) { o_pBuffer[l_szOffs++] = TM('*'); }
// else { l_szOffs += PSPrint(o_pBuffer + l_szOffs, i_szBuffer-l_szOffs, TM("%d"), l_pArg->iWidth);}
//
// if (FORMATTER_NO_PRECISION == l_pArg->iPrecision)
// {
// }
// else
// {
// o_pBuffer[l_szOffs++] = TM('.');
// if (FORMATTER_ARG_PRECISION == l_pArg->iPrecision) { o_pBuffer[l_szOffs++] = TM('*'); }
// else if (FORMATTER_SKIP_PRECISION == l_pArg->iPrecision) { o_pBuffer[l_szOffs++] = TM('0'); }
// else { l_szOffs += PSPrint(o_pBuffer + l_szOffs, i_szBuffer-l_szOffs, TM("%d"), l_pArg->iPrecision);}
// }
//
// if (eSizehh == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('h');
// o_pBuffer[l_szOffs++] = TM('h');
// }
// else if (eSizell == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('l');
// o_pBuffer[l_szOffs++] = TM('l');
// }
// else if (eSizeh == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('h');
// }
// else if (eSizel == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('l');
// }
// else if (eSizeI == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('I');
// }
// else if (eSizez == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('z');
// }
// else if (eSize32 == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('I');
// o_pBuffer[l_szOffs++] = TM('3');
// o_pBuffer[l_szOffs++] = TM('2');
// }
// else if (eSize64 == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('I');
// o_pBuffer[l_szOffs++] = TM('6');
// o_pBuffer[l_szOffs++] = TM('4');
// }
// else if (eSizet == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('t');
// }
// else if (eSizeL == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('L');
// }
// else if (eSizew == l_pArg->eSize)
// {
// o_pBuffer[l_szOffs++] = TM('w');
// }
//
// if (eTypeStringH == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('s');}
// else if (eTypeStringW == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('S');}
// else if (eTypeInt_d == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('d');}
// else if (eTypeInt_u == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('u');}
// else if (eTypeInt_i == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('i');}
// else if (eTypeInt_x == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('x');}
// else if (eTypeInt_X == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('X');}
// else if (eTypeInt_o == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('o');}
// else if (eTypeInt_b == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('b');}
// else if (eTypeInt_p == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('p');}
// else if (eTypeInt_n == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('n');}
// else if (eTypeInt_c == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('c');}
// else if (eTypeInt_C == l_pArg->eType) {o_pBuffer[l_szOffs++] = TM('C');}
// }
//
// l_pArg = l_pArg->pNext;
// }
//
// if (l_bReturn)
// {
// o_pBuffer[l_szOffs] = 0;
// }
//
// return l_bReturn;
// }
////////////////////////////////////////////////////////////////////////////
//TestScan - test function
/*
static tBOOL TestScan()
{
tXCHAR l_pBuffer[8192];
CFormatter *l_pFormatter = NULL;
const tXCHAR *l_pPattern = NULL;
const tXCHAR *l_pError = NULL;
#define COMPARE_PATTERN(i_pFormat, i_pPattern)\
if (l_pFormatter)\
{\
delete l_pFormatter;\
}\
l_pFormatter = new CFormatter(TM(i_pFormat), NULL, 0, NULL);\
l_pPattern = TM(i_pPattern);\
if ( (!l_pFormatter->Print(l_pBuffer, 8192))\
|| (0 != PStrCmp(l_pBuffer, l_pPattern))\
)\
{\
l_pError = l_pPattern;\
goto l_blExit;\
}\
COMPARE_PATTERN("%%1 %I32d %%2 %I64d %%3 %hhd %%4 %wd %%5 %Ld %%6 %lld %%7 %ld %%8 %Id %%9 %zd %%10 %td",
"%1 %I32d %2 %I64d %3 %hhd %4 %wd %5 %Ld %6 %lld %7 %ld %8 %Id %9 %zd %10 %td"
);
COMPARE_PATTERN("%+- #0*lld", "%+- #0*lld");
COMPARE_PATTERN("%+- #0123lld", "%+- #0123lld");
COMPARE_PATTERN("%+.03f", "%+.03f");
COMPARE_PATTERN("%.0d", "%.0d");
COMPARE_PATTERN("Test1 %.*d Test2 %.*d", "Test1 %.*d Test2 %.*d");
COMPARE_PATTERN("%s%S%d%u%i%x%X%o%c%C%b%p%n", "%s%S%d%u%i%x%X%o%c%C%b%p%n");
COMPARE_PATTERN("Test %hc", "Test %hc");
COMPARE_PATTERN("Test %wc", "Test %wc");
COMPARE_PATTERN("Test %lc", "Test %lc");
COMPARE_PATTERN("Test %0c", "Test %0c");
COMPARE_PATTERN("Test %%", "Test %");
COMPARE_PATTERN("%% Test", "% Test");
COMPARE_PATTERN("%%%c Test", "%%c Test");
COMPARE_PATTERN("%% Test", "% Test");
COMPARE_PATTERN("Test %%", "Test %");
COMPARE_PATTERN("Test %c Test", "Test %c Test");
l_blExit:
delete l_pFormatter;
if (l_pError)
{
printf("ERROR");
}
return l_pError ? FALSE : TRUE;
}
*/
private:
////////////////////////////////////////////////////////////////////////////
//AddArg
sArg *AddArg(const tXCHAR *i_pPrefix, size_t i_szPrefix)
{
sArg *l_pReturn = new sArg();
if (l_pReturn)
{
if (i_szPrefix)
{
l_pReturn->pPrefix = (tXCHAR*)malloc(i_szPrefix * sizeof(tXCHAR));
if (l_pReturn->pPrefix)
{
const tXCHAR *l_pSrc = i_pPrefix;
tXCHAR *l_pDst = l_pReturn->pPrefix;
l_pReturn->szPrefix = 0;
while (i_szPrefix--)
{
*l_pDst = *l_pSrc;
l_pDst ++;
l_pReturn->szPrefix++;
if ( (TM('%') == *l_pSrc)
&& (TM('%') == *(l_pSrc + 1))
)
{
l_pSrc ++;
i_szPrefix--;
}
l_pSrc ++;
}
}
}
}
return l_pReturn;
}
////////////////////////////////////////////////////////////////////////////
//GetSize
CFormatter::eSize GetSize(const tXCHAR *&i_pFormat)
{
struct sSize{ const tXCHAR *pPrefix; size_t szPrefix; CFormatter::eSize eSize;};
const static sSize g_pSize[] = {{TM("I64"), 3, eSize64},
{TM("I32"), 3, eSize32},
{TM("ll"), 2, eSizell},
{TM("hh"), 2, eSizehh},
{TM("h"), 1, eSizeh },
{TM("w"), 1, eSizew },
{TM("l"), 1, eSizel },
{TM("L"), 1, eSizeL },
{TM("I"), 1, eSizeI },
{TM("z"), 1, eSizez },
{TM("j"), 1, eSizej },
{TM("t"), 1, eSizet },
{TM("?"), 0, eSize32}
};
const sSize *l_pIter = &g_pSize[0];
while (l_pIter->szPrefix)
{
if (0 == PStrNCmp(i_pFormat, l_pIter->pPrefix, l_pIter->szPrefix))
{
i_pFormat += l_pIter->szPrefix;
return l_pIter->eSize;
}
l_pIter ++;
}
return eSizeUnk;
}
};
#endif //FORMATTER_H