Added a few more routines required to port FLAIM to FTK.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@497 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
ahodgkinson
2006-06-01 19:42:56 +00:00
parent 488ad60c0d
commit 73aa65fabd
10 changed files with 1660 additions and 104 deletions

View File

@@ -86,6 +86,211 @@ FSTATIC void f_logNotHandledFormatter(
IF_LogMessageClient * pLogMessage,
f_va_list * args);
FSTATIC FLMUINT traceFormatNumber(
FLMUINT64 ui64Number,
FLMINT uiBase,
char * pszDest);
#define FORMAT_MINUS_FLAG 0x0001
#define FORMAT_PLUS_FLAG 0x0002
#define FORMAT_SPACE_FLAG 0x0004
#define FORMAT_POUND_FLAG 0x0008
#define FORMAT_ZERO_FLAG 0x0010
#define FORMAT_SHORT_FLAG 0x0020
#define FORMAT_LONG_FLAG 0x0040
#define FORMAT_DOUBLE_FLAG 0x0080
#define FORMAT_INT64_FLAG 0x0100
// Special strings to embed in trace() calls.
#define FORE_BLACK "%0F"
#define FORE_BLUE "%1F"
#define FORE_GREEN "%2F"
#define FORE_CYAN "%3F"
#define FORE_RED "%4F"
#define FORE_MAGENTA "%5F"
#define FORE_BROWN "%6F"
#define FORE_LIGHTGRAY "%7F"
#define FORE_DARKGRAY "%8F"
#define FORE_LIGHTBLUE "%9F"
#define FORE_LIGHTGREEN "%10F"
#define FORE_LIGHTCYAN "%11F"
#define FORE_LIGHTRED "%12F"
#define FORE_LIGHTMAGENTA "%13F"
#define FORE_YELLOW "%14F"
#define FORE_WHITE "%15F"
#define BACK_BLACK "%0B"
#define BACK_BLUE "%1B"
#define BACK_GREEN "%2B"
#define BACK_CYAN "%3B"
#define BACK_RED "%4B"
#define BACK_MAGENTA "%5B"
#define BACK_BROWN "%6B"
#define BACK_LIGHTGRAY "%7B"
#define BACK_DARKGRAY "%8B"
#define BACK_LIGHTBLUE "%9B"
#define BACK_LIGHTGREEN "%10B"
#define BACK_LIGHTCYAN "%11B"
#define BACK_LIGHTRED "%12B"
#define BACK_LIGHTMAGENTA "%13B"
#define BACK_YELLOW "%14B"
#define BACK_WHITE "%15B"
#define PUSH_FORE_COLOR "%+F"
#define POP_FORE_COLOR "%-F"
#define PUSH_BACK_COLOR "%+B"
#define POP_BACK_COLOR "%-B"
// Trace categories reserved for users
#define USER_CATEGORY1 0x8000000
#define USER_CATEGORY2 0x4000000
#define USER_CATEGORY3 0x2000000
#define USER_CATEGORY4 0x1000000
#define USER_CATEGORY5 0x0800000
#define USER_CATEGORY6 0x0400000
#define USER_CATEGORY7 0x0200000
#define USER_CATEGORY8 0x0100000
/****************************************************************************
Desc:
****************************************************************************/
class F_Trace : public F_Object
{
public:
F_Trace();
virtual ~F_Trace();
FLMINT FLMAPI AddRef( void);
FLMINT FLMAPI Release( void);
FINLINE void enableCategory(
FLMUINT uiCategory)
{
m_uiEnabledCategories |= uiCategory;
}
FINLINE void disableCategory(
FLMUINT uiCategory)
{
m_uiEnabledCategories &= (~(uiCategory));
}
FINLINE FLMBOOL categoryEnabled(
FLMUINT uiCategory)
{
return( ((m_uiEnabledCategories & uiCategory) == uiCategory)
? TRUE
: FALSE);
}
FINLINE FLMUINT getEnabledCategories( void)
{
return( m_uiEnabledCategories);
}
void trace(
FLMUINT uiCategory,
const char * pszFormat,
...);
FLMBOOL setMultiThreaded( void);
void setPipe(
F_Trace * pTracePipe);
void lock( void);
void unlock( void);
void outputText(
FLMUINT uiCategory,
FLMUINT uiForeColor,
FLMUINT uiBackColor,
const char * pszString);
virtual void outputString(
FLMUINT uiCategory,
FLMUINT uiForeColor,
FLMUINT uiBackColor,
const char * pszString) = 0;
private:
void processFieldInfo(
const char ** ppszFormat,
FLMUINT * puiWidth,
FLMUINT * puiPrecision,
FLMUINT * puiFlags,
f_va_list * args);
void processStringText(
FLMUINT uiLen,
...);
void traceOutputArgs(
const char * pszFormat,
f_va_list * args);
void formatColor(
FLMUINT uiChar,
FLMUINT uiColor,
FLMUINT uiFlags);
void formatString(
FLMUINT uiFormatChar,
FLMUINT uiWidth,
FLMUINT uiPrecision,
FLMUINT uiFlags,
f_va_list * args);
void formatNumber(
FLMUINT uiFormatChar,
FLMUINT uiWidth,
FLMUINT uiPrecision,
FLMUINT uiFlags,
f_va_list * args);
void formatChar(
FLMUINT uiFormatChar,
f_va_list * args);
void formatNotHandled( void);
void outputCurrentText(
FLMUINT uiForeColor,
FLMUINT uiBackColor);
F_MUTEX m_hMutex;
FLMUINT m_uiLockCnt;
#ifdef FLM_DEBUG
FLMUINT m_uiLockThreadId;
#endif
FLMUINT m_uiEnabledCategories;
F_Trace * m_pTracePipe;
// Variables used to do the printf stuff
#define MAX_FORMAT_STR_SIZE 1000
char m_szDestStr [MAX_FORMAT_STR_SIZE];
char * m_pszDestStr;
FLMUINT m_uiMaxLen;
FLMUINT m_uiForeColorDepth;
FLMUINT m_uiBackColorDepth;
FLMUINT m_uiForeColorStack [8];
FLMUINT m_uiBackColorStack [8];
FLMUINT m_uiCurrentForeColor;
FLMUINT m_uiCurrentBackColor;
FLMUINT m_uiCategory;
};
/****************************************************************************
Desc: Handle text portions of the format string
****************************************************************************/
@@ -505,3 +710,722 @@ void FLMAPI f_endLogMessage(
f_mutexUnlock( gv_hLoggerMutex);
}
}
/****************************************************************************
Desc:
****************************************************************************/
F_Trace::F_Trace()
{
m_hMutex = F_MUTEX_NULL;
m_uiLockCnt = 0;
#ifdef FLM_DEBUG
m_uiLockThreadId = 0;
#endif
m_uiEnabledCategories = 0;
m_pTracePipe = NULL;
}
/****************************************************************************
Desc:
****************************************************************************/
F_Trace::~F_Trace()
{
flmAssert( m_uiLockCnt == 0);
if (m_hMutex != F_MUTEX_NULL)
{
f_mutexDestroy( &m_hMutex);
}
if (m_pTracePipe)
{
m_pTracePipe->Release();
}
}
/****************************************************************************
Desc:
****************************************************************************/
FLMINT FLMAPI F_Trace::AddRef( void)
{
return( f_atomicInc( &m_refCnt));
}
/****************************************************************************
Desc:
****************************************************************************/
FLMINT FLMAPI F_Trace::Release( void)
{
FLMINT iRefCnt;
if( (iRefCnt = f_atomicDec( &m_refCnt)) == 0)
{
delete this;
}
return( iRefCnt);
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::trace(
FLMUINT uiCategory,
const char * pszFormat,
...
)
{
f_va_list args;
f_va_start( args, pszFormat);
// First see if the stuff is enabled.
if (uiCategory & m_uiEnabledCategories)
{
lock();
// Leave room for terminator.
m_uiMaxLen = sizeof( m_szDestStr) - 1;
m_pszDestStr = &m_szDestStr [0];
m_uiCurrentForeColor = FLM_CURRENT_COLOR;
m_uiCurrentBackColor = FLM_CURRENT_COLOR;
m_uiForeColorDepth = 0;
m_uiBackColorDepth = 0;
m_uiCategory = uiCategory;
traceOutputArgs( pszFormat, (f_va_list *)&args);
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
unlock();
}
f_va_end( args);
}
/****************************************************************************
Desc:
****************************************************************************/
FLMBOOL F_Trace::setMultiThreaded( void)
{
FLMBOOL bOk = TRUE;
if (m_hMutex == F_MUTEX_NULL)
{
if (RC_BAD( f_mutexCreate( &m_hMutex)))
{
bOk = FALSE;
}
}
return( bOk);
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::setPipe(
F_Trace * pTracePipe)
{
lock();
if (m_pTracePipe && m_pTracePipe != pTracePipe)
{
m_pTracePipe->Release();
}
if ((m_pTracePipe = pTracePipe) != NULL)
{
m_pTracePipe->AddRef();
}
unlock();
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::lock( void)
{
if (m_uiLockCnt)
{
#ifdef FLM_DEBUG
flmAssert( m_uiLockThreadId == f_threadId());
#endif
m_uiLockCnt++;
}
else if (m_hMutex != F_MUTEX_NULL)
{
f_mutexLock( m_hMutex);
m_uiLockCnt++;
#ifdef FLM_DEBUG
m_uiLockThreadId = f_threadId();
#endif
}
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::unlock( void)
{
if (m_uiLockCnt)
{
#ifdef FLM_DEBUG
flmAssert( m_uiLockThreadId == f_threadId());
#endif
m_uiLockCnt--;
if (!m_uiLockCnt && m_hMutex != F_MUTEX_NULL)
{
f_mutexUnlock( m_hMutex);
#ifdef FLM_DEBUG
m_uiLockThreadId = 0;
#endif
}
}
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::outputText(
FLMUINT uiCategory,
FLMUINT uiForeColor,
FLMUINT uiBackColor,
const char * pszString)
{
lock();
outputString( uiCategory, uiForeColor, uiBackColor, pszString);
unlock();
if (m_pTracePipe)
{
if (uiCategory & m_pTracePipe->getEnabledCategories())
{
m_pTracePipe->outputText( uiCategory, uiForeColor, uiBackColor,
pszString);
}
}
}
/****************************************************************************
Desc: Parameter 'ppszFormat' points to text following a '%' sign. Process
legal field information. Leave 'ppszFormat' pointing at the format
specifier character.
****************************************************************************/
void F_Trace::processFieldInfo(
const char ** ppszFormat,
FLMUINT * puiWidth,
FLMUINT * puiPrecision,
FLMUINT * puiFlags,
f_va_list * args)
{
const char * pszTmp = *ppszFormat;
// Process flags
*puiFlags = 0;
for (;;)
{
switch (*pszTmp)
{
case '-': *puiFlags |= FORMAT_MINUS_FLAG; break;
case '+': *puiFlags |= FORMAT_PLUS_FLAG; break;
case ' ': *puiFlags |= FORMAT_SPACE_FLAG; break;
case '#': *puiFlags |= FORMAT_POUND_FLAG; break;
case '0': *puiFlags |= FORMAT_ZERO_FLAG; break;
default:
goto Out1;
}
pszTmp++;
}
Out1:
// Process width
*puiWidth = 0;
if (*pszTmp == '*')
{
*puiWidth = f_va_arg( *args, unsigned int);
++pszTmp;
}
else while (*pszTmp >= '0' && *pszTmp <= '9')
{
*puiWidth = (*puiWidth * 10) + (*pszTmp - '0');
++pszTmp;
}
// Process precision
*puiPrecision = 0;
if (*pszTmp == '.')
{
++pszTmp;
if (*pszTmp == '*')
{
*puiPrecision = f_va_arg( *args, unsigned int);
++pszTmp;
}
else while (*pszTmp >= '0' && *pszTmp <= '9')
{
*puiPrecision = (*puiPrecision * 10) + (*pszTmp - '0');
++pszTmp;
}
}
// Size modifiers
switch( *pszTmp)
{
case 'L': *puiFlags |= FORMAT_DOUBLE_FLAG; ++pszTmp; break;
case 'l': *puiFlags |= FORMAT_LONG_FLAG; ++pszTmp; break;
case 'h': *puiFlags |= FORMAT_SHORT_FLAG; ++pszTmp; break;
case 'I':
{
if( pszTmp[1] == '6' && pszTmp[2] == '4')
{
*puiFlags |= FORMAT_INT64_FLAG;
pszTmp += 3;
}
break;
}
}
*ppszFormat = pszTmp;
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::processStringText(
FLMUINT uiLen,
...)
{
f_va_list args;
f_va_start(args, uiLen);
if (uiLen)
{
formatString( 0, uiLen, uiLen, 0, (f_va_list *)&args);
}
f_va_end(args);
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::traceOutputArgs(
const char * pszFormat,
f_va_list * args)
{
FLMUINT uiChar;
FLMUINT uiWidth;
FLMUINT uiPrecision;
FLMUINT uiFlags;
const char * pszTextStart = pszFormat;
while ((uiChar = (FLMUINT)*pszFormat++) != 0)
{
if (uiChar != '%')
{
continue;
}
uiWidth = pszFormat - pszTextStart - 1;
processStringText( uiWidth, pszTextStart);
processFieldInfo( &pszFormat, &uiWidth, &uiPrecision, &uiFlags, args);
uiChar = (FLMUINT)*pszFormat++;
switch (uiChar)
{
case 'c':
case '%':
formatChar( uiChar, args);
break;
case 'B':
case 'F':
formatColor( uiChar, uiWidth, uiFlags);
break;
case 'd':
case 'o':
case 'u':
case 'x':
case 'X':
formatNumber( uiChar, uiWidth, uiPrecision, uiFlags, args);
break;
case 's':
case 'S':
case 'U':
formatString( uiChar, uiWidth, uiPrecision, uiFlags, args);
break;
default:
formatNotHandled();
break;
}
pszTextStart = pszFormat;
}
processStringText( (FLMUINT)(pszFormat - pszTextStart) - 1, pszTextStart);
}
/****************************************************************************
Desc:
****************************************************************************/
void F_Trace::formatColor(
FLMUINT uiChar,
FLMUINT uiColor,
FLMUINT uiFlags)
{
FLMUINT uiPrevForeColor = m_uiCurrentForeColor;
FLMUINT uiPrevBackColor = m_uiCurrentBackColor;
if (uiChar == 'F') // Foreground color
{
if ((uiFlags & FORMAT_PLUS_FLAG) && m_uiForeColorDepth < 8)
{
m_uiForeColorStack [m_uiForeColorDepth++] = m_uiCurrentForeColor;
}
else if ((uiFlags & FORMAT_MINUS_FLAG) && m_uiForeColorDepth > 0)
{
m_uiCurrentForeColor = m_uiForeColorStack [--m_uiForeColorDepth];
}
else
{
m_uiCurrentForeColor = uiColor;
}
}
else // uiChar == 'B' - background color
{
if ((uiFlags & FORMAT_PLUS_FLAG) && m_uiBackColorDepth < 8)
{
m_uiBackColorStack [m_uiBackColorDepth++] = m_uiCurrentBackColor;
}
else if ((uiFlags & FORMAT_MINUS_FLAG) && m_uiBackColorDepth > 0)
{
m_uiCurrentBackColor = m_uiBackColorStack [--m_uiBackColorDepth];
}
else
{
m_uiCurrentBackColor = uiColor;
}
}
// If the color changed, output the current text with the last
// colors we had.
if ((m_uiCurrentForeColor != uiPrevForeColor) ||
(m_uiCurrentBackColor != uiPrevBackColor))
{
outputCurrentText( uiPrevForeColor, uiPrevBackColor);
}
}
/****************************************************************************
Desc: String formatter.
Outputs the asciiz string specified by ADDRESS in 's'.
Outputs length preceeded string specified by ADDRESS in 'S'.
Outputs unicode string specified by ADDRESS in 'U'.
Format: %[flags][width][.prec]'s'|'S'|'U'
flags = '-' left justifies if string length < width
width = minimum number of characters to print
prec = maximum number of characters to print
****************************************************************************/
void F_Trace::formatString(
FLMUINT uiFormatChar,
FLMUINT uiWidth,
FLMUINT uiPrecision,
FLMUINT uiFlags,
f_va_list * args)
{
F_SPRINTF_INFO info;
info.pszDestStr = (FLMBYTE *)m_pszDestStr;
f_sprintfStringFormatter( (FLMBYTE)uiFormatChar, uiWidth,
uiPrecision, uiFlags, &info, args);
m_pszDestStr = (char *)info.pszDestStr;
}
/****************************************************************************
Desc: This is used by printf and sprintf to output numbers. It uses
recursion to separate the numbers down to individual digits and
output them in the proper order.
****************************************************************************/
FSTATIC FLMUINT traceFormatNumber(
FLMUINT64 ui64Number,
FLMINT uiBase,
char * pszDest)
{
char c = (char)(ui64Number % uiBase);
FLMUINT64 ui64Index = ui64Number / uiBase;
ui64Index = ui64Index
? traceFormatNumber( ui64Index, uiBase, pszDest)
: 0;
pszDest [ui64Index] = (char)((c > 9)
? c + 'a' - 10
: c + '0');
return (FLMUINT)(ui64Index + 1);
}
// Percent formating prefixes
#define P_NONE 0
#define P_MINUS 1
#define P_PLUS 2
#define P_POUND 3
/****************************************************************************
Desc: Number formatter.
Formats the number specified by VALUE in 'd', 'o', 'u', 'x', or 'X'
Format: %[flags][width][.prec]'E'
flags = 'h' value is uint16
'l' value is uint32
'-' left align result
'+' print plus sign if positive
'#' print '0x' in front of hex numbers
'0' zero-fill
width = minimum number of characters to output
prec = maximum number of characters to output (truncates or rounds)
****************************************************************************/
void F_Trace::formatNumber(
FLMUINT uiFormatChar,
FLMUINT uiWidth,
FLMUINT uiPrecision,
FLMUINT uiFlags,
f_va_list * args)
{
FLMUINT uiCount;
FLMUINT uiPrefix = P_NONE;
FLMUINT uiLength;
FLMUINT uiBase = 10;
char szNumberBuffer [64];
char * pszStr;
FLMUINT64 ui64Arg;
if (uiFlags & FORMAT_SHORT_FLAG)
{
ui64Arg = f_va_arg( *args, int);
}
else if (uiFlags & FORMAT_LONG_FLAG)
{
ui64Arg = f_va_arg( *args, long int);
}
else if ( uiFlags & FORMAT_INT64_FLAG)
{
ui64Arg = f_va_arg( *args, FLMUINT64);
}
else
{
ui64Arg = f_va_arg( *args, int);
}
switch (uiFormatChar)
{
case 'd':
if ((long)ui64Arg < 0)
{
// handle negatives
uiPrefix = P_MINUS;
if (uiWidth > 0)
{
uiWidth--;
}
ui64Arg = -(long)ui64Arg;
}
else if (uiFlags & FORMAT_PLUS_FLAG)
{
uiPrefix = P_PLUS;
if (uiWidth > 0)
uiWidth--;
}
break;
case 'o':
uiBase = 8;
break;
case 'x':
case 'X':
if (uiFlags & FORMAT_POUND_FLAG && ui64Arg)
{
uiPrefix = P_POUND;
if (uiWidth > 1)
{
uiWidth -= 2;
}
}
uiBase = 16;
break;
}
uiLength = traceFormatNumber( ui64Arg, uiBase, szNumberBuffer);
szNumberBuffer [uiLength] = 0;
if (uiFormatChar == 'X')
{
char * p = &szNumberBuffer [0];
while (*p)
{
if ((*p >= 'a') && (*p <= 'z'))
{
*p = (char)(*p - 'a' + 'A');
}
p++;
}
}
if (uiWidth < uiLength)
{
uiWidth = uiLength;
}
if (uiFlags & FORMAT_ZERO_FLAG)
{
uiPrecision = uiWidth; // zero fill
}
else if (!(uiFlags & FORMAT_MINUS_FLAG))
{
// Right justify.
while ((uiWidth > uiLength) &&
(uiWidth > uiPrecision))
{
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = ' ';
m_uiMaxLen--;
--uiWidth;
}
}
// handle the prefix if any
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
switch (uiPrefix)
{
case P_MINUS:
*m_pszDestStr++ = '-';
m_uiMaxLen--;
break;
case P_PLUS:
*m_pszDestStr++ = '+';
m_uiMaxLen--;
break;
case P_POUND:
*m_pszDestStr++ = '0';
m_uiMaxLen--;
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = (char)uiFormatChar;
m_uiMaxLen--;
break;
}
// handle the precision
while (uiLength < uiPrecision)
{
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = '0';
m_uiMaxLen--;
--uiPrecision;
--uiWidth;
}
// print out the number
for (uiCount = uiLength, pszStr = szNumberBuffer;
uiCount > 0;
uiCount--, m_uiMaxLen--)
{
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = *pszStr++;
}
if (uiFlags & FORMAT_MINUS_FLAG)
{
while (uiLength < uiWidth) // left justify
{
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = ' ';
m_uiMaxLen--;
--uiWidth;
}
}
}
/****************************************************************************
Desc: Character formatter.
FOrmats the character specified by VALUE in 'c', or the '%' character.
Format: %[flags][width][.prec]'c'
flags = <not used>
width = <not used>
prec = <not used>
****************************************************************************/
void F_Trace::formatChar(
FLMUINT uiFormatChar,
f_va_list * args)
{
char c = (uiFormatChar == '%')
? '%'
: f_va_arg( *args, int);
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
*m_pszDestStr++ = c;
m_uiMaxLen--;
}
/****************************************************************************
Desc: Handles all formatting stuff that is invalid.
****************************************************************************/
void F_Trace::formatNotHandled( void)
{
const char * pszNoFormatter = "<no formatter>";
FLMUINT uiLen = f_strlen( pszNoFormatter);
FLMUINT uiTmpLen;
while (uiLen)
{
if (!m_uiMaxLen)
{
outputCurrentText( m_uiCurrentForeColor, m_uiCurrentBackColor);
}
if ((uiTmpLen = uiLen) > m_uiMaxLen)
{
uiTmpLen = m_uiMaxLen;
}
f_memcpy( m_pszDestStr, (void *)pszNoFormatter, uiTmpLen);
m_pszDestStr += uiTmpLen;
m_uiMaxLen -= uiTmpLen;
uiLen -= uiTmpLen;
pszNoFormatter += uiTmpLen;
}
}
/****************************************************************************
Desc: Outputs the current text that we have buffered.
****************************************************************************/
void F_Trace::outputCurrentText(
FLMUINT uiForeColor,
FLMUINT uiBackColor)
{
FLMUINT uiLen = (FLMUINT)(m_pszDestStr - &m_szDestStr [0]);
if (uiLen)
{
m_szDestStr [uiLen] = 0;
outputText( m_uiCategory, uiForeColor, uiBackColor, m_szDestStr);
m_uiMaxLen = sizeof( m_szDestStr) - 1;
m_pszDestStr = &m_szDestStr [0];
}
}