Team Fortress 2 Source Code as on 22/4/2020
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.

1398 lines
36 KiB

  1. //====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. // Serialization/unserialization buffer
  8. //=============================================================================//
  9. #ifndef UTLBUFFER_H
  10. #define UTLBUFFER_H
  11. #ifdef _WIN32
  12. #pragma once
  13. #endif
  14. #include "unitlib/unitlib.h" // just here for tests - remove before checking in!!!
  15. #include "tier1/utlmemory.h"
  16. #include "tier1/byteswap.h"
  17. #include <stdarg.h>
  18. //-----------------------------------------------------------------------------
  19. // Forward declarations
  20. //-----------------------------------------------------------------------------
  21. struct characterset_t;
  22. //-----------------------------------------------------------------------------
  23. // Description of character conversions for string output
  24. // Here's an example of how to use the macros to define a character conversion
  25. // BEGIN_CHAR_CONVERSION( CStringConversion, '\\' )
  26. // { '\n', "n" },
  27. // { '\t', "t" }
  28. // END_CHAR_CONVERSION( CStringConversion, '\\' )
  29. //-----------------------------------------------------------------------------
  30. class CUtlCharConversion
  31. {
  32. public:
  33. struct ConversionArray_t
  34. {
  35. char m_nActualChar;
  36. char *m_pReplacementString;
  37. };
  38. CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray );
  39. char GetEscapeChar() const;
  40. const char *GetDelimiter() const;
  41. int GetDelimiterLength() const;
  42. const char *GetConversionString( char c ) const;
  43. int GetConversionLength( char c ) const;
  44. int MaxConversionLength() const;
  45. // Finds a conversion for the passed-in string, returns length
  46. virtual char FindConversion( const char *pString, int *pLength );
  47. protected:
  48. struct ConversionInfo_t
  49. {
  50. int m_nLength;
  51. char *m_pReplacementString;
  52. };
  53. char m_nEscapeChar;
  54. const char *m_pDelimiter;
  55. int m_nDelimiterLength;
  56. int m_nCount;
  57. int m_nMaxConversionLength;
  58. char m_pList[256];
  59. ConversionInfo_t m_pReplacements[256];
  60. };
  61. #define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
  62. static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
  63. #define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
  64. }; \
  65. CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
  66. #define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
  67. static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
  68. #define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
  69. }; \
  70. _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
  71. //-----------------------------------------------------------------------------
  72. // Character conversions for C strings
  73. //-----------------------------------------------------------------------------
  74. CUtlCharConversion *GetCStringCharConversion();
  75. //-----------------------------------------------------------------------------
  76. // Character conversions for quoted strings, with no escape sequences
  77. //-----------------------------------------------------------------------------
  78. CUtlCharConversion *GetNoEscCharConversion();
  79. //-----------------------------------------------------------------------------
  80. // Macro to set overflow functions easily
  81. //-----------------------------------------------------------------------------
  82. #define SetUtlBufferOverflowFuncs( _get, _put ) \
  83. SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
  84. #define FMSTRRETTYPE static const char *
  85. #ifdef LINUX
  86. // gcc 4.3 is techinically correct and doesn't like the storage specifier,
  87. // unfortunately, that makes gcc on the mac and VS wind up with multiply defined
  88. // symbols at link time
  89. #define FMSTRRETTYPE const char *
  90. #endif
  91. typedef unsigned short ushort;
  92. template < class A >
  93. static const char *GetFmtStr( int nRadix = 10, bool bPrint = true ) { Assert( 0 ); return ""; }
  94. template <> FMSTRRETTYPE GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; }
  95. template <> FMSTRRETTYPE GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; }
  96. template <> FMSTRRETTYPE GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; }
  97. template <> FMSTRRETTYPE GetFmtStr< uint > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; }
  98. template <> FMSTRRETTYPE GetFmtStr< int64 > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; }
  99. template <> FMSTRRETTYPE GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; }
  100. template <> FMSTRRETTYPE GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
  101. //-----------------------------------------------------------------------------
  102. // Command parsing..
  103. //-----------------------------------------------------------------------------
  104. class CUtlBuffer
  105. {
  106. // Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc.
  107. // The unsafe case is something like this:
  108. // CUtlVector< CUtlBuffer > vecFoo;
  109. //
  110. // CUtlBuffer buf;
  111. // buf.Put( xxx );
  112. // vecFoo.Insert( buf );
  113. //
  114. // This will cause memory corruption when vecFoo is cleared
  115. //
  116. //private:
  117. // // Disallow copying
  118. // CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); }
  119. // CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; }
  120. public:
  121. enum SeekType_t
  122. {
  123. SEEK_HEAD = 0,
  124. SEEK_CURRENT,
  125. SEEK_TAIL
  126. };
  127. // flags
  128. enum BufferFlags_t
  129. {
  130. TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
  131. EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
  132. CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
  133. READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
  134. AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
  135. };
  136. // Overflow functions when a get or put overflows
  137. typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize );
  138. // Constructors for growable + external buffers for serialization/unserialization
  139. CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
  140. CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
  141. // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
  142. CUtlBuffer( const void *pBuffer, int size, bool crap );
  143. unsigned char GetFlags() const;
  144. // NOTE: This will assert if you attempt to recast it in a way that
  145. // is not compatible. The only valid conversion is binary-> text w/CRLF
  146. void SetBufferType( bool bIsText, bool bContainsCRLF );
  147. // Makes sure we've got at least this much memory
  148. void EnsureCapacity( int num );
  149. // Access for direct read into buffer
  150. void * AccessForDirectRead( int nBytes );
  151. // Attaches the buffer to external memory....
  152. void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
  153. bool IsExternallyAllocated() const;
  154. void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
  155. void *Detach();
  156. void* DetachMemory();
  157. FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
  158. {
  159. if ( ( IsX360() || IsPS3() ) )
  160. ActivateByteSwapping( true );
  161. }
  162. // Controls endian-ness of binary utlbufs - default matches the current platform
  163. void ActivateByteSwapping( bool bActivate );
  164. void SetBigEndian( bool bigEndian );
  165. bool IsBigEndian( void );
  166. // Resets the buffer; but doesn't free memory
  167. void Clear();
  168. // Clears out the buffer; frees memory
  169. void Purge();
  170. // Dump the buffer to stdout
  171. void Spew( );
  172. // Read stuff out.
  173. // Binary mode: it'll just read the bits directly in, and characters will be
  174. // read for strings until a null character is reached.
  175. // Text mode: it'll parse the file, turning text #s into real numbers.
  176. // GetString will read a string until a space is reached
  177. char GetChar( );
  178. unsigned char GetUnsignedChar( );
  179. short GetShort( );
  180. unsigned short GetUnsignedShort( );
  181. int GetInt( );
  182. int64 GetInt64( );
  183. unsigned int GetIntHex( );
  184. unsigned int GetUnsignedInt( );
  185. float GetFloat( );
  186. double GetDouble( );
  187. void * GetPtr();
  188. void GetString( char* pString, int nMaxChars = 0 );
  189. void Get( void* pMem, int size );
  190. void GetLine( char* pLine, int nMaxChars = 0 );
  191. // Used for getting objects that have a byteswap datadesc defined
  192. template <typename T> void GetObjects( T *dest, int count = 1 );
  193. // This will get at least 1 byte and up to nSize bytes.
  194. // It will return the number of bytes actually read.
  195. int GetUpTo( void *pMem, int nSize );
  196. // This version of GetString converts \" to \\ and " to \, etc.
  197. // It also reads a " at the beginning and end of the string
  198. void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 );
  199. char GetDelimitedChar( CUtlCharConversion *pConv );
  200. // This will return the # of characters of the string about to be read out
  201. // NOTE: The count will *include* the terminating 0!!
  202. // In binary mode, it's the number of characters until the next 0
  203. // In text mode, it's the number of characters until the next space.
  204. int PeekStringLength();
  205. // This version of PeekStringLength converts \" to \\ and " to \, etc.
  206. // It also reads a " at the beginning and end of the string
  207. // NOTE: The count will *include* the terminating 0!!
  208. // In binary mode, it's the number of characters until the next 0
  209. // In text mode, it's the number of characters between "s (checking for \")
  210. // Specifying false for bActualSize will return the pre-translated number of characters
  211. // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
  212. // and only 1 character when bActualSize == true
  213. int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true );
  214. // Just like scanf, but doesn't work in binary mode
  215. int Scanf( const char* pFmt, ... );
  216. int VaScanf( const char* pFmt, va_list list );
  217. // Eats white space, advances Get index
  218. void EatWhiteSpace();
  219. // Eats C++ style comments
  220. bool EatCPPComment();
  221. // (For text buffers only)
  222. // Parse a token from the buffer:
  223. // Grab all text that lies between a starting delimiter + ending delimiter
  224. // (skipping whitespace that leads + trails both delimiters).
  225. // If successful, the get index is advanced and the function returns true,
  226. // otherwise the index is not advanced and the function returns false.
  227. bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen );
  228. // Advance the get index until after the particular string is found
  229. // Do not eat whitespace before starting. Return false if it failed
  230. // String test is case-insensitive.
  231. bool GetToken( const char *pToken );
  232. // Parses the next token, given a set of character breaks to stop at
  233. // Returns the length of the token parsed in bytes (-1 if none parsed)
  234. int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true );
  235. // Write stuff in
  236. // Binary mode: it'll just write the bits directly in, and strings will be
  237. // written with a null terminating character
  238. // Text mode: it'll convert the numbers to text versions
  239. // PutString will not write a terminating character
  240. void PutChar( char c );
  241. void PutUnsignedChar( unsigned char uc );
  242. void PutShort( short s );
  243. void PutUnsignedShort( unsigned short us );
  244. void PutInt( int i );
  245. void PutInt64( int64 i );
  246. void PutUnsignedInt( unsigned int u );
  247. void PutFloat( float f );
  248. void PutDouble( double d );
  249. void PutPtr( void * ); // Writes the pointer, not the pointed to
  250. void PutString( const char* pString );
  251. void Put( const void* pMem, int size );
  252. // Used for putting objects that have a byteswap datadesc defined
  253. template <typename T> void PutObjects( T *src, int count = 1 );
  254. // This version of PutString converts \ to \\ and " to \", etc.
  255. // It also places " at the beginning and end of the string
  256. void PutDelimitedString( CUtlCharConversion *pConv, const char *pString );
  257. void PutDelimitedChar( CUtlCharConversion *pConv, char c );
  258. // Just like printf, writes a terminating zero in binary mode
  259. void Printf( const char* pFmt, ... ) FMTFUNCTION( 2, 3 );
  260. void VaPrintf( const char* pFmt, va_list list );
  261. // What am I writing (put)/reading (get)?
  262. void* PeekPut( int offset = 0 );
  263. const void* PeekGet( int offset = 0 ) const;
  264. const void* PeekGet( int nMaxSize, int nOffset );
  265. // Where am I writing (put)/reading (get)?
  266. int TellPut( ) const;
  267. int TellGet( ) const;
  268. // What's the most I've ever written?
  269. int TellMaxPut( ) const;
  270. // How many bytes remain to be read?
  271. // NOTE: This is not accurate for streaming text files; it overshoots
  272. int GetBytesRemaining() const;
  273. // Change where I'm writing (put)/reading (get)
  274. void SeekPut( SeekType_t type, int offset );
  275. void SeekGet( SeekType_t type, int offset );
  276. // Buffer base
  277. const void* Base() const;
  278. void* Base();
  279. // memory allocation size, does *not* reflect size written or read,
  280. // use TellPut or TellGet for that
  281. int Size() const;
  282. // Am I a text buffer?
  283. bool IsText() const;
  284. // Can I grow if I'm externally allocated?
  285. bool IsGrowable() const;
  286. // Am I valid? (overflow or underflow error), Once invalid it stays invalid
  287. bool IsValid() const;
  288. // Do I contain carriage return/linefeeds?
  289. bool ContainsCRLF() const;
  290. // Am I read-only
  291. bool IsReadOnly() const;
  292. // Converts a buffer from a CRLF buffer to a CR buffer (and back)
  293. // Returns false if no conversion was necessary (and outBuf is left untouched)
  294. // If the conversion occurs, outBuf will be cleared.
  295. bool ConvertCRLF( CUtlBuffer &outBuf );
  296. // Push/pop pretty-printing tabs
  297. void PushTab();
  298. void PopTab();
  299. // Temporarily disables pretty print
  300. void EnableTabs( bool bEnable );
  301. #if !defined( _GAMECONSOLE )
  302. // Swap my internal memory with another buffer,
  303. // and copy all of its other members
  304. void SwapCopy( CUtlBuffer &other ) ;
  305. #endif
  306. protected:
  307. // error flags
  308. enum
  309. {
  310. PUT_OVERFLOW = 0x1,
  311. GET_OVERFLOW = 0x2,
  312. MAX_ERROR_FLAG = GET_OVERFLOW,
  313. };
  314. void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc );
  315. bool OnPutOverflow( int nSize );
  316. bool OnGetOverflow( int nSize );
  317. protected:
  318. // Checks if a get/put is ok
  319. bool CheckPut( int size );
  320. bool CheckGet( int size );
  321. // NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
  322. // after modifying m_Put and this lets it stay in a register
  323. void AddNullTermination( int nPut );
  324. // Methods to help with pretty-printing
  325. bool WasLastCharacterCR();
  326. void PutTabs();
  327. // Help with delimited stuff
  328. char GetDelimitedCharInternal( CUtlCharConversion *pConv );
  329. void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c );
  330. // Default overflow funcs
  331. bool PutOverflow( int nSize );
  332. bool GetOverflow( int nSize );
  333. // Does the next bytes of the buffer match a pattern?
  334. bool PeekStringMatch( int nOffset, const char *pString, int nLen );
  335. // Peek size of line to come, check memory bound
  336. int PeekLineLength();
  337. // How much whitespace should I skip?
  338. int PeekWhiteSpace( int nOffset );
  339. // Checks if a peek get is ok
  340. bool CheckPeekGet( int nOffset, int nSize );
  341. // Call this to peek arbitrarily long into memory. It doesn't fail unless
  342. // it can't read *anything* new
  343. bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
  344. template <typename T> void GetType( T& dest );
  345. template <typename T> void GetTypeBin( T& dest );
  346. template <typename T> bool GetTypeText( T &value, int nRadix = 10 );
  347. template <typename T> void GetObject( T *src );
  348. template <typename T> void PutType( T src );
  349. template <typename T> void PutTypeBin( T src );
  350. template <typename T> void PutObject( T *src );
  351. // be sure to also update the copy constructor
  352. // and SwapCopy() when adding members.
  353. CUtlMemory<unsigned char> m_Memory;
  354. int m_Get;
  355. int m_Put;
  356. unsigned char m_Error;
  357. unsigned char m_Flags;
  358. unsigned char m_Reserved;
  359. #if defined( _GAMECONSOLE )
  360. unsigned char pad;
  361. #endif
  362. int m_nTab;
  363. int m_nMaxPut;
  364. int m_nOffset;
  365. UtlBufferOverflowFunc_t m_GetOverflowFunc;
  366. UtlBufferOverflowFunc_t m_PutOverflowFunc;
  367. CByteswap m_Byteswap;
  368. };
  369. // Stream style output operators for CUtlBuffer
  370. inline CUtlBuffer &operator<<( CUtlBuffer &b, char v )
  371. {
  372. b.PutChar( v );
  373. return b;
  374. }
  375. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v )
  376. {
  377. b.PutUnsignedChar( v );
  378. return b;
  379. }
  380. inline CUtlBuffer &operator<<( CUtlBuffer &b, short v )
  381. {
  382. b.PutShort( v );
  383. return b;
  384. }
  385. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v )
  386. {
  387. b.PutUnsignedShort( v );
  388. return b;
  389. }
  390. inline CUtlBuffer &operator<<( CUtlBuffer &b, int v )
  391. {
  392. b.PutInt( v );
  393. return b;
  394. }
  395. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v )
  396. {
  397. b.PutUnsignedInt( v );
  398. return b;
  399. }
  400. inline CUtlBuffer &operator<<( CUtlBuffer &b, float v )
  401. {
  402. b.PutFloat( v );
  403. return b;
  404. }
  405. inline CUtlBuffer &operator<<( CUtlBuffer &b, double v )
  406. {
  407. b.PutDouble( v );
  408. return b;
  409. }
  410. inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv )
  411. {
  412. b.PutString( pv );
  413. return b;
  414. }
  415. inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector &v )
  416. {
  417. b << v.x << " " << v.y << " " << v.z;
  418. return b;
  419. }
  420. inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector2D &v )
  421. {
  422. b << v.x << " " << v.y;
  423. return b;
  424. }
  425. class CUtlInplaceBuffer : public CUtlBuffer
  426. {
  427. public:
  428. CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
  429. //
  430. // Routines returning buffer-inplace-pointers
  431. //
  432. public:
  433. //
  434. // Upon success, determines the line length, fills out the pointer to the
  435. // beginning of the line and the line length, advances the "get" pointer
  436. // offset by the line length and returns "true".
  437. //
  438. // If end of file is reached or upon error returns "false".
  439. //
  440. // Note: the returned length of the line is at least one character because the
  441. // trailing newline characters are also included as part of the line.
  442. //
  443. // Note: the pointer returned points into the local memory of this buffer, in
  444. // case the buffer gets relocated or destroyed the pointer becomes invalid.
  445. //
  446. // e.g.: -------------
  447. //
  448. // char *pszLine;
  449. // int nLineLen;
  450. // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) )
  451. // {
  452. // ...
  453. // }
  454. //
  455. // -------------
  456. //
  457. // @param ppszInBufferPtr on return points into this buffer at start of line
  458. // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr)
  459. //
  460. // @returns true if line was successfully read
  461. // false when EOF is reached or error occurs
  462. //
  463. bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength );
  464. //
  465. // Determines the line length, advances the "get" pointer offset by the line length,
  466. // replaces the newline character with null-terminator and returns the initial pointer
  467. // to now null-terminated line.
  468. //
  469. // If end of file is reached or upon error returns NULL.
  470. //
  471. // Note: the pointer returned points into the local memory of this buffer, in
  472. // case the buffer gets relocated or destroyed the pointer becomes invalid.
  473. //
  474. // e.g.: -------------
  475. //
  476. // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() )
  477. // {
  478. // ...
  479. // }
  480. //
  481. // -------------
  482. //
  483. // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified
  484. // NULL when EOF is reached or error occurs
  485. //
  486. char * InplaceGetLinePtr( void );
  487. };
  488. //-----------------------------------------------------------------------------
  489. // Where am I reading?
  490. //-----------------------------------------------------------------------------
  491. inline int CUtlBuffer::TellGet( ) const
  492. {
  493. return m_Get;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // How many bytes remain to be read?
  497. //-----------------------------------------------------------------------------
  498. inline int CUtlBuffer::GetBytesRemaining() const
  499. {
  500. return m_nMaxPut - TellGet();
  501. }
  502. //-----------------------------------------------------------------------------
  503. // What am I reading?
  504. //-----------------------------------------------------------------------------
  505. inline const void* CUtlBuffer::PeekGet( int offset ) const
  506. {
  507. return &m_Memory[ m_Get + offset - m_nOffset ];
  508. }
  509. //-----------------------------------------------------------------------------
  510. // Unserialization
  511. //-----------------------------------------------------------------------------
  512. template <typename T>
  513. inline void CUtlBuffer::GetObject( T *dest )
  514. {
  515. if ( CheckGet( sizeof(T) ) )
  516. {
  517. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  518. {
  519. *dest = *(T *)PeekGet();
  520. }
  521. else
  522. {
  523. m_Byteswap.SwapFieldsToTargetEndian<T>( dest, (T*)PeekGet() );
  524. }
  525. m_Get += sizeof(T);
  526. }
  527. else
  528. {
  529. V_memset( &dest, 0, sizeof(T) );
  530. }
  531. }
  532. template <typename T>
  533. inline void CUtlBuffer::GetObjects( T *dest, int count )
  534. {
  535. for ( int i = 0; i < count; ++i, ++dest )
  536. {
  537. GetObject<T>( dest );
  538. }
  539. }
  540. template <typename T>
  541. inline void CUtlBuffer::GetTypeBin( T &dest )
  542. {
  543. if ( CheckGet( sizeof(T) ) )
  544. {
  545. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  546. {
  547. dest = *(T *)PeekGet();
  548. }
  549. else
  550. {
  551. m_Byteswap.SwapBufferToTargetEndian<T>( &dest, (T*)PeekGet() );
  552. }
  553. m_Get += sizeof(T);
  554. }
  555. else
  556. {
  557. dest = 0;
  558. }
  559. }
  560. template <>
  561. inline void CUtlBuffer::GetTypeBin< float >( float &dest )
  562. {
  563. if ( CheckGet( sizeof( float ) ) )
  564. {
  565. uintp pData = (uintp)PeekGet();
  566. if ( ( IsX360() || IsPS3() ) && ( pData & 0x03 ) )
  567. {
  568. // handle unaligned read
  569. ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
  570. ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
  571. ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
  572. ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
  573. }
  574. else
  575. {
  576. // aligned read
  577. dest = *(float *)pData;
  578. }
  579. if ( m_Byteswap.IsSwappingBytes() )
  580. {
  581. m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest );
  582. }
  583. m_Get += sizeof( float );
  584. }
  585. else
  586. {
  587. dest = 0;
  588. }
  589. }
  590. template <>
  591. inline void CUtlBuffer::GetTypeBin< double >( double &dest )
  592. {
  593. if ( CheckGet( sizeof( double ) ) )
  594. {
  595. uintp pData = (uintp)PeekGet();
  596. if ( ( IsX360() || IsPS3() ) && ( pData & 0x07 ) )
  597. {
  598. // handle unaligned read
  599. ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
  600. ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
  601. ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
  602. ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
  603. ((unsigned char*)&dest)[4] = ((unsigned char*)pData)[4];
  604. ((unsigned char*)&dest)[5] = ((unsigned char*)pData)[5];
  605. ((unsigned char*)&dest)[6] = ((unsigned char*)pData)[6];
  606. ((unsigned char*)&dest)[7] = ((unsigned char*)pData)[7];
  607. }
  608. else
  609. {
  610. // aligned read
  611. dest = *(double *)pData;
  612. }
  613. if ( m_Byteswap.IsSwappingBytes() )
  614. {
  615. m_Byteswap.SwapBufferToTargetEndian< double >( &dest, &dest );
  616. }
  617. m_Get += sizeof( double );
  618. }
  619. else
  620. {
  621. dest = 0;
  622. }
  623. }
  624. template < class T >
  625. inline T StringToNumber( char *pString, char **ppEnd, int nRadix )
  626. {
  627. Assert( 0 );
  628. *ppEnd = pString;
  629. return 0;
  630. }
  631. template <>
  632. inline int8 StringToNumber( char *pString, char **ppEnd, int nRadix )
  633. {
  634. return ( int8 )strtol( pString, ppEnd, nRadix );
  635. }
  636. template <>
  637. inline uint8 StringToNumber( char *pString, char **ppEnd, int nRadix )
  638. {
  639. return ( uint8 )strtoul( pString, ppEnd, nRadix );
  640. }
  641. template <>
  642. inline int16 StringToNumber( char *pString, char **ppEnd, int nRadix )
  643. {
  644. return ( int16 )strtol( pString, ppEnd, nRadix );
  645. }
  646. template <>
  647. inline uint16 StringToNumber( char *pString, char **ppEnd, int nRadix )
  648. {
  649. return ( uint16 )strtoul( pString, ppEnd, nRadix );
  650. }
  651. template <>
  652. inline int32 StringToNumber( char *pString, char **ppEnd, int nRadix )
  653. {
  654. return ( int32 )strtol( pString, ppEnd, nRadix );
  655. }
  656. template <>
  657. inline uint32 StringToNumber( char *pString, char **ppEnd, int nRadix )
  658. {
  659. return ( uint32 )strtoul( pString, ppEnd, nRadix );
  660. }
  661. template <>
  662. inline int64 StringToNumber( char *pString, char **ppEnd, int nRadix )
  663. {
  664. #if defined(_PS3) || defined(POSIX)
  665. return ( int64 )strtoll( pString, ppEnd, nRadix );
  666. #else // !_PS3
  667. return ( int64 )_strtoi64( pString, ppEnd, nRadix );
  668. #endif // _PS3
  669. }
  670. template <>
  671. inline float StringToNumber( char *pString, char **ppEnd, int nRadix )
  672. {
  673. NOTE_UNUSED( nRadix );
  674. return ( float )strtod( pString, ppEnd );
  675. }
  676. template <>
  677. inline double StringToNumber( char *pString, char **ppEnd, int nRadix )
  678. {
  679. NOTE_UNUSED( nRadix );
  680. return ( double )strtod( pString, ppEnd );
  681. }
  682. template <typename T>
  683. inline bool CUtlBuffer::GetTypeText( T &value, int nRadix /*= 10*/ )
  684. {
  685. // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
  686. int nLength = 128;
  687. if ( !CheckArbitraryPeekGet( 0, nLength ) )
  688. {
  689. value = 0;
  690. return false;
  691. }
  692. char *pStart = (char*)PeekGet();
  693. char* pEnd = pStart;
  694. value = StringToNumber< T >( pStart, &pEnd, nRadix );
  695. int nBytesRead = (int)( pEnd - pStart );
  696. if ( nBytesRead == 0 )
  697. return false;
  698. m_Get += nBytesRead;
  699. return true;
  700. }
  701. template <typename T>
  702. inline void CUtlBuffer::GetType( T &dest )
  703. {
  704. if (!IsText())
  705. {
  706. GetTypeBin( dest );
  707. }
  708. else
  709. {
  710. GetTypeText( dest );
  711. }
  712. }
  713. inline char CUtlBuffer::GetChar( )
  714. {
  715. // LEGACY WARNING: this behaves differently than GetUnsignedChar()
  716. char c;
  717. GetTypeBin( c ); // always reads as binary
  718. return c;
  719. }
  720. inline unsigned char CUtlBuffer::GetUnsignedChar( )
  721. {
  722. // LEGACY WARNING: this behaves differently than GetChar()
  723. unsigned char c;
  724. if (!IsText())
  725. {
  726. GetTypeBin( c );
  727. }
  728. else
  729. {
  730. c = ( unsigned char )GetUnsignedShort();
  731. }
  732. return c;
  733. }
  734. inline short CUtlBuffer::GetShort( )
  735. {
  736. short s;
  737. GetType( s );
  738. return s;
  739. }
  740. inline unsigned short CUtlBuffer::GetUnsignedShort( )
  741. {
  742. unsigned short s;
  743. GetType( s );
  744. return s;
  745. }
  746. inline int CUtlBuffer::GetInt( )
  747. {
  748. int i;
  749. GetType( i );
  750. return i;
  751. }
  752. inline int64 CUtlBuffer::GetInt64( )
  753. {
  754. int64 i;
  755. GetType( i );
  756. return i;
  757. }
  758. inline unsigned int CUtlBuffer::GetIntHex( )
  759. {
  760. uint i;
  761. if (!IsText())
  762. {
  763. GetTypeBin( i );
  764. }
  765. else
  766. {
  767. GetTypeText( i, 16 );
  768. }
  769. return i;
  770. }
  771. inline unsigned int CUtlBuffer::GetUnsignedInt( )
  772. {
  773. unsigned int i;
  774. GetType( i );
  775. return i;
  776. }
  777. inline float CUtlBuffer::GetFloat( )
  778. {
  779. float f;
  780. GetType( f );
  781. return f;
  782. }
  783. inline double CUtlBuffer::GetDouble( )
  784. {
  785. double d;
  786. GetType( d );
  787. return d;
  788. }
  789. inline void *CUtlBuffer::GetPtr( )
  790. {
  791. void *p;
  792. // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
  793. #ifndef X64BITS
  794. p = ( void* )GetUnsignedInt();
  795. #else
  796. p = ( void* )GetInt64();
  797. #endif
  798. return p;
  799. }
  800. //-----------------------------------------------------------------------------
  801. // Where am I writing?
  802. //-----------------------------------------------------------------------------
  803. inline unsigned char CUtlBuffer::GetFlags() const
  804. {
  805. return m_Flags;
  806. }
  807. //-----------------------------------------------------------------------------
  808. //
  809. //-----------------------------------------------------------------------------
  810. inline bool CUtlBuffer::IsExternallyAllocated() const
  811. {
  812. return m_Memory.IsExternallyAllocated();
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Where am I writing?
  816. //-----------------------------------------------------------------------------
  817. inline int CUtlBuffer::TellPut( ) const
  818. {
  819. return m_Put;
  820. }
  821. //-----------------------------------------------------------------------------
  822. // What's the most I've ever written?
  823. //-----------------------------------------------------------------------------
  824. inline int CUtlBuffer::TellMaxPut( ) const
  825. {
  826. return m_nMaxPut;
  827. }
  828. //-----------------------------------------------------------------------------
  829. // What am I reading?
  830. //-----------------------------------------------------------------------------
  831. inline void* CUtlBuffer::PeekPut( int offset )
  832. {
  833. return &m_Memory[m_Put + offset - m_nOffset];
  834. }
  835. //-----------------------------------------------------------------------------
  836. // Various put methods
  837. //-----------------------------------------------------------------------------
  838. template <typename T>
  839. inline void CUtlBuffer::PutObject( T *src )
  840. {
  841. if ( CheckPut( sizeof(T) ) )
  842. {
  843. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  844. {
  845. *(T *)PeekPut() = *src;
  846. }
  847. else
  848. {
  849. m_Byteswap.SwapFieldsToTargetEndian<T>( (T*)PeekPut(), src );
  850. }
  851. m_Put += sizeof(T);
  852. AddNullTermination( m_Put );
  853. }
  854. }
  855. template <typename T>
  856. inline void CUtlBuffer::PutObjects( T *src, int count )
  857. {
  858. for ( int i = 0; i < count; ++i, ++src )
  859. {
  860. PutObject<T>( src );
  861. }
  862. }
  863. template <typename T>
  864. inline void CUtlBuffer::PutTypeBin( T src )
  865. {
  866. if ( CheckPut( sizeof(T) ) )
  867. {
  868. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  869. {
  870. *(T *)PeekPut() = src;
  871. }
  872. else
  873. {
  874. m_Byteswap.SwapBufferToTargetEndian<T>( (T*)PeekPut(), &src );
  875. }
  876. m_Put += sizeof(T);
  877. AddNullTermination( m_Put );
  878. }
  879. }
  880. #if defined( _GAMECONSOLE )
  881. template <>
  882. inline void CUtlBuffer::PutTypeBin< float >( float src )
  883. {
  884. if ( CheckPut( sizeof( src ) ) )
  885. {
  886. if ( m_Byteswap.IsSwappingBytes() )
  887. {
  888. m_Byteswap.SwapBufferToTargetEndian<float>( &src, &src );
  889. }
  890. //
  891. // Write the data
  892. //
  893. unsigned pData = (unsigned)PeekPut();
  894. if ( pData & 0x03 )
  895. {
  896. // handle unaligned write
  897. byte* dst = (byte*)pData;
  898. byte* srcPtr = (byte*)&src;
  899. dst[0] = srcPtr[0];
  900. dst[1] = srcPtr[1];
  901. dst[2] = srcPtr[2];
  902. dst[3] = srcPtr[3];
  903. }
  904. else
  905. {
  906. *(float *)pData = src;
  907. }
  908. m_Put += sizeof(float);
  909. AddNullTermination( m_Put );
  910. }
  911. }
  912. template <>
  913. inline void CUtlBuffer::PutTypeBin< double >( double src )
  914. {
  915. if ( CheckPut( sizeof( src ) ) )
  916. {
  917. if ( m_Byteswap.IsSwappingBytes() )
  918. {
  919. m_Byteswap.SwapBufferToTargetEndian<double>( &src, &src );
  920. }
  921. //
  922. // Write the data
  923. //
  924. unsigned pData = (unsigned)PeekPut();
  925. if ( pData & 0x07 )
  926. {
  927. // handle unaligned write
  928. byte* dst = (byte*)pData;
  929. byte* srcPtr = (byte*)&src;
  930. dst[0] = srcPtr[0];
  931. dst[1] = srcPtr[1];
  932. dst[2] = srcPtr[2];
  933. dst[3] = srcPtr[3];
  934. dst[4] = srcPtr[4];
  935. dst[5] = srcPtr[5];
  936. dst[6] = srcPtr[6];
  937. dst[7] = srcPtr[7];
  938. }
  939. else
  940. {
  941. *(double *)pData = src;
  942. }
  943. m_Put += sizeof(double);
  944. AddNullTermination( m_Put );
  945. }
  946. }
  947. #endif
  948. template <typename T>
  949. inline void CUtlBuffer::PutType( T src )
  950. {
  951. if (!IsText())
  952. {
  953. PutTypeBin( src );
  954. }
  955. else
  956. {
  957. Printf( GetFmtStr< T >(), src );
  958. }
  959. }
  960. //-----------------------------------------------------------------------------
  961. // Methods to help with pretty-printing
  962. //-----------------------------------------------------------------------------
  963. inline bool CUtlBuffer::WasLastCharacterCR()
  964. {
  965. if ( !IsText() || (TellPut() == 0) )
  966. return false;
  967. return ( *( const char * )PeekPut( -1 ) == '\n' );
  968. }
  969. inline void CUtlBuffer::PutTabs()
  970. {
  971. int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab;
  972. for (int i = nTabCount; --i >= 0; )
  973. {
  974. PutTypeBin<char>( '\t' );
  975. }
  976. }
  977. //-----------------------------------------------------------------------------
  978. // Push/pop pretty-printing tabs
  979. //-----------------------------------------------------------------------------
  980. inline void CUtlBuffer::PushTab( )
  981. {
  982. ++m_nTab;
  983. }
  984. inline void CUtlBuffer::PopTab()
  985. {
  986. if ( --m_nTab < 0 )
  987. {
  988. m_nTab = 0;
  989. }
  990. }
  991. //-----------------------------------------------------------------------------
  992. // Temporarily disables pretty print
  993. //-----------------------------------------------------------------------------
  994. inline void CUtlBuffer::EnableTabs( bool bEnable )
  995. {
  996. if ( bEnable )
  997. {
  998. m_Flags &= ~AUTO_TABS_DISABLED;
  999. }
  1000. else
  1001. {
  1002. m_Flags |= AUTO_TABS_DISABLED;
  1003. }
  1004. }
  1005. inline void CUtlBuffer::PutChar( char c )
  1006. {
  1007. if ( WasLastCharacterCR() )
  1008. {
  1009. PutTabs();
  1010. }
  1011. PutTypeBin( c );
  1012. }
  1013. inline void CUtlBuffer::PutUnsignedChar( unsigned char c )
  1014. {
  1015. if (!IsText())
  1016. {
  1017. PutTypeBin( c );
  1018. }
  1019. else
  1020. {
  1021. PutUnsignedShort( c );
  1022. }
  1023. }
  1024. inline void CUtlBuffer::PutShort( short s )
  1025. {
  1026. PutType( s );
  1027. }
  1028. inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
  1029. {
  1030. PutType( s );
  1031. }
  1032. inline void CUtlBuffer::PutInt( int i )
  1033. {
  1034. PutType( i );
  1035. }
  1036. inline void CUtlBuffer::PutInt64( int64 i )
  1037. {
  1038. PutType( i );
  1039. }
  1040. inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
  1041. {
  1042. PutType( u );
  1043. }
  1044. inline void CUtlBuffer::PutFloat( float f )
  1045. {
  1046. PutType( f );
  1047. }
  1048. inline void CUtlBuffer::PutDouble( double d )
  1049. {
  1050. PutType( d );
  1051. }
  1052. inline void CUtlBuffer::PutPtr( void *p )
  1053. {
  1054. // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
  1055. if (!IsText())
  1056. {
  1057. PutTypeBin( p );
  1058. }
  1059. else
  1060. {
  1061. Printf( "0x%p", p );
  1062. }
  1063. }
  1064. //-----------------------------------------------------------------------------
  1065. // Am I a text buffer?
  1066. //-----------------------------------------------------------------------------
  1067. inline bool CUtlBuffer::IsText() const
  1068. {
  1069. return (m_Flags & TEXT_BUFFER) != 0;
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. // Can I grow if I'm externally allocated?
  1073. //-----------------------------------------------------------------------------
  1074. inline bool CUtlBuffer::IsGrowable() const
  1075. {
  1076. return (m_Flags & EXTERNAL_GROWABLE) != 0;
  1077. }
  1078. //-----------------------------------------------------------------------------
  1079. // Am I valid? (overflow or underflow error), Once invalid it stays invalid
  1080. //-----------------------------------------------------------------------------
  1081. inline bool CUtlBuffer::IsValid() const
  1082. {
  1083. return m_Error == 0;
  1084. }
  1085. //-----------------------------------------------------------------------------
  1086. // Do I contain carriage return/linefeeds?
  1087. //-----------------------------------------------------------------------------
  1088. inline bool CUtlBuffer::ContainsCRLF() const
  1089. {
  1090. return IsText() && ((m_Flags & CONTAINS_CRLF) != 0);
  1091. }
  1092. //-----------------------------------------------------------------------------
  1093. // Am I read-only
  1094. //-----------------------------------------------------------------------------
  1095. inline bool CUtlBuffer::IsReadOnly() const
  1096. {
  1097. return (m_Flags & READ_ONLY) != 0;
  1098. }
  1099. //-----------------------------------------------------------------------------
  1100. // Buffer base and size
  1101. //-----------------------------------------------------------------------------
  1102. inline const void* CUtlBuffer::Base() const
  1103. {
  1104. return m_Memory.Base();
  1105. }
  1106. inline void* CUtlBuffer::Base()
  1107. {
  1108. return m_Memory.Base();
  1109. }
  1110. inline int CUtlBuffer::Size() const
  1111. {
  1112. return m_Memory.NumAllocated();
  1113. }
  1114. //-----------------------------------------------------------------------------
  1115. // Clears out the buffer; frees memory
  1116. //-----------------------------------------------------------------------------
  1117. inline void CUtlBuffer::Clear()
  1118. {
  1119. m_Get = 0;
  1120. m_Put = 0;
  1121. m_Error = 0;
  1122. m_nOffset = 0;
  1123. m_nMaxPut = -1;
  1124. AddNullTermination( m_Put );
  1125. }
  1126. inline void CUtlBuffer::Purge()
  1127. {
  1128. m_Get = 0;
  1129. m_Put = 0;
  1130. m_nOffset = 0;
  1131. m_nMaxPut = 0;
  1132. m_Error = 0;
  1133. m_Memory.Purge();
  1134. }
  1135. //-----------------------------------------------------------------------------
  1136. //
  1137. //-----------------------------------------------------------------------------
  1138. inline void *CUtlBuffer::AccessForDirectRead( int nBytes )
  1139. {
  1140. Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 );
  1141. EnsureCapacity( nBytes );
  1142. m_nMaxPut = nBytes;
  1143. return Base();
  1144. }
  1145. inline void *CUtlBuffer::Detach()
  1146. {
  1147. void *p = m_Memory.Detach();
  1148. Clear();
  1149. return p;
  1150. }
  1151. //-----------------------------------------------------------------------------
  1152. inline void CUtlBuffer::Spew( )
  1153. {
  1154. SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  1155. char pTmpLine[1024];
  1156. while( IsValid() && GetBytesRemaining() )
  1157. {
  1158. V_memset( pTmpLine, 0, sizeof(pTmpLine) );
  1159. Get( pTmpLine, MIN( ( size_t )GetBytesRemaining(), sizeof(pTmpLine)-1 ) );
  1160. Msg( _T( "%s" ), pTmpLine );
  1161. }
  1162. }
  1163. #if !defined(_GAMECONSOLE)
  1164. inline void CUtlBuffer::SwapCopy( CUtlBuffer &other )
  1165. {
  1166. m_Get = other.m_Get;
  1167. m_Put = other.m_Put;
  1168. m_Error = other.m_Error;
  1169. m_Flags = other.m_Flags;
  1170. m_Reserved = other.m_Reserved;
  1171. m_nTab = other.m_nTab;
  1172. m_nMaxPut = other.m_nMaxPut;
  1173. m_nOffset = other.m_nOffset;
  1174. m_GetOverflowFunc = other.m_GetOverflowFunc;
  1175. m_PutOverflowFunc = other.m_PutOverflowFunc;
  1176. m_Byteswap = other.m_Byteswap;
  1177. m_Memory.Swap( other.m_Memory );
  1178. }
  1179. #endif
  1180. #endif // UTLBUFFER_H