You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.6 KiB
179 lines
4.6 KiB
//========= 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 <stdarg.h> |
|
#include <stdio.h> |
|
#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 <int SIZE_BUF> |
|
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<SIZE_BUF> & operator=( const char *pchValue ) { sprintf( pchValue ); return *this; } |
|
CFmtStrN<SIZE_BUF> & 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 <int SIZE_BUF> |
|
class CFmtStrQuietTruncationN : public CFmtStrN<SIZE_BUF> |
|
{ |
|
protected: |
|
virtual void InitQuietTruncation() { this->m_bQuietTruncation = true; } |
|
}; |
|
|
|
|
|
template< int SIZE_BUF > |
|
void CFmtStrN<SIZE_BUF>::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<SIZE_BUF>::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<FMTSTR_STD_LEN> CFmtStr; |
|
typedef CFmtStrQuietTruncationN<FMTSTR_STD_LEN> 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
|
|
|