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