forked from ValveSoftware/GameNetworkingSockets
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathfmtstr.h
More file actions
127 lines (109 loc) · 4.94 KB
/
fmtstr.h
File metadata and controls
127 lines (109 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//========= Copyright (c) 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 <cinttypes>
#include <cmath>
#include "strtools.h"
#if defined( _WIN32 )
#pragma once
#endif
#if defined(POSIX)
// clang will error if the symbol visibility for an object changes between static libraries (and/or your main dylib)
// so force the FmtStr templates and importantly the global scAsserted below to hidden (i.e don't escape the dll) forcefully
#pragma GCC visibility push(hidden)
#endif
//=============================================================================
// using macro to be compatible with GCC
#define FmtStrVSNPrintf( szBuf, nBufSize, refnFormattedLength, bQuietTruncation, pszFormat, lastArg ) \
do \
{ \
va_list arg_ptr; \
bool bTruncated = false; \
static int scAsserted = 0; \
\
va_start(arg_ptr, lastArg); \
(refnFormattedLength) = V_vsnprintfRet( (szBuf), (nBufSize), pszFormat, 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
//
class CNumStr
{
public:
CNumStr() { m_szBuf[0] = 0; m_nLength = 0; }
explicit CNumStr( bool b ) { SetBool( b ); }
explicit CNumStr( int8_t n8 ) { SetInt8( n8 ); }
explicit CNumStr( uint8_t un8 ) { SetUint8( un8 ); }
explicit CNumStr( int16_t n16 ) { SetInt16( n16 ); }
explicit CNumStr( uint16_t un16 ) { SetUint16( un16 ); }
explicit CNumStr( int32_t n32 ) { SetInt32( n32 ); }
explicit CNumStr( uint32_t un32 ) { SetUint32( un32 ); }
explicit CNumStr( int64_t n64 ) { SetInt64( n64 ); }
explicit CNumStr( uint64_t un64 ) { SetUint64( un64 ); }
explicit CNumStr( double f ) { SetDouble( f ); }
explicit CNumStr( float f ) { SetFloat( f ); }
#define NUMSTR_FAST_DIGIT( digit ) { m_nLength = 1; m_szBuf[0] = '0' + ( digit ); m_szBuf[1] = 0; return m_szBuf; }
#define NUMSTR_CHECK_FAST( val, utype ) if ( (utype)val < 10 ) NUMSTR_FAST_DIGIT( (utype)val )
inline const char* SetBool( bool b ) { NUMSTR_FAST_DIGIT( b & 1 ); }
inline const char* SetInt8( int8_t n8 ) { NUMSTR_CHECK_FAST( n8, uint8_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi32, n8 ); return m_szBuf; }
inline const char* SetUint8( uint8_t un8 ) { NUMSTR_CHECK_FAST( un8, uint8_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi32, un8 ); return m_szBuf; }
inline const char* SetInt16( int16_t n16 ) { NUMSTR_CHECK_FAST( n16, uint16_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi32, n16 ); return m_szBuf; }
inline const char* SetUint16( uint16_t un16 ) { NUMSTR_CHECK_FAST( un16, uint16_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi32, un16 ); return m_szBuf; }
inline const char* SetInt32( int32_t n32 ) { NUMSTR_CHECK_FAST( n32, uint32_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi32, n32 ); return m_szBuf; }
inline const char* SetUint32( uint32_t un32 ) { NUMSTR_CHECK_FAST( un32, uint32_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIu32, un32 ); return m_szBuf; }
inline const char* SetInt64( int64_t n64 ) { NUMSTR_CHECK_FAST( n64, uint64_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIi64, n64 ); return m_szBuf; }
inline const char* SetUint64( uint64_t un64 ) { NUMSTR_CHECK_FAST( un64, uint64_t ) m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIu64, un64 ); return m_szBuf; }
inline const char* SetHexUint64( uint64_t un64 ) { m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%" PRIx64, un64 ); return m_szBuf; }
inline const char* SetDouble( double f )
{
if ( f == 1.0 )
NUMSTR_FAST_DIGIT( 1 );
m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%.18g", f );
return m_szBuf;
}
inline const char* SetFloat( float f )
{
if ( f == 1.0f )
NUMSTR_FAST_DIGIT( 1 );
m_nLength = V_snprintf( m_szBuf, sizeof( m_szBuf ), "%.18g", f );
return m_szBuf;
}
//SDR_PUBLIC
#undef NUMSTR_FAST_DIGIT
#undef NUMSTR_CHECK_FAST
operator const char *() const { return m_szBuf; }
char *Access() { return m_szBuf; }
const char* String() const { return m_szBuf; }
int Length() const { return m_nLength; }
void AddQuotes()
{
Assert( m_nLength + 2 <= V_ARRAYSIZE(m_szBuf) );
memmove( m_szBuf+1, m_szBuf, m_nLength );
m_szBuf[0] = '"';
m_szBuf[m_nLength+1] = '"';
m_nLength+=2;
m_szBuf[m_nLength]=0;
}
protected:
char m_szBuf[28]; // long enough to hold 18 digits of precision, a decimal, a - sign, e+### suffix, and quotes
int m_nLength;
};
#endif // FMTSTR_H