1 // Copyright 2017 The PDFium Authors 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 <stdarg.h> 11 #include <stddef.h> 12 #include <stdint.h> 13 #include <string.h> 14 15 #include <functional> 16 #include <iosfwd> 17 #include <iterator> 18 #include <utility> 19 20 #include "core/fxcrt/fx_string_wrappers.h" 21 #include "core/fxcrt/retain_ptr.h" 22 #include "core/fxcrt/string_data_template.h" 23 #include "core/fxcrt/string_view_template.h" 24 #include "third_party/abseil-cpp/absl/types/optional.h" 25 #include "third_party/base/check.h" 26 #include "third_party/base/span.h" 27 28 namespace fxcrt { 29 30 // A mutable string with shared buffers using copy-on-write semantics that 31 // avoids the cost of std::string's iterator stability guarantees. 32 class ByteString { 33 public: 34 using CharType = char; 35 using const_iterator = const CharType*; 36 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 37 38 [[nodiscard]] static ByteString FormatInteger(int i); 39 [[nodiscard]] static ByteString FormatFloat(float f); 40 [[nodiscard]] static ByteString Format(const char* pFormat, ...); 41 [[nodiscard]] static ByteString FormatV(const char* pFormat, va_list argList); 42 43 ByteString(); 44 ByteString(const ByteString& other); 45 46 // Move-construct a ByteString. After construction, |other| is empty. 47 ByteString(ByteString&& other) noexcept; 48 49 // Make a one-character string from a char. 50 explicit ByteString(char ch); 51 52 // Deliberately implicit to avoid calling on every string literal. 53 // NOLINTNEXTLINE(runtime/explicit) 54 ByteString(const char* ptr); 55 56 // No implicit conversions from wide strings. 57 // NOLINTNEXTLINE(runtime/explicit) 58 ByteString(wchar_t) = delete; 59 60 ByteString(const char* pStr, size_t len); 61 ByteString(const uint8_t* pStr, size_t len); 62 63 explicit ByteString(ByteStringView bstrc); 64 ByteString(ByteStringView str1, ByteStringView str2); 65 ByteString(const std::initializer_list<ByteStringView>& list); 66 explicit ByteString(const fxcrt::ostringstream& outStream); 67 68 ~ByteString(); 69 70 // Holds on to buffer if possible for later re-use. Assign ByteString() 71 // to force immediate release if desired. 72 void clear(); 73 74 // Explicit conversion to C-style string. 75 // Note: Any subsequent modification of |this| will invalidate the result. c_str()76 const char* c_str() const { return m_pData ? m_pData->m_String : ""; } 77 78 // Explicit conversion to uint8_t*. 79 // Note: Any subsequent modification of |this| will invalidate the result. raw_str()80 const uint8_t* raw_str() const { 81 return m_pData ? reinterpret_cast<const uint8_t*>(m_pData->m_String) 82 : nullptr; 83 } 84 85 // Explicit conversion to ByteStringView. 86 // Note: Any subsequent modification of |this| will invalidate the result. AsStringView()87 ByteStringView AsStringView() const { 88 return ByteStringView(raw_str(), GetLength()); 89 } 90 91 // Explicit conversion to span. 92 // Note: Any subsequent modification of |this| will invalidate the result. span()93 pdfium::span<const char> span() const { 94 return pdfium::make_span(m_pData ? m_pData->m_String : nullptr, 95 GetLength()); 96 } raw_span()97 pdfium::span<const uint8_t> raw_span() const { 98 return pdfium::make_span(raw_str(), GetLength()); 99 } 100 101 // Note: Any subsequent modification of |this| will invalidate iterators. begin()102 const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } end()103 const_iterator end() const { 104 return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; 105 } 106 107 // Note: Any subsequent modification of |this| will invalidate iterators. rbegin()108 const_reverse_iterator rbegin() const { 109 return const_reverse_iterator(end()); 110 } rend()111 const_reverse_iterator rend() const { 112 return const_reverse_iterator(begin()); 113 } 114 GetLength()115 size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } GetStringLength()116 size_t GetStringLength() const { 117 return m_pData ? strlen(m_pData->m_String) : 0; 118 } IsEmpty()119 bool IsEmpty() const { return !GetLength(); } IsValidIndex(size_t index)120 bool IsValidIndex(size_t index) const { return index < GetLength(); } IsValidLength(size_t length)121 bool IsValidLength(size_t length) const { return length <= GetLength(); } 122 123 int Compare(ByteStringView str) const; 124 bool EqualNoCase(ByteStringView str) const; 125 126 bool operator==(const char* ptr) const; 127 bool operator==(ByteStringView str) const; 128 bool operator==(const ByteString& other) const; 129 130 bool operator!=(const char* ptr) const { return !(*this == ptr); } 131 bool operator!=(ByteStringView str) const { return !(*this == str); } 132 bool operator!=(const ByteString& other) const { return !(*this == other); } 133 134 bool operator<(const char* ptr) const; 135 bool operator<(ByteStringView str) const; 136 bool operator<(const ByteString& other) const; 137 138 ByteString& operator=(const char* str); 139 ByteString& operator=(ByteStringView str); 140 ByteString& operator=(const ByteString& that); 141 142 // Move-assign a ByteString. After assignment, |that| is empty. 143 ByteString& operator=(ByteString&& that) noexcept; 144 145 ByteString& operator+=(char ch); 146 ByteString& operator+=(const char* str); 147 ByteString& operator+=(const ByteString& str); 148 ByteString& operator+=(ByteStringView str); 149 150 CharType operator[](const size_t index) const { 151 CHECK(IsValidIndex(index)); 152 return m_pData->m_String[index]; 153 } 154 Front()155 CharType Front() const { return GetLength() ? (*this)[0] : 0; } Back()156 CharType Back() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } 157 158 void SetAt(size_t index, char c); 159 160 size_t Insert(size_t index, char ch); InsertAtFront(char ch)161 size_t InsertAtFront(char ch) { return Insert(0, ch); } InsertAtBack(char ch)162 size_t InsertAtBack(char ch) { return Insert(GetLength(), ch); } 163 size_t Delete(size_t index, size_t count = 1); 164 165 void Reserve(size_t len); 166 167 // Note: any modification of the string (including ReleaseBuffer()) may 168 // invalidate the span, which must not outlive its buffer. 169 pdfium::span<char> GetBuffer(size_t nMinBufLength); 170 void ReleaseBuffer(size_t nNewLength); 171 172 ByteString Substr(size_t offset) const; 173 ByteString Substr(size_t first, size_t count) const; 174 ByteString First(size_t count) const; 175 ByteString Last(size_t count) const; 176 177 absl::optional<size_t> Find(ByteStringView subStr, size_t start = 0) const; 178 absl::optional<size_t> Find(char ch, size_t start = 0) const; 179 absl::optional<size_t> ReverseFind(char ch) const; 180 181 bool Contains(ByteStringView lpszSub, size_t start = 0) const { 182 return Find(lpszSub, start).has_value(); 183 } 184 185 bool Contains(char ch, size_t start = 0) const { 186 return Find(ch, start).has_value(); 187 } 188 189 void MakeLower(); 190 void MakeUpper(); 191 192 void Trim(); 193 void Trim(char target); 194 void Trim(ByteStringView targets); 195 196 void TrimLeft(); 197 void TrimLeft(char target); 198 void TrimLeft(ByteStringView targets); 199 200 void TrimRight(); 201 void TrimRight(char target); 202 void TrimRight(ByteStringView targets); 203 204 size_t Replace(ByteStringView pOld, ByteStringView pNew); 205 size_t Remove(char ch); 206 GetID()207 uint32_t GetID() const { return AsStringView().GetID(); } 208 209 protected: 210 using StringData = StringDataTemplate<char>; 211 212 void ReallocBeforeWrite(size_t nNewLen); 213 void AllocBeforeWrite(size_t nNewLen); 214 void AllocCopy(ByteString& dest, size_t nCopyLen, size_t nCopyIndex) const; 215 void AssignCopy(const char* pSrcData, size_t nSrcLen); 216 void Concat(const char* pSrcData, size_t nSrcLen); 217 intptr_t ReferenceCountForTesting() const; 218 219 RetainPtr<StringData> m_pData; 220 221 friend class ByteString_Assign_Test; 222 friend class ByteString_Concat_Test; 223 friend class ByteString_Construct_Test; 224 friend class StringPool_ByteString_Test; 225 }; 226 227 inline bool operator==(const char* lhs, const ByteString& rhs) { 228 return rhs == lhs; 229 } 230 inline bool operator==(ByteStringView lhs, const ByteString& rhs) { 231 return rhs == lhs; 232 } 233 inline bool operator!=(const char* lhs, const ByteString& rhs) { 234 return rhs != lhs; 235 } 236 inline bool operator!=(ByteStringView lhs, const ByteString& rhs) { 237 return rhs != lhs; 238 } 239 inline bool operator<(const char* lhs, const ByteString& rhs) { 240 return rhs.Compare(lhs) > 0; 241 } 242 inline bool operator<(const ByteStringView& lhs, const ByteString& rhs) { 243 return rhs.Compare(lhs) > 0; 244 } 245 inline bool operator<(const ByteStringView& lhs, const char* rhs) { 246 return lhs < ByteStringView(rhs); 247 } 248 249 inline ByteString operator+(ByteStringView str1, ByteStringView str2) { 250 return ByteString(str1, str2); 251 } 252 inline ByteString operator+(ByteStringView str1, const char* str2) { 253 return ByteString(str1, str2); 254 } 255 inline ByteString operator+(const char* str1, ByteStringView str2) { 256 return ByteString(str1, str2); 257 } 258 inline ByteString operator+(ByteStringView str1, char ch) { 259 return ByteString(str1, ByteStringView(ch)); 260 } 261 inline ByteString operator+(char ch, ByteStringView str2) { 262 return ByteString(ByteStringView(ch), str2); 263 } 264 inline ByteString operator+(const ByteString& str1, const ByteString& str2) { 265 return ByteString(str1.AsStringView(), str2.AsStringView()); 266 } 267 inline ByteString operator+(const ByteString& str1, char ch) { 268 return ByteString(str1.AsStringView(), ByteStringView(ch)); 269 } 270 inline ByteString operator+(char ch, const ByteString& str2) { 271 return ByteString(ByteStringView(ch), str2.AsStringView()); 272 } 273 inline ByteString operator+(const ByteString& str1, const char* str2) { 274 return ByteString(str1.AsStringView(), str2); 275 } 276 inline ByteString operator+(const char* str1, const ByteString& str2) { 277 return ByteString(str1, str2.AsStringView()); 278 } 279 inline ByteString operator+(const ByteString& str1, ByteStringView str2) { 280 return ByteString(str1.AsStringView(), str2); 281 } 282 inline ByteString operator+(ByteStringView str1, const ByteString& str2) { 283 return ByteString(str1, str2.AsStringView()); 284 } 285 286 std::ostream& operator<<(std::ostream& os, const ByteString& str); 287 std::ostream& operator<<(std::ostream& os, ByteStringView str); 288 289 } // namespace fxcrt 290 291 using ByteString = fxcrt::ByteString; 292 293 uint32_t FX_HashCode_GetA(ByteStringView str); 294 uint32_t FX_HashCode_GetLoweredA(ByteStringView str); 295 uint32_t FX_HashCode_GetAsIfW(ByteStringView str); 296 uint32_t FX_HashCode_GetLoweredAsIfW(ByteStringView str); 297 298 namespace std { 299 300 template <> 301 struct hash<ByteString> { 302 size_t operator()(const ByteString& str) const { 303 return FX_HashCode_GetA(str.AsStringView()); 304 } 305 }; 306 307 } // namespace std 308 309 extern template struct std::hash<ByteString>; 310 311 #endif // CORE_FXCRT_BYTESTRING_H_ 312