//////////////////////////////////////////////////////////////////////////////// // / // 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 #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