698 lines
10 KiB
C++
698 lines
10 KiB
C++
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
dbgstr.cxx
|
|
|
|
Abstract:
|
|
|
|
Debug string class
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 23-May-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Class specific NULL state.
|
|
//
|
|
TCHAR TDebugString::gszNullState[2] = {0,0};
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
TDebugString
|
|
|
|
Routine Description:
|
|
|
|
Default construction.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
TDebugString::
|
|
TDebugString(
|
|
VOID
|
|
) : m_pszString( &TDebugString::gszNullState[kValid] )
|
|
{
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
TDebugString
|
|
|
|
Routine Description:
|
|
|
|
Construction using an existing LPCTSTR string.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Last Error:
|
|
|
|
None.
|
|
|
|
--*/
|
|
TDebugString::
|
|
TDebugString(
|
|
IN LPCTSTR psz
|
|
) : m_pszString( &TDebugString::gszNullState[kValid] )
|
|
{
|
|
(VOID)bUpdate( psz );
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
~TDebugString
|
|
|
|
Routine Description:
|
|
|
|
Destruction, ensure we don't free our NULL state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
TDebugString::
|
|
~TDebugString(
|
|
VOID
|
|
)
|
|
{
|
|
vFree( m_pszString );
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
TDebugString
|
|
|
|
Routine Description:
|
|
|
|
Copy constructor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
TDebugString::
|
|
TDebugString(
|
|
const TDebugString &String
|
|
) : m_pszString( &TDebugString::gszNullState[kValid] )
|
|
{
|
|
(VOID)bUpdate( String.m_pszString );
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bEmpty
|
|
|
|
Routine Description:
|
|
|
|
Indicates if a string has any usable data.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bEmpty(
|
|
VOID
|
|
) const
|
|
{
|
|
return *m_pszString == NULL;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bValid
|
|
|
|
Routine Description:
|
|
|
|
Indicates if a string object is valid.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bValid(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_pszString != &TDebugString::gszNullState[kInValid];
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
uLen
|
|
|
|
Routine Description:
|
|
|
|
Return the length of the string in characters
|
|
does not include the null terminator.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
UINT
|
|
TDebugString::
|
|
uLen(
|
|
VOID
|
|
) const
|
|
{
|
|
return _tcslen( m_pszString );
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
operator LPCTSTR
|
|
|
|
Routine Description:
|
|
|
|
Conversion operator from string object to pointer
|
|
to constant zero terminated string.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
TDebugString::
|
|
operator LPCTSTR(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_pszString;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bCat
|
|
|
|
Routine Description:
|
|
|
|
Safe concatenation of the specified string to the string
|
|
object. If the allocation fails, return FALSE and the
|
|
original string is not lost.
|
|
|
|
Arguments:
|
|
|
|
psz - Input string, may be NULL.
|
|
|
|
Return Value:
|
|
|
|
TRUE concatination was successful
|
|
FALSE concatination failed, orginal string is not modified
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bCat(
|
|
IN LPCTSTR psz
|
|
)
|
|
{
|
|
BOOL bReturn;
|
|
|
|
//
|
|
// If a valid string was passed.
|
|
//
|
|
if (psz && *psz)
|
|
{
|
|
//
|
|
// Allocate the new buffer consisting of the size of the orginal
|
|
// string plus the sizeof of the new string plus the null terminator.
|
|
//
|
|
LPTSTR pszTemp = INTERNAL_NEW TCHAR [ _tcslen( m_pszString ) + _tcslen( psz ) + 1 ];
|
|
|
|
//
|
|
// If memory was not available.
|
|
//
|
|
if (!pszTemp)
|
|
{
|
|
//
|
|
// Indicate failure, original string not modified.
|
|
//
|
|
bReturn = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Copy the original string and tack on the provided string.
|
|
//
|
|
_tcscpy( pszTemp, m_pszString );
|
|
_tcscat( pszTemp, psz );
|
|
|
|
//
|
|
// Release the original buffer.
|
|
//
|
|
vFree( m_pszString );
|
|
|
|
//
|
|
// Save pointer to new string.
|
|
//
|
|
m_pszString = pszTemp;
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// NULL pointers and NULL strings are silently ignored.
|
|
//
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bUpdate
|
|
|
|
Routine Description:
|
|
|
|
Safe updating of string. If the allocation fails the
|
|
orginal string is lost and the object becomes invalid.
|
|
A null pointer can be passed which is basically a
|
|
request to clear the contents of the string.
|
|
|
|
Arguments:
|
|
|
|
psz - Input string. The input string can be the null pointer
|
|
in this case the contents of the string cleared.
|
|
|
|
Return Value:
|
|
|
|
TRUE update successful
|
|
FALSE update failed
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bUpdate(
|
|
IN LPCTSTR psz OPTIONAL
|
|
)
|
|
{
|
|
BOOL bReturn;
|
|
|
|
//
|
|
// Check if the null pointer is passed.
|
|
//
|
|
if (!psz)
|
|
{
|
|
//
|
|
// Release the original string.
|
|
//
|
|
vFree( m_pszString );
|
|
|
|
//
|
|
// Mark the object as valid.
|
|
//
|
|
m_pszString = &TDebugString::gszNullState[kValid];
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
bReturn = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Create temp pointer to the previous string.
|
|
//
|
|
LPTSTR pszTmp = m_pszString;
|
|
|
|
//
|
|
// Allocate storage for the new string.
|
|
//
|
|
m_pszString = INTERNAL_NEW TCHAR [ _tcslen(psz) + 1 ];
|
|
|
|
//
|
|
// If memory was not available.
|
|
//
|
|
if (!m_pszString)
|
|
{
|
|
//
|
|
// Mark the string object as invalid.
|
|
//
|
|
m_pszString = &TDebugString::gszNullState[kInValid];
|
|
|
|
//
|
|
// Indicate failure.
|
|
//
|
|
bReturn = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Copy the string to the new buffer.
|
|
//
|
|
_tcscpy( m_pszString, psz );
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
//
|
|
// Release the previous string.
|
|
//
|
|
vFree( pszTmp );
|
|
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
vFree
|
|
|
|
Routine Description:
|
|
|
|
Safe free, frees the string memory. Ensures
|
|
we do not try an free our global memory block.
|
|
|
|
Arguments:
|
|
|
|
pszString pointer to string meory to free.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TDebugString::
|
|
vFree(
|
|
IN LPTSTR pszString OPTIONAL
|
|
)
|
|
{
|
|
//
|
|
// If this memory was not pointing to our
|
|
// class specific gszNullStates then release the memory.
|
|
//
|
|
if (pszString &&
|
|
pszString != &TDebugString::gszNullState[kValid] &&
|
|
pszString != &TDebugString::gszNullState[kInValid])
|
|
{
|
|
INTERNAL_DELETE [] pszString;
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bFormat
|
|
|
|
Routine Description:
|
|
|
|
Format the string opbject similar to sprintf.
|
|
|
|
Arguments:
|
|
|
|
pszFmt pointer format string.
|
|
.. variable number of arguments similar to sprintf.
|
|
|
|
Return Value:
|
|
|
|
TRUE if string was format successfully. FALSE if error
|
|
occurred creating the format string, string object will be
|
|
invalid and the previous string lost.
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bFormat(
|
|
IN LPCTSTR pszFmt,
|
|
IN ...
|
|
)
|
|
{
|
|
BOOL bReturn;
|
|
|
|
va_list pArgs;
|
|
|
|
va_start( pArgs, pszFmt );
|
|
|
|
bReturn = bvFormat( pszFmt, pArgs );
|
|
|
|
va_end( pArgs );
|
|
|
|
return bReturn;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bvFormat
|
|
|
|
Routine Description:
|
|
|
|
Format the string opbject similar to vsprintf.
|
|
|
|
Arguments:
|
|
|
|
pszFmt pointer format string.
|
|
pointer to variable number of arguments similar to vsprintf.
|
|
|
|
Return Value:
|
|
|
|
TRUE if string was format successfully. FALSE if error
|
|
occurred creating the format string, string object will be
|
|
left unaltered.
|
|
|
|
--*/
|
|
BOOL
|
|
TDebugString::
|
|
bvFormat(
|
|
IN LPCTSTR pszFmt,
|
|
IN va_list avlist
|
|
)
|
|
{
|
|
BOOL bReturn;
|
|
|
|
//
|
|
// Save previous string value.
|
|
//
|
|
LPTSTR pszTemp = m_pszString;
|
|
|
|
//
|
|
// Format the string.
|
|
//
|
|
m_pszString = vsntprintf( pszFmt, avlist );
|
|
|
|
//
|
|
// If format failed mark object as invalid and
|
|
// set the return value.
|
|
//
|
|
if (!m_pszString)
|
|
{
|
|
//
|
|
// Restore the orginal pointer.
|
|
//
|
|
m_pszString = pszTemp;
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
bReturn = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Release the previous string.
|
|
//
|
|
vFree( pszTemp );
|
|
|
|
//
|
|
// Indicate success.
|
|
//
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
vsntprintf
|
|
|
|
Routine Description:
|
|
|
|
Formats a string and returns a heap allocated string with the
|
|
formated data. This routine can be used to for extremely
|
|
long format strings. Note: If a valid pointer is returned
|
|
the callng functions must release the data with a call to delete.
|
|
|
|
Example:
|
|
|
|
LPCTSTR p = vsntprintf( _T("Test %s"), pString );
|
|
|
|
if (p)
|
|
{
|
|
SetTitle( p );
|
|
}
|
|
|
|
INTERNAL_DELETE [] p;
|
|
|
|
Arguments:
|
|
|
|
psFmt - format string
|
|
pArgs - pointer to a argument list.
|
|
|
|
Return Value:
|
|
|
|
Pointer to formated string. NULL if error.
|
|
|
|
--*/
|
|
LPTSTR
|
|
TDebugString::
|
|
vsntprintf(
|
|
IN LPCTSTR szFmt,
|
|
IN va_list pArgs
|
|
) const
|
|
{
|
|
LPTSTR pszBuff;
|
|
INT iSize = 256;
|
|
|
|
for( ; ; )
|
|
{
|
|
//
|
|
// Allocate the message buffer.
|
|
//
|
|
pszBuff = INTERNAL_NEW TCHAR [iSize];
|
|
|
|
//
|
|
// Allocating the buffer failed, we are done.
|
|
//
|
|
if (!pszBuff)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Attempt to format the string. snprintf fails with a
|
|
// negative number when the buffer is too small.
|
|
//
|
|
INT iReturn = _vsntprintf(pszBuff, iSize, szFmt, pArgs);
|
|
|
|
//
|
|
// If the return value positive and not equal to the buffer size
|
|
// then the format succeeded. _vsntprintf will not null terminate
|
|
// the string if the resultant string is exactly the length of the
|
|
// provided buffer.
|
|
//
|
|
if (iReturn > 0 && iReturn != iSize)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// String did not fit release the current buffer.
|
|
//
|
|
INTERNAL_DELETE [] pszBuff;
|
|
|
|
//
|
|
// Null the buffer pointer.
|
|
//
|
|
pszBuff = NULL;
|
|
|
|
//
|
|
// Double the buffer size after each failure.
|
|
//
|
|
iSize *= 2;
|
|
|
|
//
|
|
// If the size is greater than 100k exit without formatting a string.
|
|
//
|
|
if (iSize > kMaxFormatStringLength)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return pszBuff;
|
|
}
|
|
|
|
|