1 // Copyright 2017 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef CORE_FXCRT_WIDESTRING_H_ 8 #define CORE_FXCRT_WIDESTRING_H_ 9 10 #include <functional> 11 #include <iterator> 12 #include <utility> 13 14 #include "core/fxcrt/fx_memory.h" 15 #include "core/fxcrt/fx_system.h" 16 #include "core/fxcrt/retain_ptr.h" 17 #include "core/fxcrt/string_data_template.h" 18 #include "core/fxcrt/string_view_template.h" 19 #include "third_party/base/optional.h" 20 21 22 namespace fxcrt { 23 24 class ByteString; 25 class StringPool_WideString_Test; 26 class WideString_ConcatInPlace_Test; 27 28 // A mutable string with shared buffers using copy-on-write semantics that 29 // avoids the cost of std::string's iterator stability guarantees. 30 class WideString { 31 public: 32 using CharType = wchar_t; 33 using const_iterator = const CharType*; 34 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 35 36 static WideString Format(const wchar_t* lpszFormat, ...) WARN_UNUSED_RESULT; 37 static WideString FormatV(const wchar_t* lpszFormat, 38 va_list argList) WARN_UNUSED_RESULT; 39 40 WideString(); 41 WideString(const WideString& other); 42 WideString(WideString&& other) noexcept; 43 44 // Deliberately implicit to avoid calling on every string literal. 45 // NOLINTNEXTLINE(runtime/explicit) 46 WideString(wchar_t ch); 47 // NOLINTNEXTLINE(runtime/explicit) 48 WideString(const wchar_t* ptr); 49 50 // No implicit conversions from byte strings. 51 // NOLINTNEXTLINE(runtime/explicit) 52 WideString(char) = delete; 53 54 WideString(const wchar_t* ptr, size_t len); 55 56 explicit WideString(const WideStringView& str); 57 WideString(const WideStringView& str1, const WideStringView& str2); 58 WideString(const std::initializer_list<WideStringView>& list); 59 60 ~WideString(); 61 62 static WideString FromLocal(const ByteStringView& str) WARN_UNUSED_RESULT; 63 static WideString FromCodePage(const ByteStringView& str, 64 uint16_t codepage) WARN_UNUSED_RESULT; 65 66 static WideString FromUTF8(const ByteStringView& str) WARN_UNUSED_RESULT; 67 static WideString FromUTF16LE(const unsigned short* str, 68 size_t len) WARN_UNUSED_RESULT; 69 70 static size_t WStringLength(const unsigned short* str) WARN_UNUSED_RESULT; 71 72 // Explicit conversion to C-style wide string. 73 // Note: Any subsequent modification of |this| will invalidate the result. c_str()74 const wchar_t* c_str() const { return m_pData ? m_pData->m_String : L""; } 75 76 // Explicit conversion to WideStringView. 77 // Note: Any subsequent modification of |this| will invalidate the result. AsStringView()78 WideStringView AsStringView() const { 79 return WideStringView(c_str(), GetLength()); 80 } 81 82 // Note: Any subsequent modification of |this| will invalidate iterators. begin()83 const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } end()84 const_iterator end() const { 85 return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; 86 } 87 88 // Note: Any subsequent modification of |this| will invalidate iterators. rbegin()89 const_reverse_iterator rbegin() const { 90 return const_reverse_iterator(end()); 91 } rend()92 const_reverse_iterator rend() const { 93 return const_reverse_iterator(begin()); 94 } 95 clear()96 void clear() { m_pData.Reset(); } 97 GetLength()98 size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } GetStringLength()99 size_t GetStringLength() const { 100 return m_pData ? wcslen(m_pData->m_String) : 0; 101 } IsEmpty()102 bool IsEmpty() const { return !GetLength(); } IsValidIndex(size_t index)103 bool IsValidIndex(size_t index) const { return index < GetLength(); } IsValidLength(size_t length)104 bool IsValidLength(size_t length) const { return length <= GetLength(); } 105 106 const WideString& operator=(const wchar_t* str); 107 const WideString& operator=(const WideString& stringSrc); 108 const WideString& operator=(const WideStringView& stringSrc); 109 110 const WideString& operator+=(const wchar_t* str); 111 const WideString& operator+=(wchar_t ch); 112 const WideString& operator+=(const WideString& str); 113 const WideString& operator+=(const WideStringView& str); 114 115 bool operator==(const wchar_t* ptr) const; 116 bool operator==(const WideStringView& str) const; 117 bool operator==(const WideString& other) const; 118 119 bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } 120 bool operator!=(const WideStringView& str) const { return !(*this == str); } 121 bool operator!=(const WideString& other) const { return !(*this == other); } 122 123 bool operator<(const wchar_t* ptr) const; 124 bool operator<(const WideStringView& str) const; 125 bool operator<(const WideString& other) const; 126 127 CharType operator[](const size_t index) const { 128 ASSERT(IsValidIndex(index)); 129 return m_pData ? m_pData->m_String[index] : 0; 130 } 131 First()132 CharType First() const { return GetLength() ? (*this)[0] : 0; } Last()133 CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } 134 135 void SetAt(size_t index, wchar_t c); 136 137 int Compare(const wchar_t* str) const; 138 int Compare(const WideString& str) const; 139 int CompareNoCase(const wchar_t* str) const; 140 141 WideString Mid(size_t first, size_t count) const; 142 WideString Left(size_t count) const; 143 WideString Right(size_t count) const; 144 145 size_t Insert(size_t index, wchar_t ch); InsertAtFront(wchar_t ch)146 size_t InsertAtFront(wchar_t ch) { return Insert(0, ch); } InsertAtBack(wchar_t ch)147 size_t InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); } 148 size_t Delete(size_t index, size_t count = 1); 149 150 void MakeLower(); 151 void MakeUpper(); 152 153 void Trim(); 154 void Trim(wchar_t target); 155 void Trim(const WideStringView& targets); 156 157 void TrimLeft(); 158 void TrimLeft(wchar_t target); 159 void TrimLeft(const WideStringView& targets); 160 161 void TrimRight(); 162 void TrimRight(wchar_t target); 163 void TrimRight(const WideStringView& targets); 164 165 void Reserve(size_t len); 166 wchar_t* GetBuffer(size_t len); 167 void ReleaseBuffer(size_t len); 168 169 int GetInteger() const; 170 float GetFloat() const; 171 172 Optional<size_t> Find(const WideStringView& pSub, size_t start = 0) const; 173 Optional<size_t> Find(wchar_t ch, size_t start = 0) const; 174 175 bool Contains(const WideStringView& lpszSub, size_t start = 0) const { 176 return Find(lpszSub, start).has_value(); 177 } 178 179 bool Contains(char ch, size_t start = 0) const { 180 return Find(ch, start).has_value(); 181 } 182 183 size_t Replace(const WideStringView& pOld, const WideStringView& pNew); 184 size_t Remove(wchar_t ch); 185 186 ByteString UTF8Encode() const; 187 188 // This method will add \0\0 to the end of the string to represent the 189 // wide string terminator. These values are in the string, not just the data, 190 // so GetLength() will include them. 191 ByteString UTF16LE_Encode() const; 192 193 protected: 194 using StringData = StringDataTemplate<wchar_t>; 195 196 void ReallocBeforeWrite(size_t nLen); 197 void AllocBeforeWrite(size_t nLen); 198 void AllocCopy(WideString& dest, size_t nCopyLen, size_t nCopyIndex) const; 199 void AssignCopy(const wchar_t* pSrcData, size_t nSrcLen); 200 void Concat(const wchar_t* lpszSrcData, size_t nSrcLen); 201 202 RetainPtr<StringData> m_pData; 203 204 friend WideString_ConcatInPlace_Test; 205 friend StringPool_WideString_Test; 206 }; 207 208 inline WideString operator+(const WideStringView& str1, 209 const WideStringView& str2) { 210 return WideString(str1, str2); 211 } 212 inline WideString operator+(const WideStringView& str1, const wchar_t* str2) { 213 return WideString(str1, str2); 214 } 215 inline WideString operator+(const wchar_t* str1, const WideStringView& str2) { 216 return WideString(str1, str2); 217 } 218 inline WideString operator+(const WideStringView& str1, wchar_t ch) { 219 return WideString(str1, WideStringView(ch)); 220 } 221 inline WideString operator+(wchar_t ch, const WideStringView& str2) { 222 return WideString(ch, str2); 223 } 224 inline WideString operator+(const WideString& str1, const WideString& str2) { 225 return WideString(str1.AsStringView(), str2.AsStringView()); 226 } 227 inline WideString operator+(const WideString& str1, wchar_t ch) { 228 return WideString(str1.AsStringView(), WideStringView(ch)); 229 } 230 inline WideString operator+(wchar_t ch, const WideString& str2) { 231 return WideString(ch, str2.AsStringView()); 232 } 233 inline WideString operator+(const WideString& str1, const wchar_t* str2) { 234 return WideString(str1.AsStringView(), str2); 235 } 236 inline WideString operator+(const wchar_t* str1, const WideString& str2) { 237 return WideString(str1, str2.AsStringView()); 238 } 239 inline WideString operator+(const WideString& str1, 240 const WideStringView& str2) { 241 return WideString(str1.AsStringView(), str2); 242 } 243 inline WideString operator+(const WideStringView& str1, 244 const WideString& str2) { 245 return WideString(str1, str2.AsStringView()); 246 } 247 inline bool operator==(const wchar_t* lhs, const WideString& rhs) { 248 return rhs == lhs; 249 } 250 inline bool operator==(const WideStringView& lhs, const WideString& rhs) { 251 return rhs == lhs; 252 } 253 inline bool operator!=(const wchar_t* lhs, const WideString& rhs) { 254 return rhs != lhs; 255 } 256 inline bool operator!=(const WideStringView& lhs, const WideString& rhs) { 257 return rhs != lhs; 258 } 259 inline bool operator<(const wchar_t* lhs, const WideString& rhs) { 260 return rhs.Compare(lhs) > 0; 261 } 262 263 std::wostream& operator<<(std::wostream& os, const WideString& str); 264 std::ostream& operator<<(std::ostream& os, const WideString& str); 265 std::wostream& operator<<(std::wostream& os, const WideStringView& str); 266 std::ostream& operator<<(std::ostream& os, const WideStringView& str); 267 268 } // namespace fxcrt 269 270 using WideString = fxcrt::WideString; 271 272 uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase); 273 274 namespace std { 275 276 template <> 277 struct hash<WideString> { 278 std::size_t operator()(const WideString& str) const { 279 return FX_HashCode_GetW(str.AsStringView(), false); 280 } 281 }; 282 283 } // namespace std 284 285 extern template struct std::hash<WideString>; 286 287 #endif // CORE_FXCRT_WIDESTRING_H_ 288