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_BYTESTRING_H_ 8 #define CORE_FXCRT_BYTESTRING_H_ 9 10 #include <functional> 11 #include <iterator> 12 #include <sstream> 13 #include <utility> 14 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 namespace fxcrt { 22 23 class ByteString_Concat_Test; 24 class StringPool_ByteString_Test; 25 class WideString; 26 27 // A mutable string with shared buffers using copy-on-write semantics that 28 // avoids the cost of std::string's iterator stability guarantees. 29 class ByteString { 30 public: 31 using CharType = char; 32 using const_iterator = const CharType*; 33 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 34 35 static ByteString FormatInteger(int i) WARN_UNUSED_RESULT; 36 static ByteString FormatFloat(float f) WARN_UNUSED_RESULT; 37 static ByteString Format(const char* lpszFormat, ...) WARN_UNUSED_RESULT; 38 static ByteString FormatV(const char* lpszFormat, 39 va_list argList) WARN_UNUSED_RESULT; 40 41 ByteString(); 42 ByteString(const ByteString& other); 43 ByteString(ByteString&& other) noexcept; 44 45 // Deliberately implicit to avoid calling on every string literal. 46 // NOLINTNEXTLINE(runtime/explicit) 47 ByteString(char ch); 48 // NOLINTNEXTLINE(runtime/explicit) 49 ByteString(const char* ptr); 50 51 // No implicit conversions from wide strings. 52 // NOLINTNEXTLINE(runtime/explicit) 53 ByteString(wchar_t) = delete; 54 55 ByteString(const char* ptr, size_t len); 56 ByteString(const uint8_t* ptr, size_t len); 57 58 explicit ByteString(const ByteStringView& bstrc); 59 ByteString(const ByteStringView& bstrc1, const ByteStringView& bstrc2); 60 ByteString(const std::initializer_list<ByteStringView>& list); 61 explicit ByteString(const std::ostringstream& outStream); 62 63 ~ByteString(); 64 clear()65 void clear() { m_pData.Reset(); } 66 67 static ByteString FromUnicode(const WideString& str) WARN_UNUSED_RESULT; 68 69 // Explicit conversion to C-style string. 70 // Note: Any subsequent modification of |this| will invalidate the result. c_str()71 const char* c_str() const { return m_pData ? m_pData->m_String : ""; } 72 73 // Explicit conversion to uint8_t*. 74 // Note: Any subsequent modification of |this| will invalidate the result. raw_str()75 const uint8_t* raw_str() const { 76 return m_pData ? reinterpret_cast<const uint8_t*>(m_pData->m_String) 77 : nullptr; 78 } 79 80 // Explicit conversion to ByteStringView. 81 // Note: Any subsequent modification of |this| will invalidate the result. AsStringView()82 ByteStringView AsStringView() const { 83 return ByteStringView(raw_str(), GetLength()); 84 } 85 86 // Note: Any subsequent modification of |this| will invalidate iterators. begin()87 const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } end()88 const_iterator end() const { 89 return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; 90 } 91 92 // Note: Any subsequent modification of |this| will invalidate iterators. rbegin()93 const_reverse_iterator rbegin() const { 94 return const_reverse_iterator(end()); 95 } rend()96 const_reverse_iterator rend() const { 97 return const_reverse_iterator(begin()); 98 } 99 GetLength()100 size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } GetStringLength()101 size_t GetStringLength() const { 102 return m_pData ? strlen(m_pData->m_String) : 0; 103 } IsEmpty()104 bool IsEmpty() const { return !GetLength(); } IsValidIndex(size_t index)105 bool IsValidIndex(size_t index) const { return index < GetLength(); } IsValidLength(size_t length)106 bool IsValidLength(size_t length) const { return length <= GetLength(); } 107 108 int Compare(const ByteStringView& str) const; 109 bool EqualNoCase(const ByteStringView& str) const; 110 111 bool operator==(const char* ptr) const; 112 bool operator==(const ByteStringView& str) const; 113 bool operator==(const ByteString& other) const; 114 115 bool operator!=(const char* ptr) const { return !(*this == ptr); } 116 bool operator!=(const ByteStringView& str) const { return !(*this == str); } 117 bool operator!=(const ByteString& other) const { return !(*this == other); } 118 119 bool operator<(const char* ptr) const; 120 bool operator<(const ByteStringView& str) const; 121 bool operator<(const ByteString& other) const; 122 123 const ByteString& operator=(const char* str); 124 const ByteString& operator=(const ByteStringView& bstrc); 125 const ByteString& operator=(const ByteString& stringSrc); 126 127 const ByteString& operator+=(char ch); 128 const ByteString& operator+=(const char* str); 129 const ByteString& operator+=(const ByteString& str); 130 const ByteString& operator+=(const ByteStringView& bstrc); 131 132 CharType operator[](const size_t index) const { 133 ASSERT(IsValidIndex(index)); 134 return m_pData ? m_pData->m_String[index] : 0; 135 } 136 First()137 CharType First() const { return GetLength() ? (*this)[0] : 0; } Last()138 CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } 139 140 void SetAt(size_t index, char c); 141 142 size_t Insert(size_t index, char ch); InsertAtFront(char ch)143 size_t InsertAtFront(char ch) { return Insert(0, ch); } InsertAtBack(char ch)144 size_t InsertAtBack(char ch) { return Insert(GetLength(), ch); } 145 size_t Delete(size_t index, size_t count = 1); 146 147 void Reserve(size_t len); 148 char* GetBuffer(size_t len); 149 void ReleaseBuffer(size_t len); 150 151 ByteString Mid(size_t first, size_t count) const; 152 ByteString Left(size_t count) const; 153 ByteString Right(size_t count) const; 154 155 Optional<size_t> Find(const ByteStringView& lpszSub, size_t start = 0) const; 156 Optional<size_t> Find(char ch, size_t start = 0) const; 157 Optional<size_t> ReverseFind(char ch) const; 158 159 bool Contains(const ByteStringView& lpszSub, size_t start = 0) const { 160 return Find(lpszSub, start).has_value(); 161 } 162 163 bool Contains(char ch, size_t start = 0) const { 164 return Find(ch, start).has_value(); 165 } 166 167 void MakeLower(); 168 void MakeUpper(); 169 170 void Trim(); 171 void Trim(char target); 172 void Trim(const ByteStringView& targets); 173 174 void TrimLeft(); 175 void TrimLeft(char target); 176 void TrimLeft(const ByteStringView& targets); 177 178 void TrimRight(); 179 void TrimRight(char target); 180 void TrimRight(const ByteStringView& targets); 181 182 size_t Replace(const ByteStringView& lpszOld, const ByteStringView& lpszNew); 183 184 size_t Remove(char ch); 185 186 WideString UTF8Decode() const; 187 GetID()188 uint32_t GetID() const { return AsStringView().GetID(); } 189 190 protected: 191 using StringData = StringDataTemplate<char>; 192 193 void ReallocBeforeWrite(size_t nNewLen); 194 void AllocBeforeWrite(size_t nNewLen); 195 void AllocCopy(ByteString& dest, size_t nCopyLen, size_t nCopyIndex) const; 196 void AssignCopy(const char* pSrcData, size_t nSrcLen); 197 void Concat(const char* lpszSrcData, size_t nSrcLen); 198 199 RetainPtr<StringData> m_pData; 200 201 friend ByteString_Concat_Test; 202 friend class StringPool_ByteString_Test; 203 }; 204 205 inline bool operator==(const char* lhs, const ByteString& rhs) { 206 return rhs == lhs; 207 } 208 inline bool operator==(const ByteStringView& lhs, const ByteString& rhs) { 209 return rhs == lhs; 210 } 211 inline bool operator!=(const char* lhs, const ByteString& rhs) { 212 return rhs != lhs; 213 } 214 inline bool operator!=(const ByteStringView& lhs, const ByteString& rhs) { 215 return rhs != lhs; 216 } 217 inline bool operator<(const char* lhs, const ByteString& rhs) { 218 return rhs.Compare(lhs) > 0; 219 } 220 221 inline ByteString operator+(const ByteStringView& str1, 222 const ByteStringView& str2) { 223 return ByteString(str1, str2); 224 } 225 inline ByteString operator+(const ByteStringView& str1, const char* str2) { 226 return ByteString(str1, str2); 227 } 228 inline ByteString operator+(const char* str1, const ByteStringView& str2) { 229 return ByteString(str1, str2); 230 } 231 inline ByteString operator+(const ByteStringView& str1, char ch) { 232 return ByteString(str1, ByteStringView(ch)); 233 } 234 inline ByteString operator+(char ch, const ByteStringView& str2) { 235 return ByteString(ch, str2); 236 } 237 inline ByteString operator+(const ByteString& str1, const ByteString& str2) { 238 return ByteString(str1.AsStringView(), str2.AsStringView()); 239 } 240 inline ByteString operator+(const ByteString& str1, char ch) { 241 return ByteString(str1.AsStringView(), ByteStringView(ch)); 242 } 243 inline ByteString operator+(char ch, const ByteString& str2) { 244 return ByteString(ch, str2.AsStringView()); 245 } 246 inline ByteString operator+(const ByteString& str1, const char* str2) { 247 return ByteString(str1.AsStringView(), str2); 248 } 249 inline ByteString operator+(const char* str1, const ByteString& str2) { 250 return ByteString(str1, str2.AsStringView()); 251 } 252 inline ByteString operator+(const ByteString& str1, 253 const ByteStringView& str2) { 254 return ByteString(str1.AsStringView(), str2); 255 } 256 inline ByteString operator+(const ByteStringView& str1, 257 const ByteString& str2) { 258 return ByteString(str1, str2.AsStringView()); 259 } 260 261 std::ostream& operator<<(std::ostream& os, const ByteString& str); 262 std::ostream& operator<<(std::ostream& os, const ByteStringView& str); 263 264 } // namespace fxcrt 265 266 using ByteString = fxcrt::ByteString; 267 268 uint32_t FX_HashCode_GetA(const ByteStringView& str, bool bIgnoreCase); 269 270 namespace std { 271 272 template <> 273 struct hash<ByteString> { 274 std::size_t operator()(const ByteString& str) const { 275 return FX_HashCode_GetA(str.AsStringView(), false); 276 } 277 }; 278 279 } // namespace std 280 281 extern template struct std::hash<ByteString>; 282 283 #endif // CORE_FXCRT_BYTESTRING_H_ 284