|
|
/*++
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; }
|