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.

1094 lines
28 KiB

  1. //========= Copyright 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 "tier1/utlmemory.h"
  15. #include "tier1/byteswap.h"
  16. #include <stdarg.h>
  17. //-----------------------------------------------------------------------------
  18. // Forward declarations
  19. //-----------------------------------------------------------------------------
  20. struct characterset_t;
  21. //-----------------------------------------------------------------------------
  22. // Description of character conversions for string output
  23. // Here's an example of how to use the macros to define a character conversion
  24. // BEGIN_CHAR_CONVERSION( CStringConversion, '\\' )
  25. // { '\n', "n" },
  26. // { '\t', "t" }
  27. // END_CHAR_CONVERSION( CStringConversion, '\\' )
  28. //-----------------------------------------------------------------------------
  29. class CUtlCharConversion
  30. {
  31. public:
  32. struct ConversionArray_t
  33. {
  34. char m_nActualChar;
  35. const char *m_pReplacementString;
  36. };
  37. CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray );
  38. char GetEscapeChar() const;
  39. const char *GetDelimiter() const;
  40. int GetDelimiterLength() const;
  41. const char *GetConversionString( char c ) const;
  42. int GetConversionLength( char c ) const;
  43. int MaxConversionLength() const;
  44. // Finds a conversion for the passed-in string, returns length
  45. virtual char FindConversion( const char *pString, int *pLength );
  46. protected:
  47. struct ConversionInfo_t
  48. {
  49. int m_nLength;
  50. const char *m_pReplacementString;
  51. };
  52. char m_nEscapeChar;
  53. const char *m_pDelimiter;
  54. int m_nDelimiterLength;
  55. int m_nCount;
  56. int m_nMaxConversionLength;
  57. char m_pList[256];
  58. ConversionInfo_t m_pReplacements[256];
  59. };
  60. #define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
  61. static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
  62. #define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
  63. }; \
  64. CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
  65. #define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
  66. static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
  67. #define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
  68. }; \
  69. _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
  70. //-----------------------------------------------------------------------------
  71. // Character conversions for C strings
  72. //-----------------------------------------------------------------------------
  73. CUtlCharConversion *GetCStringCharConversion();
  74. //-----------------------------------------------------------------------------
  75. // Character conversions for quoted strings, with no escape sequences
  76. //-----------------------------------------------------------------------------
  77. CUtlCharConversion *GetNoEscCharConversion();
  78. //-----------------------------------------------------------------------------
  79. // Macro to set overflow functions easily
  80. //-----------------------------------------------------------------------------
  81. #define SetUtlBufferOverflowFuncs( _get, _put ) \
  82. SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
  83. //-----------------------------------------------------------------------------
  84. // Command parsing..
  85. //-----------------------------------------------------------------------------
  86. class CUtlBuffer
  87. {
  88. public:
  89. enum SeekType_t
  90. {
  91. SEEK_HEAD = 0,
  92. SEEK_CURRENT,
  93. SEEK_TAIL
  94. };
  95. // flags
  96. enum BufferFlags_t
  97. {
  98. TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
  99. EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
  100. CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
  101. READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
  102. AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
  103. };
  104. // Overflow functions when a get or put overflows
  105. typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize );
  106. // Constructors for growable + external buffers for serialization/unserialization
  107. CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
  108. CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
  109. // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
  110. CUtlBuffer( const void *pBuffer, int size, bool crap );
  111. unsigned char GetFlags() const;
  112. // NOTE: This will assert if you attempt to recast it in a way that
  113. // is not compatible. The only valid conversion is binary-> text w/CRLF
  114. void SetBufferType( bool bIsText, bool bContainsCRLF );
  115. // Makes sure we've got at least this much memory
  116. void EnsureCapacity( int num );
  117. // Attaches the buffer to external memory....
  118. void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
  119. bool IsExternallyAllocated() const;
  120. // Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
  121. void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
  122. // copies data from another buffer
  123. void CopyBuffer( const CUtlBuffer &buffer );
  124. void CopyBuffer( const void *pubData, int cubData );
  125. void Swap( CUtlBuffer &buf );
  126. void Swap( CUtlMemory<uint8> &mem );
  127. FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
  128. {
  129. if ( IsX360() )
  130. ActivateByteSwapping( true );
  131. }
  132. // Controls endian-ness of binary utlbufs - default matches the current platform
  133. void ActivateByteSwapping( bool bActivate );
  134. void SetBigEndian( bool bigEndian );
  135. bool IsBigEndian( void );
  136. // Resets the buffer; but doesn't free memory
  137. void Clear();
  138. // Clears out the buffer; frees memory
  139. void Purge();
  140. // Read stuff out.
  141. // Binary mode: it'll just read the bits directly in, and characters will be
  142. // read for strings until a null character is reached.
  143. // Text mode: it'll parse the file, turning text #s into real numbers.
  144. // GetString will read a string until a space is reached
  145. char GetChar( );
  146. unsigned char GetUnsignedChar( );
  147. short GetShort( );
  148. unsigned short GetUnsignedShort( );
  149. int GetInt( );
  150. int64 GetInt64( );
  151. int GetIntHex( );
  152. unsigned int GetUnsignedInt( );
  153. float GetFloat( );
  154. double GetDouble( );
  155. template <size_t maxLenInChars> void GetString( char( &pString )[maxLenInChars] )
  156. {
  157. GetStringInternal( pString, maxLenInChars );
  158. }
  159. void GetStringManualCharCount( char *pString, size_t maxLenInChars )
  160. {
  161. GetStringInternal( pString, maxLenInChars );
  162. }
  163. void Get( void* pMem, int size );
  164. void GetLine( char* pLine, int nMaxChars = 0 );
  165. // Used for getting objects that have a byteswap datadesc defined
  166. template <typename T> void GetObjects( T *dest, int count = 1 );
  167. // This will get at least 1 byte and up to nSize bytes.
  168. // It will return the number of bytes actually read.
  169. int GetUpTo( void *pMem, int nSize );
  170. // This version of GetString converts \" to \\ and " to \, etc.
  171. // It also reads a " at the beginning and end of the string
  172. void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 );
  173. char GetDelimitedChar( CUtlCharConversion *pConv );
  174. // This will return the # of characters of the string about to be read out
  175. // NOTE: The count will *include* the terminating 0!!
  176. // In binary mode, it's the number of characters until the next 0
  177. // In text mode, it's the number of characters until the next space.
  178. int PeekStringLength();
  179. // This version of PeekStringLength converts \" to \\ and " to \, etc.
  180. // It also reads a " at the beginning and end of the string
  181. // NOTE: The count will *include* the terminating 0!!
  182. // In binary mode, it's the number of characters until the next 0
  183. // In text mode, it's the number of characters between "s (checking for \")
  184. // Specifying false for bActualSize will return the pre-translated number of characters
  185. // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
  186. // and only 1 character when bActualSize == true
  187. int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true );
  188. // Just like scanf, but doesn't work in binary mode
  189. int Scanf( SCANF_FORMAT_STRING const char* pFmt, ... );
  190. int VaScanf( const char* pFmt, va_list list );
  191. // Eats white space, advances Get index
  192. void EatWhiteSpace();
  193. // Eats C++ style comments
  194. bool EatCPPComment();
  195. // (For text buffers only)
  196. // Parse a token from the buffer:
  197. // Grab all text that lies between a starting delimiter + ending delimiter
  198. // (skipping whitespace that leads + trails both delimiters).
  199. // If successful, the get index is advanced and the function returns true,
  200. // otherwise the index is not advanced and the function returns false.
  201. bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen );
  202. // Advance the get index until after the particular string is found
  203. // Do not eat whitespace before starting. Return false if it failed
  204. // String test is case-insensitive.
  205. bool GetToken( const char *pToken );
  206. // Parses the next token, given a set of character breaks to stop at
  207. // Returns the length of the token parsed in bytes (-1 if none parsed)
  208. int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true );
  209. // Write stuff in
  210. // Binary mode: it'll just write the bits directly in, and strings will be
  211. // written with a null terminating character
  212. // Text mode: it'll convert the numbers to text versions
  213. // PutString will not write a terminating character
  214. void PutChar( char c );
  215. void PutUnsignedChar( unsigned char uc );
  216. void PutUint64( uint64 ub );
  217. void PutInt16( int16 s16 );
  218. void PutShort( short s );
  219. void PutUnsignedShort( unsigned short us );
  220. void PutInt( int i );
  221. void PutInt64( int64 i );
  222. void PutUnsignedInt( unsigned int u );
  223. void PutFloat( float f );
  224. void PutDouble( double d );
  225. void PutString( const char* pString );
  226. void Put( const void* pMem, int size );
  227. // Used for putting objects that have a byteswap datadesc defined
  228. template <typename T> void PutObjects( T *src, int count = 1 );
  229. // This version of PutString converts \ to \\ and " to \", etc.
  230. // It also places " at the beginning and end of the string
  231. void PutDelimitedString( CUtlCharConversion *pConv, const char *pString );
  232. void PutDelimitedChar( CUtlCharConversion *pConv, char c );
  233. // Just like printf, writes a terminating zero in binary mode
  234. void Printf( PRINTF_FORMAT_STRING const char* pFmt, ... ) FMTFUNCTION( 2, 3 );
  235. void VaPrintf( const char* pFmt, va_list list );
  236. // What am I writing (put)/reading (get)?
  237. void* PeekPut( int offset = 0 );
  238. const void* PeekGet( int offset = 0 ) const;
  239. const void* PeekGet( int nMaxSize, int nOffset );
  240. // Where am I writing (put)/reading (get)?
  241. int TellPut( ) const;
  242. int TellGet( ) const;
  243. // What's the most I've ever written?
  244. int TellMaxPut( ) const;
  245. // How many bytes remain to be read?
  246. // NOTE: This is not accurate for streaming text files; it overshoots
  247. int GetBytesRemaining() const;
  248. // Change where I'm writing (put)/reading (get)
  249. void SeekPut( SeekType_t type, int offset );
  250. void SeekGet( SeekType_t type, int offset );
  251. // Buffer base
  252. const void* Base() const;
  253. void* Base();
  254. // Returns the base as a const char*, only valid in text mode.
  255. const char *String() const;
  256. // memory allocation size, does *not* reflect size written or read,
  257. // use TellPut or TellGet for that
  258. int Size() const;
  259. // Am I a text buffer?
  260. bool IsText() const;
  261. // Can I grow if I'm externally allocated?
  262. bool IsGrowable() const;
  263. // Am I valid? (overflow or underflow error), Once invalid it stays invalid
  264. bool IsValid() const;
  265. // Do I contain carriage return/linefeeds?
  266. bool ContainsCRLF() const;
  267. // Am I read-only
  268. bool IsReadOnly() const;
  269. // Converts a buffer from a CRLF buffer to a CR buffer (and back)
  270. // Returns false if no conversion was necessary (and outBuf is left untouched)
  271. // If the conversion occurs, outBuf will be cleared.
  272. bool ConvertCRLF( CUtlBuffer &outBuf );
  273. // Push/pop pretty-printing tabs
  274. void PushTab();
  275. void PopTab();
  276. // Temporarily disables pretty print
  277. void EnableTabs( bool bEnable );
  278. protected:
  279. // error flags
  280. enum
  281. {
  282. PUT_OVERFLOW = 0x1,
  283. GET_OVERFLOW = 0x2,
  284. MAX_ERROR_FLAG = GET_OVERFLOW,
  285. };
  286. void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc );
  287. bool OnPutOverflow( int nSize );
  288. bool OnGetOverflow( int nSize );
  289. protected:
  290. // Checks if a get/put is ok
  291. bool CheckPut( int size );
  292. bool CheckGet( int size );
  293. void AddNullTermination( );
  294. // Methods to help with pretty-printing
  295. bool WasLastCharacterCR();
  296. void PutTabs();
  297. // Help with delimited stuff
  298. char GetDelimitedCharInternal( CUtlCharConversion *pConv );
  299. void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c );
  300. // Default overflow funcs
  301. bool PutOverflow( int nSize );
  302. bool GetOverflow( int nSize );
  303. // Does the next bytes of the buffer match a pattern?
  304. bool PeekStringMatch( int nOffset, const char *pString, int nLen );
  305. // Peek size of line to come, check memory bound
  306. int PeekLineLength();
  307. // How much whitespace should I skip?
  308. int PeekWhiteSpace( int nOffset );
  309. // Checks if a peek get is ok
  310. bool CheckPeekGet( int nOffset, int nSize );
  311. // Call this to peek arbitrarily long into memory. It doesn't fail unless
  312. // it can't read *anything* new
  313. bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
  314. void GetStringInternal( char *pString, size_t maxLenInChars );
  315. template <typename T> void GetType( T& dest, const char *pszFmt );
  316. template <typename T> void GetTypeBin( T& dest );
  317. template <typename T> void GetObject( T *src );
  318. template <typename T> void PutType( T src, const char *pszFmt );
  319. template <typename T> void PutTypeBin( T src );
  320. template <typename T> void PutObject( T *src );
  321. CUtlMemory<unsigned char> m_Memory;
  322. int m_Get;
  323. int m_Put;
  324. unsigned char m_Error;
  325. unsigned char m_Flags;
  326. unsigned char m_Reserved;
  327. #if defined( _X360 )
  328. unsigned char pad;
  329. #endif
  330. int m_nTab;
  331. int m_nMaxPut;
  332. int m_nOffset;
  333. UtlBufferOverflowFunc_t m_GetOverflowFunc;
  334. UtlBufferOverflowFunc_t m_PutOverflowFunc;
  335. CByteswap m_Byteswap;
  336. };
  337. // Stream style output operators for CUtlBuffer
  338. inline CUtlBuffer &operator<<( CUtlBuffer &b, char v )
  339. {
  340. b.PutChar( v );
  341. return b;
  342. }
  343. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v )
  344. {
  345. b.PutUnsignedChar( v );
  346. return b;
  347. }
  348. inline CUtlBuffer &operator<<( CUtlBuffer &b, short v )
  349. {
  350. b.PutShort( v );
  351. return b;
  352. }
  353. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v )
  354. {
  355. b.PutUnsignedShort( v );
  356. return b;
  357. }
  358. inline CUtlBuffer &operator<<( CUtlBuffer &b, int v )
  359. {
  360. b.PutInt( v );
  361. return b;
  362. }
  363. inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v )
  364. {
  365. b.PutUnsignedInt( v );
  366. return b;
  367. }
  368. inline CUtlBuffer &operator<<( CUtlBuffer &b, float v )
  369. {
  370. b.PutFloat( v );
  371. return b;
  372. }
  373. inline CUtlBuffer &operator<<( CUtlBuffer &b, double v )
  374. {
  375. b.PutDouble( v );
  376. return b;
  377. }
  378. inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv )
  379. {
  380. b.PutString( pv );
  381. return b;
  382. }
  383. inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector &v )
  384. {
  385. b << v.x << " " << v.y << " " << v.z;
  386. return b;
  387. }
  388. inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector2D &v )
  389. {
  390. b << v.x << " " << v.y;
  391. return b;
  392. }
  393. class CUtlInplaceBuffer : public CUtlBuffer
  394. {
  395. public:
  396. CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
  397. //
  398. // Routines returning buffer-inplace-pointers
  399. //
  400. public:
  401. //
  402. // Upon success, determines the line length, fills out the pointer to the
  403. // beginning of the line and the line length, advances the "get" pointer
  404. // offset by the line length and returns "true".
  405. //
  406. // If end of file is reached or upon error returns "false".
  407. //
  408. // Note: the returned length of the line is at least one character because the
  409. // trailing newline characters are also included as part of the line.
  410. //
  411. // Note: the pointer returned points into the local memory of this buffer, in
  412. // case the buffer gets relocated or destroyed the pointer becomes invalid.
  413. //
  414. // e.g.: -------------
  415. //
  416. // char *pszLine;
  417. // int nLineLen;
  418. // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) )
  419. // {
  420. // ...
  421. // }
  422. //
  423. // -------------
  424. //
  425. // @param ppszInBufferPtr on return points into this buffer at start of line
  426. // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr)
  427. //
  428. // @returns true if line was successfully read
  429. // false when EOF is reached or error occurs
  430. //
  431. bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength );
  432. //
  433. // Determines the line length, advances the "get" pointer offset by the line length,
  434. // replaces the newline character with null-terminator and returns the initial pointer
  435. // to now null-terminated line.
  436. //
  437. // If end of file is reached or upon error returns NULL.
  438. //
  439. // Note: the pointer returned points into the local memory of this buffer, in
  440. // case the buffer gets relocated or destroyed the pointer becomes invalid.
  441. //
  442. // e.g.: -------------
  443. //
  444. // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() )
  445. // {
  446. // ...
  447. // }
  448. //
  449. // -------------
  450. //
  451. // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified
  452. // NULL when EOF is reached or error occurs
  453. //
  454. char * InplaceGetLinePtr( void );
  455. };
  456. //-----------------------------------------------------------------------------
  457. // Where am I reading?
  458. //-----------------------------------------------------------------------------
  459. inline int CUtlBuffer::TellGet( ) const
  460. {
  461. return m_Get;
  462. }
  463. //-----------------------------------------------------------------------------
  464. // How many bytes remain to be read?
  465. //-----------------------------------------------------------------------------
  466. inline int CUtlBuffer::GetBytesRemaining() const
  467. {
  468. return m_nMaxPut - TellGet();
  469. }
  470. //-----------------------------------------------------------------------------
  471. // What am I reading?
  472. //-----------------------------------------------------------------------------
  473. inline const void* CUtlBuffer::PeekGet( int offset ) const
  474. {
  475. return &m_Memory[ m_Get + offset - m_nOffset ];
  476. }
  477. //-----------------------------------------------------------------------------
  478. // Unserialization
  479. //-----------------------------------------------------------------------------
  480. template <typename T>
  481. inline void CUtlBuffer::GetObject( T *dest )
  482. {
  483. if ( CheckGet( sizeof(T) ) )
  484. {
  485. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  486. {
  487. *dest = *(T *)PeekGet();
  488. }
  489. else
  490. {
  491. m_Byteswap.SwapFieldsToTargetEndian<T>( dest, (T*)PeekGet() );
  492. }
  493. m_Get += sizeof(T);
  494. }
  495. else
  496. {
  497. Q_memset( dest, 0, sizeof(T) );
  498. }
  499. }
  500. template <typename T>
  501. inline void CUtlBuffer::GetObjects( T *dest, int count )
  502. {
  503. for ( int i = 0; i < count; ++i, ++dest )
  504. {
  505. GetObject<T>( dest );
  506. }
  507. }
  508. template <typename T>
  509. inline void CUtlBuffer::GetTypeBin( T &dest )
  510. {
  511. if ( CheckGet( sizeof(T) ) )
  512. {
  513. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  514. {
  515. dest = *(T *)PeekGet();
  516. }
  517. else
  518. {
  519. m_Byteswap.SwapBufferToTargetEndian<T>( &dest, (T*)PeekGet() );
  520. }
  521. m_Get += sizeof(T);
  522. }
  523. else
  524. {
  525. dest = 0;
  526. }
  527. }
  528. template <>
  529. inline void CUtlBuffer::GetTypeBin< float >( float &dest )
  530. {
  531. if ( CheckGet( sizeof( float ) ) )
  532. {
  533. uintptr_t pData = (uintptr_t)PeekGet();
  534. if ( IsX360() && ( pData & 0x03 ) )
  535. {
  536. // handle unaligned read
  537. ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
  538. ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
  539. ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
  540. ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
  541. }
  542. else
  543. {
  544. // aligned read
  545. dest = *(float *)pData;
  546. }
  547. if ( m_Byteswap.IsSwappingBytes() )
  548. {
  549. m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest );
  550. }
  551. m_Get += sizeof( float );
  552. }
  553. else
  554. {
  555. dest = 0;
  556. }
  557. }
  558. template <typename T>
  559. inline void CUtlBuffer::GetType( T &dest, const char *pszFmt )
  560. {
  561. if (!IsText())
  562. {
  563. GetTypeBin( dest );
  564. }
  565. else
  566. {
  567. dest = 0;
  568. Scanf( pszFmt, &dest );
  569. }
  570. }
  571. inline char CUtlBuffer::GetChar( )
  572. {
  573. char c;
  574. GetType( c, "%c" );
  575. return c;
  576. }
  577. inline unsigned char CUtlBuffer::GetUnsignedChar( )
  578. {
  579. unsigned char c;
  580. GetType( c, "%u" );
  581. return c;
  582. }
  583. inline short CUtlBuffer::GetShort( )
  584. {
  585. short s;
  586. GetType( s, "%d" );
  587. return s;
  588. }
  589. inline unsigned short CUtlBuffer::GetUnsignedShort( )
  590. {
  591. unsigned short s;
  592. GetType( s, "%u" );
  593. return s;
  594. }
  595. inline int CUtlBuffer::GetInt( )
  596. {
  597. int i;
  598. GetType( i, "%d" );
  599. return i;
  600. }
  601. inline int64 CUtlBuffer::GetInt64( )
  602. {
  603. int64 i;
  604. GetType( i, "%lld" );
  605. return i;
  606. }
  607. inline int CUtlBuffer::GetIntHex( )
  608. {
  609. int i;
  610. GetType( i, "%x" );
  611. return i;
  612. }
  613. inline unsigned int CUtlBuffer::GetUnsignedInt( )
  614. {
  615. unsigned int u;
  616. GetType( u, "%u" );
  617. return u;
  618. }
  619. inline float CUtlBuffer::GetFloat( )
  620. {
  621. float f;
  622. GetType( f, "%f" );
  623. return f;
  624. }
  625. inline double CUtlBuffer::GetDouble( )
  626. {
  627. double d;
  628. GetType( d, "%f" );
  629. return d;
  630. }
  631. //-----------------------------------------------------------------------------
  632. // Where am I writing?
  633. //-----------------------------------------------------------------------------
  634. inline unsigned char CUtlBuffer::GetFlags() const
  635. {
  636. return m_Flags;
  637. }
  638. //-----------------------------------------------------------------------------
  639. //
  640. //-----------------------------------------------------------------------------
  641. inline bool CUtlBuffer::IsExternallyAllocated() const
  642. {
  643. return m_Memory.IsExternallyAllocated();
  644. }
  645. //-----------------------------------------------------------------------------
  646. // Where am I writing?
  647. //-----------------------------------------------------------------------------
  648. inline int CUtlBuffer::TellPut( ) const
  649. {
  650. return m_Put;
  651. }
  652. //-----------------------------------------------------------------------------
  653. // What's the most I've ever written?
  654. //-----------------------------------------------------------------------------
  655. inline int CUtlBuffer::TellMaxPut( ) const
  656. {
  657. return m_nMaxPut;
  658. }
  659. //-----------------------------------------------------------------------------
  660. // What am I reading?
  661. //-----------------------------------------------------------------------------
  662. inline void* CUtlBuffer::PeekPut( int offset )
  663. {
  664. return &m_Memory[m_Put + offset - m_nOffset];
  665. }
  666. //-----------------------------------------------------------------------------
  667. // Various put methods
  668. //-----------------------------------------------------------------------------
  669. template <typename T>
  670. inline void CUtlBuffer::PutObject( T *src )
  671. {
  672. if ( CheckPut( sizeof(T) ) )
  673. {
  674. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  675. {
  676. *(T *)PeekPut() = *src;
  677. }
  678. else
  679. {
  680. m_Byteswap.SwapFieldsToTargetEndian<T>( (T*)PeekPut(), src );
  681. }
  682. m_Put += sizeof(T);
  683. AddNullTermination();
  684. }
  685. }
  686. template <typename T>
  687. inline void CUtlBuffer::PutObjects( T *src, int count )
  688. {
  689. for ( int i = 0; i < count; ++i, ++src )
  690. {
  691. PutObject<T>( src );
  692. }
  693. }
  694. template <typename T>
  695. inline void CUtlBuffer::PutTypeBin( T src )
  696. {
  697. if ( CheckPut( sizeof(T) ) )
  698. {
  699. if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
  700. {
  701. *(T *)PeekPut() = src;
  702. }
  703. else
  704. {
  705. m_Byteswap.SwapBufferToTargetEndian<T>( (T*)PeekPut(), &src );
  706. }
  707. m_Put += sizeof(T);
  708. AddNullTermination();
  709. }
  710. }
  711. template <typename T>
  712. inline void CUtlBuffer::PutType( T src, const char *pszFmt )
  713. {
  714. if (!IsText())
  715. {
  716. PutTypeBin( src );
  717. }
  718. else
  719. {
  720. Printf( pszFmt, src );
  721. }
  722. }
  723. //-----------------------------------------------------------------------------
  724. // Methods to help with pretty-printing
  725. //-----------------------------------------------------------------------------
  726. inline bool CUtlBuffer::WasLastCharacterCR()
  727. {
  728. if ( !IsText() || (TellPut() == 0) )
  729. return false;
  730. return ( *( const char * )PeekPut( -1 ) == '\n' );
  731. }
  732. inline void CUtlBuffer::PutTabs()
  733. {
  734. int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab;
  735. for (int i = nTabCount; --i >= 0; )
  736. {
  737. PutTypeBin<char>( '\t' );
  738. }
  739. }
  740. //-----------------------------------------------------------------------------
  741. // Push/pop pretty-printing tabs
  742. //-----------------------------------------------------------------------------
  743. inline void CUtlBuffer::PushTab( )
  744. {
  745. ++m_nTab;
  746. }
  747. inline void CUtlBuffer::PopTab()
  748. {
  749. if ( --m_nTab < 0 )
  750. {
  751. m_nTab = 0;
  752. }
  753. }
  754. //-----------------------------------------------------------------------------
  755. // Temporarily disables pretty print
  756. //-----------------------------------------------------------------------------
  757. inline void CUtlBuffer::EnableTabs( bool bEnable )
  758. {
  759. if ( bEnable )
  760. {
  761. m_Flags &= ~AUTO_TABS_DISABLED;
  762. }
  763. else
  764. {
  765. m_Flags |= AUTO_TABS_DISABLED;
  766. }
  767. }
  768. inline void CUtlBuffer::PutChar( char c )
  769. {
  770. if ( WasLastCharacterCR() )
  771. {
  772. PutTabs();
  773. }
  774. PutTypeBin( c );
  775. }
  776. inline void CUtlBuffer::PutUnsignedChar( unsigned char c )
  777. {
  778. PutType( c, "%u" );
  779. }
  780. inline void CUtlBuffer::PutUint64( uint64 ub )
  781. {
  782. PutType( ub, "%llu" );
  783. }
  784. inline void CUtlBuffer::PutInt16( int16 s16 )
  785. {
  786. PutType( s16, "%d" );
  787. }
  788. inline void CUtlBuffer::PutShort( short s )
  789. {
  790. PutType( s, "%d" );
  791. }
  792. inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
  793. {
  794. PutType( s, "%u" );
  795. }
  796. inline void CUtlBuffer::PutInt( int i )
  797. {
  798. PutType( i, "%d" );
  799. }
  800. inline void CUtlBuffer::PutInt64( int64 i )
  801. {
  802. PutType( i, "%llu" );
  803. }
  804. inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
  805. {
  806. PutType( u, "%u" );
  807. }
  808. inline void CUtlBuffer::PutFloat( float f )
  809. {
  810. PutType( f, "%f" );
  811. }
  812. inline void CUtlBuffer::PutDouble( double d )
  813. {
  814. PutType( d, "%f" );
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Am I a text buffer?
  818. //-----------------------------------------------------------------------------
  819. inline bool CUtlBuffer::IsText() const
  820. {
  821. return (m_Flags & TEXT_BUFFER) != 0;
  822. }
  823. //-----------------------------------------------------------------------------
  824. // Can I grow if I'm externally allocated?
  825. //-----------------------------------------------------------------------------
  826. inline bool CUtlBuffer::IsGrowable() const
  827. {
  828. return (m_Flags & EXTERNAL_GROWABLE) != 0;
  829. }
  830. //-----------------------------------------------------------------------------
  831. // Am I valid? (overflow or underflow error), Once invalid it stays invalid
  832. //-----------------------------------------------------------------------------
  833. inline bool CUtlBuffer::IsValid() const
  834. {
  835. return m_Error == 0;
  836. }
  837. //-----------------------------------------------------------------------------
  838. // Do I contain carriage return/linefeeds?
  839. //-----------------------------------------------------------------------------
  840. inline bool CUtlBuffer::ContainsCRLF() const
  841. {
  842. return IsText() && ((m_Flags & CONTAINS_CRLF) != 0);
  843. }
  844. //-----------------------------------------------------------------------------
  845. // Am I read-only
  846. //-----------------------------------------------------------------------------
  847. inline bool CUtlBuffer::IsReadOnly() const
  848. {
  849. return (m_Flags & READ_ONLY) != 0;
  850. }
  851. //-----------------------------------------------------------------------------
  852. // Buffer base and size
  853. //-----------------------------------------------------------------------------
  854. inline const void* CUtlBuffer::Base() const
  855. {
  856. return m_Memory.Base();
  857. }
  858. inline void* CUtlBuffer::Base()
  859. {
  860. return m_Memory.Base();
  861. }
  862. // Returns the base as a const char*, only valid in text mode.
  863. inline const char *CUtlBuffer::String() const
  864. {
  865. Assert( IsText() );
  866. return reinterpret_cast<const char*>( m_Memory.Base() );
  867. }
  868. inline int CUtlBuffer::Size() const
  869. {
  870. return m_Memory.NumAllocated();
  871. }
  872. //-----------------------------------------------------------------------------
  873. // Clears out the buffer; frees memory
  874. //-----------------------------------------------------------------------------
  875. inline void CUtlBuffer::Clear()
  876. {
  877. m_Get = 0;
  878. m_Put = 0;
  879. m_Error = 0;
  880. m_nOffset = 0;
  881. m_nMaxPut = -1;
  882. AddNullTermination();
  883. }
  884. inline void CUtlBuffer::Purge()
  885. {
  886. m_Get = 0;
  887. m_Put = 0;
  888. m_nOffset = 0;
  889. m_nMaxPut = 0;
  890. m_Error = 0;
  891. m_Memory.Purge();
  892. }
  893. inline void CUtlBuffer::CopyBuffer( const CUtlBuffer &buffer )
  894. {
  895. CopyBuffer( buffer.Base(), buffer.TellPut() );
  896. }
  897. inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData )
  898. {
  899. Clear();
  900. if ( cubData )
  901. {
  902. Put( pubData, cubData );
  903. }
  904. }
  905. #endif // UTLBUFFER_H