1 //====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
2 //
3 // Purpose:
4 //
5 // $NoKeywords: $
6 //
7 // Serialization/unserialization buffer
8 //=============================================================================//
9
10 #ifndef UTLBUFFER_H
11 #define UTLBUFFER_H
12
13 #ifdef _WIN32
14 #pragma once
15 #endif
16
17 #include "tier1/utlmemory.h"
18 #include <stdarg.h>
19 //SDR_PUBLIC #include "tier1/utlstring.h"
20
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
38 CUtlCharConversion( const char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray );
39 char GetEscapeChar() const;
40 const char *GetDelimiter() const;
41 int GetDelimiterLength() const;
42
43 const char *GetConversionString( char c ) const;
44 int GetConversionLength( char c ) const;
45 int MaxConversionLength() const;
46
47 // Finds a conversion for the passed-in string, returns length
48 virtual char FindConversion( const char *pString, int *pLength );
49
50 protected:
51 struct ConversionInfo_t
52 {
53 int m_nLength;
54 const char *m_pReplacementString;
55 };
56
57 char m_nEscapeChar;
58 const char *m_pDelimiter;
59 int m_nDelimiterLength;
60 int m_nCount;
61 int m_nMaxConversionLength;
62 char m_pList[255];
63 ConversionInfo_t m_pReplacements[255];
64 };
65
66 #define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
67 static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
68
69 #define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
70 }; \
71 CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
72
73 #define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
74 static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
75
76 #define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
77 }; \
78 _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
79
80 //-----------------------------------------------------------------------------
81 // Character conversions for C strings
82 //-----------------------------------------------------------------------------
83 CUtlCharConversion *GetCStringCharConversion();
84
85 //-----------------------------------------------------------------------------
86 // Character conversions for quoted strings, with no escape sequences
87 //-----------------------------------------------------------------------------
88 CUtlCharConversion *GetNoEscCharConversion();
89
90
91 //-----------------------------------------------------------------------------
92 // Macro to set overflow functions easily
93 //-----------------------------------------------------------------------------
94 #define SetUtlBufferOverflowFuncs( _get, _put ) \
95 SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
96
97
98 //-----------------------------------------------------------------------------
99 // Command parsing..
100 //-----------------------------------------------------------------------------
101 class CUtlBuffer
102 {
103 public:
104 enum SeekType_t
105 {
106 SEEK_HEAD = 0,
107 SEEK_CURRENT,
108 SEEK_TAIL
109 };
110
111 // flags
112 enum BufferFlags_t
113 {
114 TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
115 EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
116 CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
117 READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
118 AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
119 LITTLE_ENDIAN_BUFFER = 0x20,// ensures that data is stored in little endian format
120 BIG_ENDIAN_BUFFER = 0x40, // ensures that data is stored in big endian format
121 };
122
123 // Overflow functions when a get or put overflows
124 typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize );
125
126 // Constructors for growable + external buffers for serialization/unserialization
127 CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
128 CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
129
130 unsigned char GetFlags() const;
131
132 // NOTE: This will assert if you attempt to recast it in a way that
133 // is not compatible. The only valid conversion is binary-> text w/CRLF
134 void SetBufferType( bool bIsText, bool bContainsCRLF );
135
136 // Makes sure we've got at least this much memory
137 void EnsureCapacity( int num );
138
139 // Attaches the buffer to external memory....
140 void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
141
142 // Attaches to an external buffer as read only. Will purge any existing buffer data
143 void SetReadOnlyBuffer( void *pMemory, int nSize );
144
145 // Controls endian-ness of binary utlbufs
146 // Resets the buffer; but doesn't free memory
147 void Clear();
148
149 // Clears out the buffer; frees memory
150 void Purge();
151
152 void Swap( CUtlBuffer &buf );
153 void TakeOwnershipOfMemory( CUtlMemory<uint8> &mem );
154 void ReleaseToMemory( CUtlMemory<uint8> &mem, int *punCurrentPut );
155
156 // detaches the memory, returns it, and clears the members (but detached memory is preserved)
157 void * DetachAndClear();
158
159 // copies data from another buffer
160 void CopyBuffer( const CUtlBuffer &buffer );
161 void CopyBuffer( const void *pubData, int cubData );
162
163
164 // Read stuff out.
165 // Binary mode: it'll just read the bits directly in, and characters will be
166 // read for strings until a null character is reached.
167 // Text mode: it'll parse the file, turning text #s into real numbers.
168 // GetString will read a string until a space is reached
169
170 char GetChar();
171 uint8 GetUint8();
172 short GetShort();
173 unsigned short GetUnsignedShort();
174 int GetInt();
175 int GetIntHex();
176 unsigned int GetUnsignedInt();
177 int16 GetInt16();
178 uint64 GetUnsignedInt64();
179 int64 GetInt64();
180 float GetFloat();
181 double GetDouble();
182 bool GetString( char *pString, int nMaxLen );
183 bool GetLine( char *pString, int nMaxLen );
184 const char* GetStringFast(); // binary mode only
185 bool Get( void* pMem, int size );
186
187 // This will get at least 1 byte and up to nSize bytes.
188 // It will return the number of bytes actually read.
189 int GetUpTo( void *pMem, int nSize );
190
191 // This version of GetString converts \" to \\ and " to \, etc.
192 // It also reads a " at the beginning and end of the string
193 void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars );
194 char GetDelimitedChar( CUtlCharConversion *pConv );
195
196 // This will return the # of characters of the string about to be read out
197 // NOTE: The count will *include* the terminating 0!!
198 // In binary mode, it's the number of characters until the next 0
199 // In text mode, it's the number of characters until the next space.
200 int PeekStringLength();
201
202 // This version of PeekStringLength converts \" to \\ and " to \, etc.
203 // It also reads a " at the beginning and end of the string
204 // NOTE: The count will *include* the terminating 0!!
205 // In binary mode, it's the number of characters until the next 0
206 // In text mode, it's the number of characters between "s (checking for \")
207 // Specifying false for bActualSize will return the pre-translated number of characters
208 // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
209 // and only 1 character when bActualSize == true
210 int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true );
211
212 // Just like scanf, but doesn't work in binary mode
213 int Scanf( SCANF_FORMAT_STRING const char* pFmt, ... );
214 int VaScanf( const char* pFmt, va_list list );
215
216 // Eats white space, advances Get index
217 void EatWhiteSpace();
218 // Eats white space, advances Get index - won't overflow if file ends with whitespace.
219 void EatWhiteSpaceNoOverflow();
220
221 // Eats C++ style comments
222 bool EatCPPComment();
223
224 // (For text buffers only)
225 // Parse a token from the buffer:
226 // Grab all text that lies between a starting delimiter + ending delimiter
227 // (skipping whitespace that leads + trails both delimiters).
228 // If successful, the get index is advanced and the function returns true,
229 // otherwise the index is not advanced and the function returns false.
230 bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen );
231
232 // Advance the get index until after the particular string is found
233 // Do not eat whitespace before starting. Return false if it failed
234 // String test is case-insensitive.
235 bool GetToken( const char *pToken );
236
237 // Write stuff in
238 // Binary mode: it'll just write the bits directly in, and strings will be
239 // written with a null terminating character
240 // Text mode: it'll convert the numbers to text versions
241 // PutString will not write a terminating character
242 void PutChar( char c );
243 void PutUint8( uint8 ub );
244 void PutShort( short s );
245 void PutUnsignedShort( unsigned short us );
246 void PutInt( int i );
247 void PutUnsignedInt( unsigned int u );
248 void PutInt16( int16 s16 );
249 void PutUnsignedInt64( uint64 u64 );
250 void PutInt64( int64 u64 );
251 void PutFloat( float f );
252 void PutDouble( double d );
253 void PutString( const char* pString );
254 void PutStringWithoutNull( const char* pString );
255 void Put( const void* pMem, int size );
256
257 // This version of PutString converts \ to \\ and " to \", etc.
258 // It also places " at the beginning and end of the string
259 void PutDelimitedString( CUtlCharConversion *pConv, const char *pString );
260 void PutDelimitedChar( CUtlCharConversion *pConv, char c );
261
262 // Just like printf, writes a terminating zero in binary mode
263 void Printf( PRINTF_FORMAT_STRING const char* pFmt, ... ) FMTFUNCTION( 2, 3 );
264 void VaPrintf( const char* pFmt, va_list list );
265
266 // What am I writing (put)/reading (get)?
267 void* PeekPut( int offset = 0 );
268 const void* PeekGet( ) const;
269 const void* PeekGet( int offset ) const;
270 const void* PeekGet( int nMaxSize, int nOffset );
271
272 // Reserve at least nBytes and return the pointer to the start of the reserved area.
273 // Like EnsureCapacity(TellPut()+nBytes) but non-exact; preserves geometric growth.
274 void *ReservePut( int nBytes );
275
276 // How many bytes remain to be read?
277 // NOTE: This is not accurate for streaming text files; it overshoots
278 int GetBytesRemaining() const;
279
280 // Where am I writing (put)/reading (get)?
281 int TellPut() const;
282 int TellGet() const;
283
284 // Change where I'm writing (put)/reading (get)
285 void SeekPut( SeekType_t type, int offset );
286 bool SeekGet( SeekType_t type, int offset );
287
288 // Buffer base
289 const void* Base() const;
290 void* Base();
291 // Returns the base as a const char*, only valid in text mode.
292 const char *String() const;
293 // Copies the content of the buffer into a string (valid for binary and text mode).
294 //SDR_PUBLIC void CopyToString( CUtlString &strText ) const;
295
296 // memory allocation size, does *not* reflect size written or read,
297 // use TellPut or TellGet for that
298 int Size() const; // FIXME will delete soon
299 int SizeAllocated() const;
300
301 // Am I a text buffer?
302 bool IsText() const;
303
304 // Am I externally allocated (may not be growable, check below)
305 bool IsExternallyAllocated() const;
306
307 // Can I grow if I'm externally allocated?
308 bool IsGrowable() const;
309
310 // Am I valid? (overflow or underflow error), Once invalid it stays invalid
311 bool IsValid() const;
312
313 // Do I contain carriage return/linefeeds?
314 bool ContainsCRLF() const;
315
316 // Am I read-only
317 bool IsReadOnly() const;
318
319 // Converts a buffer from a CRLF buffer to a CR buffer (and back)
320 // Returns false if no conversion was necessary (and outBuf is left untouched)
321 // If the conversion occurs, outBuf will be cleared.
322 bool ConvertCRLF( CUtlBuffer &outBuf );
323
324 // Push/pop pretty-printing tabs
325 void PushTab();
326 void PopTab();
327
328 // Temporarily disables pretty print
329 void EnableTabs( bool bEnable );
330
331 // Securely erases buffer
SecureZero()332 void SecureZero() { SecureZeroMemory( m_Memory.Base(), m_Memory.Count() ); }
333
334 protected:
335 // error flags
336 enum
337 {
338 PUT_OVERFLOW = 0x1,
339 GET_OVERFLOW = 0x2,
340 MAX_ERROR_FLAG = GET_OVERFLOW,
341 };
342
343 void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc );
344
345 bool OnPutOverflow( int nSize );
346 bool OnGetOverflow( int nSize );
347
348 protected:
349 // Checks if a get/put is ok
350 bool CheckPut( int size );
351 bool CheckGet( int size );
352
353 void AddNullTermination( );
354
355 // Methods to help with pretty-printing
356 bool WasLastCharacterCR();
357 void PutTabs();
358
359 // Help with delimited stuff
360 char GetDelimitedCharInternal( CUtlCharConversion *pConv );
361 void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c );
362
363 // Default overflow funcs
364 bool PutOverflow( int nSize );
365 bool GetOverflow( int nSize );
366
367 // Does the next bytes of the buffer match a pattern?
368 bool PeekStringMatch( int nOffset, const char *pString, int nLen );
369
370 // How much whitespace should I skip?
371 int PeekWhiteSpace( int nOffset );
372
373 // Checks if a peek get is ok
374 bool CheckPeekGet( int nOffset, int nSize );
375
376 // Call this to peek arbitrarily long into memory. It doesn't fail unless
377 // it can't read *anything* new
378 bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
379
380 CUtlMemory<uint8> m_Memory;
381 int m_Get;
382 int m_Put;
383
384 int m_nMaxPut;
385 uint16 m_nTab;
386
387 uint8 m_Error;
388 uint8 m_Flags;
389
390 UtlBufferOverflowFunc_t m_GetOverflowFunc;
391 UtlBufferOverflowFunc_t m_PutOverflowFunc;
392
393 private:
394 // Returns max amount of data written. Used internally but externally you should use put / seek
395 int TellMaxPut() const;
396
397 // Copy construction and assignment are not valid
398 CUtlBuffer(const CUtlBuffer& rhs);
399 const CUtlBuffer& operator=(const CUtlBuffer& rhs);
400 };
401
402
403 //-----------------------------------------------------------------------------
404 // Where am I reading?
405 //-----------------------------------------------------------------------------
TellGet()406 inline int CUtlBuffer::TellGet() const
407 {
408 return m_Get;
409 }
410
411
412 //-----------------------------------------------------------------------------
413 // How many bytes remain to be read?
414 //-----------------------------------------------------------------------------
GetBytesRemaining()415 inline int CUtlBuffer::GetBytesRemaining() const
416 {
417 return m_nMaxPut - TellGet();
418 }
419
420
421 //-----------------------------------------------------------------------------
422 // What am I reading?
423 //-----------------------------------------------------------------------------
PeekGet(int offset)424 inline const void* CUtlBuffer::PeekGet( int offset ) const
425 {
426 return &m_Memory[ m_Get + offset ];
427 }
428
429 //-----------------------------------------------------------------------------
430 // no offset so optimizer can resolve the function
431 //-----------------------------------------------------------------------------
PeekGet()432 inline const void* CUtlBuffer::PeekGet() const
433 {
434 return &m_Memory[ m_Get ];
435 }
436
437 //-----------------------------------------------------------------------------
438 // Reserve nBytes at the put location and return pointer; follow with SeekPut
439 //-----------------------------------------------------------------------------
ReservePut(int nBytes)440 inline void *CUtlBuffer::ReservePut( int nBytes )
441 {
442 return CheckPut( nBytes ) ? PeekPut() : NULL;
443 }
444
445 //-----------------------------------------------------------------------------
446 // Unserialization
447 //-----------------------------------------------------------------------------
448 #if defined(__arm__) || defined(__arm64__)
449 #define COPY_TYPE( _type, _val ) V_memcpy( &_val, PeekGet(), sizeof( _type ) )
450 #else
451 #define COPY_TYPE( _type, _val ) _val = *(_type *)PeekGet()
452 #endif
453 #define GET_TYPE( _type, _val, _fmt ) \
454 if ( !IsText() ) \
455 { \
456 if (CheckGet( sizeof(_type) )) \
457 { \
458 if ( (sizeof(_type)>1) && (m_Flags & CUtlBuffer::LITTLE_ENDIAN_BUFFER ) ) \
459 { \
460 if( sizeof(_type) == 2 ) \
461 { \
462 _val = LittleWord( (uint16)*(_type *)PeekGet() ); \
463 } \
464 else if ( sizeof(_type) == 4 ) \
465 { \
466 _val = LittleDWord( (uint32)*(_type *)PeekGet() ); \
467 } \
468 else if ( sizeof(_type) == 8 ) \
469 { \
470 _val = LittleQWord( (uint64)*(_type *)PeekGet() ); \
471 } \
472 else \
473 { \
474 Assert( !"Type not supported" ); \
475 } \
476 } \
477 else if ( (sizeof(_type)>1) && (m_Flags & CUtlBuffer::BIG_ENDIAN_BUFFER ) ) \
478 { \
479 if( sizeof(_type) == 2 ) \
480 { \
481 _val = BigWord( (uint16)*(_type *)PeekGet() ); \
482 } \
483 else if ( sizeof(_type) == 4 ) \
484 { \
485 _val = BigDWord( (uint32)*(_type *)PeekGet() ); \
486 } \
487 else if ( sizeof(_type) == 8 ) \
488 { \
489 _val = BigQWord( (uint64)*(_type *)PeekGet() ); \
490 } \
491 else \
492 { \
493 Assert( !"Type not supported" ); \
494 } \
495 } \
496 else \
497 { \
498 COPY_TYPE( _type, _val ); \
499 } \
500 m_Get += sizeof(_type); \
501 } \
502 else \
503 { \
504 _val = 0; \
505 } \
506 } \
507 else \
508 { \
509 _val = 0; \
510 Scanf( _fmt, &_val ); \
511 }
512
513
514 //-----------------------------------------------------------------------------
515 // Where am I writing?
516 //-----------------------------------------------------------------------------
GetFlags()517 inline unsigned char CUtlBuffer::GetFlags() const
518 {
519 return m_Flags;
520 }
521
522
523 //-----------------------------------------------------------------------------
524 // Where am I writing?
525 //-----------------------------------------------------------------------------
TellPut()526 inline int CUtlBuffer::TellPut() const
527 {
528 return m_Put;
529 }
530
531
532 //-----------------------------------------------------------------------------
533 // What's the most I've ever written?
534 //-----------------------------------------------------------------------------
TellMaxPut()535 inline int CUtlBuffer::TellMaxPut( ) const
536 {
537 return m_nMaxPut;
538 }
539
540
541 //-----------------------------------------------------------------------------
542 // What am I reading?
543 //-----------------------------------------------------------------------------
PeekPut(int offset)544 inline void* CUtlBuffer::PeekPut( int offset )
545 {
546 return &m_Memory[m_Put + offset];
547 }
548
549
550 //-----------------------------------------------------------------------------
551 //-----------------------------------------------------------------------------
552 // Various put methods
553 //-----------------------------------------------------------------------------
554 #define PUT_BIN_DATA( _type, _val ) \
555 if ( CheckPut( sizeof(_type) ) ) \
556 { \
557 if ( (sizeof(_type)>1) && (m_Flags & CUtlBuffer::LITTLE_ENDIAN_BUFFER ) ) \
558 { \
559 if( sizeof(_type) == 2 ) \
560 { \
561 *(_type *)PeekPut() = (_type)LittleWord( (uint16)_val ); \
562 } \
563 else if ( sizeof(_type) == 4 ) \
564 { \
565 *(_type *)PeekPut() = (_type)LittleDWord( (uint32)_val ); \
566 } \
567 else if ( sizeof(_type) == 8 ) \
568 { \
569 *(_type *)PeekPut() = (_type)LittleQWord( (uint64)_val ); \
570 } \
571 else \
572 { \
573 Assert( !"Type not supported" ); \
574 } \
575 } \
576 else if ( (sizeof(_type)>1) && (m_Flags & CUtlBuffer::BIG_ENDIAN_BUFFER ) ) \
577 { \
578 if( sizeof(_type) == 2 ) \
579 { \
580 *(_type *)PeekPut() = (_type)BigWord( (uint16)_val ); \
581 } \
582 else if ( sizeof(_type) == 4 ) \
583 { \
584 *(_type *)PeekPut() = (_type)BigDWord( (uint32)_val ); \
585 } \
586 else if ( sizeof(_type) == 8 ) \
587 { \
588 *(_type *)PeekPut() = (_type)BigQWord( (uint64)_val ); \
589 } \
590 else \
591 { \
592 Assert( !"Type not supported" ); \
593 } \
594 } \
595 else \
596 { \
597 *(_type *)PeekPut() = _val; \
598 } \
599 m_Put += sizeof(_type); \
600 AddNullTermination(); \
601 } \
602
603
604 #define PUT_TYPE( _type, _val ) \
605 if (!IsText()) \
606 { \
607 PUT_BIN_DATA( _type, _val ); \
608 } \
609 else \
610 { \
611 PutString( CNumStr( _val ) ); \
612 }
613
614
615 //-----------------------------------------------------------------------------
616 // Methods to help with pretty-printing
617 //-----------------------------------------------------------------------------
WasLastCharacterCR()618 inline bool CUtlBuffer::WasLastCharacterCR()
619 {
620 if ( !IsText() || (TellPut() == 0) )
621 return false;
622 return ( *( const char * )PeekPut( -1 ) == '\n' );
623 }
624
PutTabs()625 inline void CUtlBuffer::PutTabs()
626 {
627 int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab;
628 for (int i = nTabCount; --i >= 0; )
629 {
630 PUT_BIN_DATA( char, '\t' );
631 }
632 }
633
634
635 //-----------------------------------------------------------------------------
636 // Push/pop pretty-printing tabs
637 //-----------------------------------------------------------------------------
PushTab()638 inline void CUtlBuffer::PushTab( )
639 {
640 ++m_nTab;
641 }
642
PopTab()643 inline void CUtlBuffer::PopTab()
644 {
645 if ( m_nTab )
646 {
647 m_nTab--;
648 }
649 }
650
651
652 //-----------------------------------------------------------------------------
653 // Temporarily disables pretty print
654 //-----------------------------------------------------------------------------
EnableTabs(bool bEnable)655 inline void CUtlBuffer::EnableTabs( bool bEnable )
656 {
657 if ( bEnable )
658 {
659 m_Flags &= ~AUTO_TABS_DISABLED;
660 }
661 else
662 {
663 m_Flags |= AUTO_TABS_DISABLED;
664 }
665 }
666
667
668 //-----------------------------------------------------------------------------
669 // Am I a text buffer?
670 //-----------------------------------------------------------------------------
IsText()671 inline bool CUtlBuffer::IsText() const
672 {
673 return (m_Flags & TEXT_BUFFER) != 0;
674 }
675
676
677 //-----------------------------------------------------------------------------
678 // Can I grow if I'm externally allocated?
679 //-----------------------------------------------------------------------------
IsGrowable()680 inline bool CUtlBuffer::IsGrowable() const
681 {
682 return (m_Flags & EXTERNAL_GROWABLE) != 0;
683 }
684
685 //-----------------------------------------------------------------------------
686 // Am I externally allocated (may need to check IsGrowable or can't grow buffer)
687 //-----------------------------------------------------------------------------
IsExternallyAllocated()688 inline bool CUtlBuffer::IsExternallyAllocated() const
689 {
690 return m_Memory.IsExternallyAllocated();
691 }
692
693 //-----------------------------------------------------------------------------
694 // Am I valid? (overflow or underflow error), Once invalid it stays invalid
695 //-----------------------------------------------------------------------------
IsValid()696 inline bool CUtlBuffer::IsValid() const
697 {
698 return m_Error == 0;
699 }
700
701
702 //-----------------------------------------------------------------------------
703 // Do I contain carriage return/linefeeds?
704 //-----------------------------------------------------------------------------
ContainsCRLF()705 inline bool CUtlBuffer::ContainsCRLF() const
706 {
707 return IsText() && ((m_Flags & CONTAINS_CRLF) != 0);
708 }
709
710
711 //-----------------------------------------------------------------------------
712 // Am I read-only
713 //-----------------------------------------------------------------------------
IsReadOnly()714 inline bool CUtlBuffer::IsReadOnly() const
715 {
716 return (m_Flags & READ_ONLY) != 0;
717 }
718
719
720 //-----------------------------------------------------------------------------
721 // Buffer base and size
722 //-----------------------------------------------------------------------------
Base()723 inline const void* CUtlBuffer::Base() const
724 {
725 return m_Memory.Base();
726 }
727
Base()728 inline void* CUtlBuffer::Base()
729 {
730 return m_Memory.Base();
731 }
732
733 // Returns the base as a const char*, only valid in text mode.
String()734 inline const char *CUtlBuffer::String() const
735 {
736 Assert( IsText() );
737 const char *pchReturn = reinterpret_cast<const char*>( m_Memory.Base() );
738 // Never return NULL
739 if ( pchReturn )
740 return pchReturn;
741 else
742 return "";
743 }
744
745 //SDR_PUBLIC inline void CUtlBuffer::CopyToString( CUtlString &strText ) const
746 //SDR_PUBLIC {
747 //SDR_PUBLIC strText.SetDirect( (const char *)Base(), TellMaxPut() );
748 //SDR_PUBLIC }
749
750
Size()751 inline int CUtlBuffer::Size() const // FIXME delete soon
752 {
753 return m_Memory.NumAllocated();
754 }
SizeAllocated()755 inline int CUtlBuffer::SizeAllocated() const
756 {
757 return m_Memory.NumAllocated();
758 }
759
760
761 //-----------------------------------------------------------------------------
762 // Clears out the buffer; does not free memory
763 //-----------------------------------------------------------------------------
Clear()764 inline void CUtlBuffer::Clear()
765 {
766 m_Get = 0;
767 m_Put = 0;
768 m_Error = 0;
769 m_nMaxPut = -1;
770 AddNullTermination();
771 }
772
773 //-----------------------------------------------------------------------------
774 // Clears out the buffer; frees memory
775 //-----------------------------------------------------------------------------
Purge()776 inline void CUtlBuffer::Purge()
777 {
778 m_Get = 0;
779 m_Put = 0;
780 m_nMaxPut = 0;
781 m_Error = 0;
782 m_Memory.Purge();
783 }
784
CopyBuffer(const CUtlBuffer & buffer)785 inline void CUtlBuffer::CopyBuffer( const CUtlBuffer &buffer )
786 {
787 CopyBuffer( buffer.Base(), buffer.TellPut() );
788 }
789
CopyBuffer(const void * pubData,int cubData)790 inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData )
791 {
792 Clear();
793 if ( cubData )
794 {
795 Put( pubData, cubData );
796 }
797 }
798
799
800 /// CUtlBuffer that will wipe upon destruction
801 //
802 /// WARNING: This is only intended for simple use cases where the caller
803 /// can easily pre-allocate. For example, it won't wipe if the buffer needs
804 /// to be relocated as a result of realloc. Or if you pas it to a function
805 /// via a CUtlBuffer&, and CUtlBuffer::Purge is invoked directly. Etc.
806 class CAutoWipeBuffer : public CUtlBuffer
807 {
808 public:
CAutoWipeBuffer()809 CAutoWipeBuffer() {}
CAutoWipeBuffer(int cbInit)810 explicit CAutoWipeBuffer( int cbInit ) : CUtlBuffer( 0, cbInit, 0 ) {}
~CAutoWipeBuffer()811 ~CAutoWipeBuffer() { Purge(); }
812
Clear()813 void Clear()
814 {
815 SecureZeroMemory( Base(), SizeAllocated() );
816 CUtlBuffer::Clear();
817 }
818
Purge()819 void Purge()
820 {
821 Clear();
822 CUtlBuffer::Purge();
823 }
824 };
825
826 #endif // UTLBUFFER_H
827
828