#ifndef UTLSTRING_H #define UTLSTRING_H #ifdef _WIN32 #pragma once #endif #include "utlmemory.h" #include "strtools.h" #include "limits.h" #if defined( OSX ) #define wcsdup wcsdup_osx inline wchar_t* wcsdup_osx(const wchar_t* pString) { wchar_t* pMemory; if (!pString) return NULL; size_t len = (wcslen(pString) + 1); if ((pMemory = (wchar_t*)malloc(len * sizeof(wchar_t))) != NULL) { return wcscpy(pMemory, pString); } return NULL; } #endif class CUtlBinaryBlock { public: CUtlBinaryBlock(int growSize = 0, int initSize = 0); CUtlBinaryBlock(void* pMemory, int nSizeInBytes, int nInitialLength); CUtlBinaryBlock(const void* pMemory, int nSizeInBytes); CUtlBinaryBlock(const CUtlBinaryBlock& src); void Get(void* pValue, int nMaxLen) const; void Set(const void* pValue, int nLen); const void* Get() const; void* Get(); unsigned char& operator[](int i); const unsigned char& operator[](int i) const; int Length() const; void SetLength(int nLength); bool IsEmpty() const; void Clear(); void Purge(); bool IsReadOnly() const; CUtlBinaryBlock& operator=(const CUtlBinaryBlock& src); bool operator==(const CUtlBinaryBlock& src) const; private: CUtlMemory m_Memory; int m_nActualLength; }; inline const void* CUtlBinaryBlock::Get() const { return m_Memory.Base(); } inline void* CUtlBinaryBlock::Get() { return m_Memory.Base(); } inline int CUtlBinaryBlock::Length() const { return m_nActualLength; } inline unsigned char& CUtlBinaryBlock::operator[](int i) { return m_Memory[i]; } inline const unsigned char& CUtlBinaryBlock::operator[](int i) const { return m_Memory[i]; } inline bool CUtlBinaryBlock::IsReadOnly() const { return m_Memory.IsReadOnly(); } inline bool CUtlBinaryBlock::IsEmpty() const { return Length() == 0; } inline void CUtlBinaryBlock::Clear() { SetLength(0); } inline void CUtlBinaryBlock::Purge() { SetLength(0); m_Memory.Purge(); } class CUtlString { public: typedef enum { PATTERN_NONE = 0x00000000, PATTERN_DIRECTORY = 0x00000001 } TUtlStringPattern; public: CUtlString(); CUtlString(const char* pString); CUtlString(const CUtlString& string); CUtlString(void* pMemory, int nSizeInBytes, int nInitialLength); CUtlString(const void* pMemory, int nSizeInBytes); const char* Get() const; void Set(const char* pValue); void Clear() { Set(NULL); } operator const char* () const; const char* String() const { return Get(); } int Length() const; bool IsEmpty() const; void SetLength(int nLen); char* Get(); void Purge(); void ToLower(); void ToUpper(); void Append(const char* pchAddition); void StripTrailingSlash(); CUtlString& operator=(const CUtlString& src); CUtlString& operator=(const char* src); bool operator==(const CUtlString& src) const; bool operator==(const char* src) const; bool operator!=(const CUtlString& src) const { return !operator==(src); } bool operator!=(const char* src) const { return !operator==(src); } inline friend bool operator==(const char* lhs, const CUtlString& rhs) { return rhs.operator==(lhs); } inline friend bool operator!=(const char* lhs, const CUtlString& rhs) { return rhs.operator!=(lhs); } CUtlString& operator+=(const CUtlString& rhs); CUtlString& operator+=(const char* rhs); CUtlString& operator+=(char c); CUtlString& operator+=(int rhs); CUtlString& operator+=(double rhs); bool IsValid() const; bool MatchesPattern(const CUtlString& Pattern, int nFlags = 0); int Format(PRINTF_FORMAT_STRING const char* pFormat, ...); void SetDirect(const char* pValue, int nChars); typedef const char* AltArgumentType_t; CUtlString Slice(int32 nStart = 0, int32 nEnd = INT_MAX); CUtlString Left(int32 nChars); CUtlString Right(int32 nChars); CUtlString Replace(char cFrom, char cTo); CUtlString AbsPath(const char* pStartingDir = NULL); CUtlString UnqualifiedFilename(); CUtlString DirName(); static CUtlString PathJoin(const char* pStr1, const char* pStr2); static int __cdecl SortCaseInsensitive(const CUtlString* pString1, const CUtlString* pString2); static int __cdecl SortCaseSensitive(const CUtlString* pString1, const CUtlString* pString2); private: CUtlBinaryBlock m_Storage; }; inline bool CUtlString::IsEmpty() const { return Length() == 0; } inline bool CUtlString::IsValid() const { return (String() != NULL); } inline int __cdecl CUtlString::SortCaseInsensitive(const CUtlString* pString1, const CUtlString* pString2) { return V_stricmp(pString1->String(), pString2->String()); } inline int __cdecl CUtlString::SortCaseSensitive(const CUtlString* pString1, const CUtlString* pString2) { return V_strcmp(pString1->String(), pString2->String()); } template < typename T > class StringFuncs { public: static T* Duplicate(const T* pValue); static void Copy(T* out_pOut, const T* pIn, int iLengthInChars); static int Compare(const T* pLhs, const T* pRhs); static int CaselessCompare(const T* pLhs, const T* pRhs); static int Length(const T* pValue); static const T* FindChar(const T* pStr, const T cSearch); static const T* EmptyString(); static const T* NullDebugString(); }; template < > class StringFuncs { public: static char* Duplicate(const char* pValue) { return strdup(pValue); } static void Copy(OUT_CAP(iLengthInChars) char* out_pOut, const char* pIn, int iLengthInChars) { strncpy(out_pOut, pIn, iLengthInChars); } static int Compare(const char* pLhs, const char* pRhs) { return strcmp(pLhs, pRhs); } static int CaselessCompare(const char* pLhs, const char* pRhs) { return Q_strcasecmp(pLhs, pRhs); } static int Length(const char* pValue) { return (int)strlen(pValue); } static const char* FindChar(const char* pStr, const char cSearch) { return strchr(pStr, cSearch); } static const char* EmptyString() { return ""; } static const char* NullDebugString() { return "(null)"; } }; template < > class StringFuncs { public: static wchar_t* Duplicate(const wchar_t* pValue) { return wcsdup(pValue); } static void Copy(OUT_CAP(iLengthInChars) wchar_t* out_pOut, const wchar_t* pIn, int iLengthInChars) { wcsncpy(out_pOut, pIn, iLengthInChars); } static int Compare(const wchar_t* pLhs, const wchar_t* pRhs) { return wcscmp(pLhs, pRhs); } static int CaselessCompare(const wchar_t* pLhs, const wchar_t* pRhs); static int Length(const wchar_t* pValue) { return (int)wcslen(pValue); } static const wchar_t* FindChar(const wchar_t* pStr, const wchar_t cSearch) { return wcschr(pStr, cSearch); } static const wchar_t* EmptyString() { return L""; } static const wchar_t* NullDebugString() { return L"(null)"; } }; template < typename T = char > class CUtlConstStringBase { public: CUtlConstStringBase() : m_pString(NULL) {} explicit CUtlConstStringBase(const T* pString) : m_pString(NULL) { Set(pString); } CUtlConstStringBase(const CUtlConstStringBase& src) : m_pString(NULL) { Set(src.m_pString); } ~CUtlConstStringBase() { Set(NULL); } void Set(const T* pValue); void Clear() { Set(NULL); } const T* Get() const { return m_pString ? m_pString : StringFuncs::EmptyString(); } operator const T* () const { return m_pString ? m_pString : StringFuncs::EmptyString(); } bool IsEmpty() const { return m_pString == NULL; } int Compare(const T* rhs) const; bool operator<(const T* rhs) const { return Compare(rhs) < 0; } bool operator==(const T* rhs) const { return Compare(rhs) == 0; } bool operator!=(const T* rhs) const { return Compare(rhs) != 0; } bool operator<(const CUtlConstStringBase& rhs) const { return Compare(rhs.m_pString) < 0; } bool operator==(const CUtlConstStringBase& rhs) const { return Compare(rhs.m_pString) == 0; } bool operator!=(const CUtlConstStringBase& rhs) const { return Compare(rhs.m_pString) != 0; } inline friend bool operator<(const T* lhs, const CUtlConstStringBase& rhs) { return rhs.Compare(lhs) > 0; } inline friend bool operator==(const T* lhs, const CUtlConstStringBase& rhs) { return rhs.Compare(lhs) == 0; } inline friend bool operator!=(const T* lhs, const CUtlConstStringBase& rhs) { return rhs.Compare(lhs) != 0; } CUtlConstStringBase& operator=(const T* src) { Set(src); return *this; } CUtlConstStringBase& operator=(const CUtlConstStringBase& src) { Set(src.m_pString); return *this; } typedef const T* AltArgumentType_t; protected: const T* m_pString; }; template < typename T > void CUtlConstStringBase::Set(const T* pValue) { if (pValue != m_pString) { free((void*)m_pString); m_pString = pValue && pValue[0] ? StringFuncs::Duplicate(pValue) : NULL; } } template < typename T > int CUtlConstStringBase::Compare(const T* rhs) const { if (!rhs || !rhs[0]) return m_pString ? 1 : 0; if (!m_pString) return -1; return StringFuncs::Compare(m_pString, rhs); } typedef CUtlConstStringBase CUtlConstString; typedef CUtlConstStringBase CUtlConstWideString; template < typename T > struct UTLConstStringCaselessStringLessFunctor { bool operator()(const CUtlConstStringBase& a, const char* b) const { return StringFuncs::CaselessCompare(a.Get(), b) < 0; } }; template < typename T > struct UTLConstStringCaselessStringEqualFunctor { bool operator()(const CUtlConstStringBase& a, const char* b) const { return StringFuncs::CaselessCompare(a.Get(), b) == 0; } }; #endif