//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: A simple class for performing safe and in-expression sprintf-style // string formatting // // $NoKeywords: $ //=============================================================================// #ifndef FMTSTR_H #define FMTSTR_H #include #include #include "tier0/platform.h" #include "tier0/dbg.h" #include "tier1/strtools.h" #if defined( _WIN32 ) #pragma once #endif //============================================================================= // using macro to be compatable with GCC #define FmtStrVSNPrintf( szBuf, nBufSize, bQuietTruncation, ppszFormat ) \ do \ { \ int result; \ va_list arg_ptr; \ bool bTruncated = false; \ static int scAsserted = 0; \ \ va_start(arg_ptr, (*(ppszFormat))); \ result = V_vsnprintfRet( (szBuf), (nBufSize)-1, (*(ppszFormat)), arg_ptr, &bTruncated ); \ va_end(arg_ptr); \ \ (szBuf)[(nBufSize)-1] = 0; \ if ( bTruncated && !(bQuietTruncation) && scAsserted < 5 ) \ { \ Assert( !bTruncated ); \ scAsserted++; \ } \ } \ while (0) //----------------------------------------------------------------------------- // // Purpose: String formatter with specified size // template class CFmtStrN { public: CFmtStrN() { InitQuietTruncation(); m_szBuf[0] = 0; m_nLength = 0; } // Standard C formatting CFmtStrN(const char *pszFormat, ...) FMTFUNCTION( 2, 3 ) { InitQuietTruncation(); FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat); FixLength(); } // Use this for pass-through formatting CFmtStrN(const char ** ppszFormat, ...) { InitQuietTruncation(); FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat); FixLength(); } // Explicit reformat const char *sprintf(const char *pszFormat, ...) FMTFUNCTION( 2, 3 ) { InitQuietTruncation(); FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat); FixLength(); return m_szBuf; } // Use this for pass-through formatting void VSprintf(const char **ppszFormat, ...) { InitQuietTruncation(); FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat); FixLength(); } // Use for access operator const char *() const { return m_szBuf; } char *Access() { return m_szBuf; } CFmtStrN & operator=( const char *pchValue ) { sprintf( pchValue ); return *this; } CFmtStrN & operator+=( const char *pchValue ) { Append( pchValue ); return *this; } int Length() const { return m_nLength; } void Clear() { m_szBuf[0] = 0; m_nLength = 0; } void AppendFormat( const char *pchFormat, ... ) { char *pchEnd = m_szBuf + m_nLength; FmtStrVSNPrintf( pchEnd, SIZE_BUF - m_nLength, m_bQuietTruncation, &pchFormat ); FixLength(); } void AppendFormatV( const char *pchFormat, va_list args ); void Append( const char *pchValue ) { AppendFormat( pchValue ); } void AppendIndent( uint32 unCount, char chIndent = '\t' ); protected: virtual void InitQuietTruncation() { #ifdef _DEBUG m_bQuietTruncation = false; #else m_bQuietTruncation = true; // Force quiet for release builds #endif } bool m_bQuietTruncation; void FixLength() { m_nLength = V_strlen(m_szBuf); } private: char m_szBuf[SIZE_BUF]; int m_nLength; }; // Version which will not assert if strings are truncated template class CFmtStrQuietTruncationN : public CFmtStrN { protected: virtual void InitQuietTruncation() { this->m_bQuietTruncation = true; } }; template< int SIZE_BUF > void CFmtStrN::AppendIndent( uint32 unCount, char chIndent ) { Assert( Length() + unCount < SIZE_BUF ); if( Length() + unCount >= SIZE_BUF ) unCount = SIZE_BUF - (1+Length()); for ( uint32 x = 0; x < unCount; x++ ) { m_szBuf[ m_nLength++ ] = chIndent; } m_szBuf[ m_nLength ] = '\0'; } template< int SIZE_BUF > void CFmtStrN::AppendFormatV( const char *pchFormat, va_list args ) { int cubPrinted = V_vsnprintf( m_szBuf+Length(), SIZE_BUF - Length(), pchFormat, args ); m_nLength += cubPrinted; } //----------------------------------------------------------------------------- // // Purpose: Default-sized string formatter // #define FMTSTR_STD_LEN 1024 typedef CFmtStrN CFmtStr; typedef CFmtStrQuietTruncationN CFmtStrQuietTruncation; typedef CFmtStrN<1024> CFmtStr1024; typedef CFmtStrN<8192> CFmtStrMax; //============================================================================= const int k_cchFormattedDate = 64; const int k_cchFormattedTime = 32; bool BGetLocalFormattedTime( time_t timeVal, char *pchDate, int cubDate, char *pchTime, int cubTime ); #endif // FMTSTR_H