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.

469 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef UTLSTRING_H
  7. #define UTLSTRING_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier1/utlmemory.h"
  12. #include "tier1/strtools.h"
  13. #include "limits.h"
  14. // Matched with the memdbgoff at end of header
  15. #include "memdbgon.h"
  16. #if defined( OSX )
  17. #ifndef wcsdup
  18. // The mem override tools may provide a copy of this if active, otherwise it is not available in OS X's libc due to
  19. // being introduced in POSIX-20008
  20. inline wchar_t *wcsdup(const wchar_t *pString)
  21. {
  22. wchar_t *pMemory;
  23. if (!pString)
  24. return NULL;
  25. size_t len = (wcslen(pString) + 1);
  26. if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL)
  27. {
  28. return wcscpy( pMemory, pString );
  29. }
  30. return NULL;
  31. }
  32. #endif
  33. inline size_t strnlen(const char *s, size_t n)
  34. {
  35. const char *p = (const char *)memchr(s, 0, n);
  36. return (p ? p - s : n);
  37. }
  38. #endif
  39. //-----------------------------------------------------------------------------
  40. // Simple string class.
  41. // NOTE: This is *not* optimal! Use in tools, but not runtime code
  42. //-----------------------------------------------------------------------------
  43. class CUtlString
  44. {
  45. public:
  46. typedef enum
  47. {
  48. PATTERN_NONE = 0x00000000,
  49. PATTERN_DIRECTORY = 0x00000001
  50. } TUtlStringPattern;
  51. public:
  52. CUtlString();
  53. CUtlString( const char *pString );
  54. CUtlString( const char *pString, int length );
  55. CUtlString( const CUtlString& string );
  56. #ifdef MOVE_CONSTRUCTOR_SUPPORT
  57. // Support moving of CUtlString objects. Long live C++11
  58. // This move constructor will get called when appropriate, such as when
  59. // returning objects from functions, or otherwise copying from temporaries
  60. // which are about to be destroyed. It can also be explicitly invoked with
  61. // std::move().
  62. // Move constructor:
  63. CUtlString( CUtlString&& rhs )
  64. {
  65. // Move the string pointer from the source to this -- be sure to
  66. // zero out the source to avoid double frees.
  67. m_pString = rhs.m_pString;
  68. rhs.m_pString = 0;
  69. }
  70. // Move assignment operator:
  71. CUtlString& operator=( CUtlString&& rhs )
  72. {
  73. // Move the string pointer from the source to this -- be sure to
  74. // zero out the source to avoid double frees.
  75. m_pString = rhs.m_pString;
  76. rhs.m_pString = 0;
  77. return *this;
  78. }
  79. #endif
  80. ~CUtlString();
  81. const char *Get( ) const;
  82. void Set( const char *pValue );
  83. operator const char*() const;
  84. // Set directly and don't look for a null terminator in pValue.
  85. // nChars does not include the nul and this will only copy
  86. // at most nChars (even if pValue is longer). If nChars
  87. // is >strlen(pValue) it will copy past the end, don't do it
  88. // Does nothing if pValue == String()
  89. void SetDirect( const char *pValue, int nChars );
  90. // for compatibility switching items from UtlSymbol
  91. const char *String() const { return Get(); }
  92. // Returns strlen
  93. int Length() const;
  94. // IsEmpty() is more efficient than Length() == 0
  95. bool IsEmpty() const;
  96. // Sets the length (used to serialize into the buffer )
  97. // Note: If nLen != 0, then this adds an extra byte for a null-terminator.
  98. void SetLength( int nLen );
  99. char *GetForModify();
  100. void Clear();
  101. void Purge();
  102. // Case Change
  103. void ToLower();
  104. void ToUpper();
  105. void Append( const char *pAddition, int nChars );
  106. void Append( const char *pchAddition );
  107. void Append( const char chAddition ) { char temp[2] = { chAddition, 0 }; Append( temp ); }
  108. // Strips the trailing slash
  109. void StripTrailingSlash();
  110. void FixSlashes( char cSeparator = CORRECT_PATH_SEPARATOR );
  111. // Trim whitespace
  112. void TrimLeft( char cTarget );
  113. void TrimLeft( const char *szTargets = "\t\r\n " );
  114. void TrimRight( char cTarget );
  115. void TrimRight( const char *szTargets = "\t\r\n " );
  116. void Trim( char cTarget );
  117. void Trim( const char *szTargets = "\t\r\n " );
  118. bool IsEqual_CaseSensitive( const char *src ) const;
  119. bool IsEqual_CaseInsensitive( const char *src ) const;
  120. CUtlString &operator=( const CUtlString &src );
  121. CUtlString &operator=( const char *src );
  122. // Test for equality
  123. bool operator==( const CUtlString &src ) const;
  124. bool operator!=( const CUtlString &src ) const { return !operator==( src ); }
  125. CUtlString &operator+=( const CUtlString &rhs );
  126. CUtlString &operator+=( const char *rhs );
  127. CUtlString &operator+=( char c );
  128. CUtlString &operator+=( int rhs );
  129. CUtlString &operator+=( double rhs );
  130. CUtlString operator+( const char *pOther ) const;
  131. CUtlString operator+( const CUtlString &other ) const;
  132. CUtlString operator+( int rhs ) const;
  133. bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ) const; // case SENSITIVE, use * for wildcard in pattern string
  134. char operator[]( int i ) const;
  135. #if ! defined(SWIG)
  136. // Don't let SWIG see the PRINTF_FORMAT_STRING attribute or it will complain.
  137. int Format( PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 2, 3 );
  138. int FormatV( PRINTF_FORMAT_STRING const char *pFormat, va_list marker );
  139. #else
  140. int Format( const char *pFormat, ... );
  141. int FormatV( const char *pFormat, va_list marker );
  142. #endif
  143. // Defining AltArgumentType_t hints that associative container classes should
  144. // also implement Find/Insert/Remove functions that take const char* params.
  145. typedef const char *AltArgumentType_t;
  146. // Get a copy of part of the string.
  147. // If you only specify nStart, it'll go from nStart to the end.
  148. // You can use negative numbers and it'll wrap around to the start.
  149. CUtlString Slice( int32 nStart=0, int32 nEnd=INT_MAX ) const;
  150. // Get a substring starting from the left or the right side.
  151. CUtlString Left( int32 nChars ) const;
  152. CUtlString Right( int32 nChars ) const;
  153. // Get a string with all instances of one character replaced with another.
  154. CUtlString Replace( char cFrom, char cTo ) const;
  155. // Replace all instances of specified string with another.
  156. CUtlString Replace( const char *pszFrom, const char *pszTo ) const;
  157. // Get this string as an absolute path (calls right through to V_MakeAbsolutePath).
  158. CUtlString AbsPath( const char *pStartingDir=NULL ) const;
  159. // Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
  160. CUtlString UnqualifiedFilename() const;
  161. // Gets a string with one directory removed. Uses V_StripLastDir but strips the last slash also!
  162. CUtlString DirName() const;
  163. // Get a string with the extension removed (with V_StripExtension).
  164. CUtlString StripExtension() const;
  165. // Get a string with the filename removed (uses V_UnqualifiedFileName and also strips the last slash)
  166. CUtlString StripFilename() const;
  167. // Get a string with the base filename (with V_FileBase).
  168. CUtlString GetBaseFilename() const;
  169. // Get a string with the file extension (with V_FileBase).
  170. CUtlString GetExtension() const;
  171. // Works like V_ComposeFileName.
  172. static CUtlString PathJoin( const char *pStr1, const char *pStr2 );
  173. // These can be used for utlvector sorts.
  174. static int __cdecl SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 );
  175. static int __cdecl SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 );
  176. // Empty string for those times when you need to return an empty string and
  177. // either don't want to pay the construction cost, or are returning a
  178. // const CUtlString& and cannot just return "".
  179. static const CUtlString &GetEmptyString();
  180. private:
  181. // INTERNALS
  182. // AllocMemory allocates enough space for length characters plus a terminating zero.
  183. // Previous characters are preserved, the buffer is null-terminated, but new characters
  184. // are not touched.
  185. void *AllocMemory( uint32 length );
  186. // If m_pString is not NULL, it points to the start of the string, and the memory allocation.
  187. char *m_pString;
  188. };
  189. // // If these are not defined, CUtlConstString as rhs will auto-convert
  190. // // to const char* and do logical operations on the raw pointers. Ugh.
  191. // inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; }
  192. // inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; }
  193. // inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; }
  194. inline bool operator==( const char *pString, const CUtlString &utlString )
  195. {
  196. return utlString.IsEqual_CaseSensitive( pString );
  197. }
  198. inline bool operator!=( const char *pString, const CUtlString &utlString )
  199. {
  200. return !utlString.IsEqual_CaseSensitive( pString );
  201. }
  202. inline bool operator==( const CUtlString &utlString, const char *pString )
  203. {
  204. return utlString.IsEqual_CaseSensitive( pString );
  205. }
  206. inline bool operator!=( const CUtlString &utlString, const char *pString )
  207. {
  208. return !utlString.IsEqual_CaseSensitive( pString );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Inline methods
  212. //-----------------------------------------------------------------------------
  213. inline CUtlString::CUtlString()
  214. : m_pString( NULL )
  215. {
  216. }
  217. inline CUtlString::CUtlString( const char *pString )
  218. : m_pString( NULL )
  219. {
  220. Set( pString );
  221. }
  222. inline CUtlString::CUtlString( const char *pString, int length )
  223. : m_pString( NULL )
  224. {
  225. SetDirect( pString, length );
  226. }
  227. inline CUtlString::CUtlString( const CUtlString& string )
  228. : m_pString( NULL )
  229. {
  230. Set( string.Get() );
  231. }
  232. inline CUtlString::~CUtlString()
  233. {
  234. Purge();
  235. }
  236. inline int CUtlString::Length() const
  237. {
  238. if (m_pString)
  239. {
  240. return V_strlen( m_pString );
  241. }
  242. return 0;
  243. }
  244. inline bool CUtlString::IsEmpty() const
  245. {
  246. return !m_pString || m_pString[0] == 0;
  247. }
  248. inline int __cdecl CUtlString::SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 )
  249. {
  250. return V_stricmp( pString1->String(), pString2->String() );
  251. }
  252. inline int __cdecl CUtlString::SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 )
  253. {
  254. return V_strcmp( pString1->String(), pString2->String() );
  255. }
  256. // Converts to c-strings
  257. inline CUtlString::operator const char*() const
  258. {
  259. return Get();
  260. }
  261. //-----------------------------------------------------------------------------
  262. // Purpose: Implementation of low-level string functionality for character types.
  263. //-----------------------------------------------------------------------------
  264. template < typename T >
  265. class StringFuncs
  266. {
  267. public:
  268. static T *Duplicate( const T *pValue );
  269. // Note that this function takes a character count, and does not guarantee null-termination.
  270. static void Copy( T *out_pOut, const T *pIn, int iLengthInChars );
  271. static int Compare( const T *pLhs, const T *pRhs );
  272. static int CaselessCompare( const T *pLhs, const T *pRhs );
  273. static int Length( const T *pValue );
  274. static const T *FindChar( const T *pStr, const T cSearch );
  275. static const T *EmptyString();
  276. static const T *NullDebugString();
  277. };
  278. template < >
  279. class StringFuncs<char>
  280. {
  281. public:
  282. static char *Duplicate( const char *pValue ) { return strdup( pValue ); }
  283. // Note that this function takes a character count, and does not guarantee null-termination.
  284. static void Copy( OUT_CAP(iLengthInChars) char *out_pOut, const char *pIn, int iLengthInChars ) { strncpy( out_pOut, pIn, iLengthInChars ); }
  285. static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); }
  286. static int CaselessCompare( const char *pLhs, const char *pRhs ) { return Q_strcasecmp( pLhs, pRhs ); }
  287. static int Length( const char *pValue ) { return (int)strlen( pValue ); }
  288. static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); }
  289. static const char *EmptyString() { return ""; }
  290. static const char *NullDebugString() { return "(null)"; }
  291. };
  292. template < >
  293. class StringFuncs<wchar_t>
  294. {
  295. public:
  296. static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); }
  297. // Note that this function takes a character count, and does not guarantee null-termination.
  298. static void Copy( OUT_CAP(iLengthInChars) wchar_t *out_pOut, const wchar_t *pIn, int iLengthInChars ) { wcsncpy( out_pOut, pIn, iLengthInChars ); }
  299. static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); }
  300. static int CaselessCompare( const wchar_t *pLhs, const wchar_t *pRhs ); // no implementation?
  301. static int Length( const wchar_t *pValue ) { return (int)wcslen( pValue ); }
  302. static const wchar_t *FindChar( const wchar_t *pStr, const wchar_t cSearch ) { return wcschr( pStr, cSearch ); }
  303. static const wchar_t *EmptyString() { return L""; }
  304. static const wchar_t *NullDebugString() { return L"(null)"; }
  305. };
  306. //-----------------------------------------------------------------------------
  307. // Dirt-basic auto-release string class. Not intended for manipulation,
  308. // can be stored in a container or forwarded as a functor parameter.
  309. // Note the benefit over CUtlString: sizeof(CUtlConstString) == sizeof(char*).
  310. // Also note: null char* pointers are treated identically to empty strings.
  311. //-----------------------------------------------------------------------------
  312. template < typename T = char >
  313. class CUtlConstStringBase
  314. {
  315. public:
  316. CUtlConstStringBase() : m_pString( NULL ) {}
  317. explicit CUtlConstStringBase( const T *pString ) : m_pString( NULL ) { Set( pString ); }
  318. CUtlConstStringBase( const CUtlConstStringBase& src ) : m_pString( NULL ) { Set( src.m_pString ); }
  319. ~CUtlConstStringBase() { Set( NULL ); }
  320. void Set( const T *pValue );
  321. void Clear() { Set( NULL ); }
  322. const T *Get() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
  323. operator const T*() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
  324. bool IsEmpty() const { return m_pString == NULL; } // Note: empty strings are never stored by Set
  325. int Compare( const T *rhs ) const;
  326. // Logical ops
  327. bool operator<( const T *rhs ) const { return Compare( rhs ) < 0; }
  328. bool operator==( const T *rhs ) const { return Compare( rhs ) == 0; }
  329. bool operator!=( const T *rhs ) const { return Compare( rhs ) != 0; }
  330. bool operator<( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) < 0; }
  331. bool operator==( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) == 0; }
  332. bool operator!=( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) != 0; }
  333. // If these are not defined, CUtlConstString as rhs will auto-convert
  334. // to const char* and do logical operations on the raw pointers. Ugh.
  335. inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; }
  336. inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; }
  337. inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; }
  338. CUtlConstStringBase &operator=( const T *src ) { Set( src ); return *this; }
  339. CUtlConstStringBase &operator=( const CUtlConstStringBase &src ) { Set( src.m_pString ); return *this; }
  340. // Defining AltArgumentType_t is a hint to containers that they should
  341. // implement Find/Insert/Remove functions that take const char* params.
  342. typedef const T *AltArgumentType_t;
  343. protected:
  344. const T *m_pString;
  345. };
  346. template < typename T >
  347. void CUtlConstStringBase<T>::Set( const T *pValue )
  348. {
  349. if ( pValue != m_pString )
  350. {
  351. free( ( void* ) m_pString );
  352. m_pString = pValue && pValue[0] ? StringFuncs<T>::Duplicate( pValue ) : NULL;
  353. }
  354. }
  355. template < typename T >
  356. int CUtlConstStringBase<T>::Compare( const T *rhs ) const
  357. {
  358. // Empty or null RHS?
  359. if ( !rhs || !rhs[0] )
  360. return m_pString ? 1 : 0;
  361. // Empty *this, non-empty RHS?
  362. if ( !m_pString )
  363. return -1;
  364. // Neither empty
  365. return StringFuncs<T>::Compare( m_pString, rhs );
  366. }
  367. typedef CUtlConstStringBase<char> CUtlConstString;
  368. typedef CUtlConstStringBase<wchar_t> CUtlConstWideString;
  369. //-----------------------------------------------------------------------------
  370. // Helper functor objects.
  371. //-----------------------------------------------------------------------------
  372. template < typename T > struct UTLConstStringCaselessStringLessFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) < 0; } };
  373. template < typename T > struct UTLConstStringCaselessStringEqualFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) == 0; } };
  374. // Helper function for CUtlMaps with a CUtlString key
  375. inline bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs ) { return V_strcmp( lhs.Get(), rhs.Get() ) < 0; }
  376. inline bool UtlStringCaseInsensitiveLessFunc( const CUtlString &lhs, const CUtlString &rhs ) { return V_stricmp( lhs.Get(), rhs.Get() ) < 0; }
  377. #include "memdbgoff.h"
  378. #endif // UTLSTRING_H