• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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