clang-format all pdfium code.
[pdfium.git] / core / include / fxcrt / fx_string.h
1 // Copyright 2014 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_INCLUDE_FXCRT_FX_STRING_H_
8 #define CORE_INCLUDE_FXCRT_FX_STRING_H_
9
10 #include <stdint.h>  // For intptr_t.
11 #include <algorithm>
12
13 #include "fx_memory.h"
14 #include "fx_system.h"
15
16 class CFX_BinaryBuf;
17 class CFX_ByteString;
18 class CFX_WideString;
19 struct CFX_CharMap;
20
21 // An immutable string with caller-provided storage which must outlive the
22 // string itself.
23 class CFX_ByteStringC {
24  public:
25   typedef FX_CHAR value_type;
26
27   CFX_ByteStringC() {
28     m_Ptr = NULL;
29     m_Length = 0;
30   }
31
32   CFX_ByteStringC(const uint8_t* ptr, FX_STRSIZE size) {
33     m_Ptr = ptr;
34     m_Length = size;
35   }
36
37   CFX_ByteStringC(const FX_CHAR* ptr) {
38     m_Ptr = (const uint8_t*)ptr;
39     m_Length = ptr ? FXSYS_strlen(ptr) : 0;
40   }
41
42   // |ch| must be an lvalue that outlives the the CFX_ByteStringC. However,
43   // the use of char rvalues are not caught at compile time.  They are
44   // implicitly promoted to CFX_ByteString (see below) and then the
45   // CFX_ByteStringC is constructed from the CFX_ByteString via the alternate
46   // constructor below. The CFX_ByteString then typically goes out of scope
47   // and |m_Ptr| may be left pointing to invalid memory. Beware.
48   // TODO(tsepez): Mark single-argument string constructors as explicit.
49   CFX_ByteStringC(FX_CHAR& ch) {
50     m_Ptr = (const uint8_t*)&ch;
51     m_Length = 1;
52   }
53
54   CFX_ByteStringC(const FX_CHAR* ptr, FX_STRSIZE len) {
55     m_Ptr = (const uint8_t*)ptr;
56     m_Length = (len == -1) ? FXSYS_strlen(ptr) : len;
57   }
58
59   CFX_ByteStringC(const CFX_ByteStringC& src) {
60     m_Ptr = src.m_Ptr;
61     m_Length = src.m_Length;
62   }
63
64   CFX_ByteStringC(const CFX_ByteString& src);
65
66   CFX_ByteStringC& operator=(const FX_CHAR* src) {
67     m_Ptr = (const uint8_t*)src;
68     m_Length = m_Ptr ? FXSYS_strlen(src) : 0;
69     return *this;
70   }
71
72   CFX_ByteStringC& operator=(const CFX_ByteStringC& src) {
73     m_Ptr = src.m_Ptr;
74     m_Length = src.m_Length;
75     return *this;
76   }
77
78   CFX_ByteStringC& operator=(const CFX_ByteString& src);
79
80   bool operator==(const char* ptr) const {
81     return FXSYS_strlen(ptr) == m_Length &&
82            FXSYS_memcmp(ptr, m_Ptr, m_Length) == 0;
83   }
84   bool operator==(const CFX_ByteStringC& other) const {
85     return other.m_Length == m_Length &&
86            FXSYS_memcmp(other.m_Ptr, m_Ptr, m_Length) == 0;
87   }
88   bool operator!=(const char* ptr) const { return !(*this == ptr); }
89   bool operator!=(const CFX_ByteStringC& other) const {
90     return !(*this == other);
91   }
92
93   FX_DWORD GetID(FX_STRSIZE start_pos = 0) const;
94
95   const uint8_t* GetPtr() const { return m_Ptr; }
96
97   const FX_CHAR* GetCStr() const { return (const FX_CHAR*)m_Ptr; }
98
99   FX_STRSIZE GetLength() const { return m_Length; }
100
101   bool IsEmpty() const { return m_Length == 0; }
102
103   uint8_t GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }
104
105   CFX_ByteStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const {
106     if (index < 0) {
107       index = 0;
108     }
109     if (index > m_Length) {
110       return CFX_ByteStringC();
111     }
112     if (count < 0 || count > m_Length - index) {
113       count = m_Length - index;
114     }
115     return CFX_ByteStringC(m_Ptr + index, count);
116   }
117
118   const uint8_t& operator[](size_t index) const { return m_Ptr[index]; }
119
120   bool operator<(const CFX_ByteStringC& that) const {
121     int result = memcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length));
122     return result < 0 || (result == 0 && m_Length < that.m_Length);
123   }
124
125  protected:
126   const uint8_t* m_Ptr;
127   FX_STRSIZE m_Length;
128
129  private:
130   void* operator new(size_t) throw() { return NULL; }
131 };
132 inline bool operator==(const char* lhs, const CFX_ByteStringC& rhs) {
133   return rhs == lhs;
134 }
135 inline bool operator!=(const char* lhs, const CFX_ByteStringC& rhs) {
136   return rhs != lhs;
137 }
138 #define FX_BSTRC(str) CFX_ByteStringC(str, sizeof str - 1)
139 #define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4))
140
141 // A mutable string with shared buffers using copy-on-write semantics that
142 // avoids the cost of std::string's iterator stability guarantees.
143 class CFX_ByteString {
144  public:
145   typedef FX_CHAR value_type;
146
147   CFX_ByteString() : m_pData(nullptr) {}
148
149   // Copy constructor.
150   CFX_ByteString(const CFX_ByteString& str);
151
152   // Move constructor.
153   inline CFX_ByteString(CFX_ByteString&& other) {
154     m_pData = other.m_pData;
155     other.m_pData = nullptr;
156   }
157
158   CFX_ByteString(char ch);
159   CFX_ByteString(const FX_CHAR* ptr)
160       : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {}
161
162   CFX_ByteString(const FX_CHAR* ptr, FX_STRSIZE len);
163   CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len);
164
165   CFX_ByteString(const CFX_ByteStringC& bstrc);
166   CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2);
167
168   ~CFX_ByteString();
169
170   static CFX_ByteString FromUnicode(const FX_WCHAR* ptr, FX_STRSIZE len = -1);
171
172   static CFX_ByteString FromUnicode(const CFX_WideString& str);
173
174   // Explicit conversion to raw string
175   const FX_CHAR* c_str() const { return m_pData ? m_pData->m_String : ""; }
176
177   // Implicit conversion to C-style string -- deprecated
178   operator const FX_CHAR*() const { return m_pData ? m_pData->m_String : ""; }
179
180   operator const uint8_t*() const {
181     return m_pData ? (const uint8_t*)m_pData->m_String : NULL;
182   }
183
184   FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }
185
186   bool IsEmpty() const { return !GetLength(); }
187
188   int Compare(const CFX_ByteStringC& str) const;
189
190   bool Equal(const char* ptr) const;
191   bool Equal(const CFX_ByteStringC& str) const;
192   bool Equal(const CFX_ByteString& other) const;
193
194   bool EqualNoCase(const CFX_ByteStringC& str) const;
195
196   bool operator==(const char* ptr) const { return Equal(ptr); }
197   bool operator==(const CFX_ByteStringC& str) const { return Equal(str); }
198   bool operator==(const CFX_ByteString& other) const { return Equal(other); }
199
200   bool operator!=(const char* ptr) const { return !(*this == ptr); }
201   bool operator!=(const CFX_ByteStringC& str) const { return !(*this == str); }
202   bool operator!=(const CFX_ByteString& other) const {
203     return !(*this == other);
204   }
205
206   bool operator<(const CFX_ByteString& str) const {
207     int result = FXSYS_memcmp(c_str(), str.c_str(),
208                               std::min(GetLength(), str.GetLength()));
209     return result < 0 || (result == 0 && GetLength() < str.GetLength());
210   }
211
212   void Empty();
213
214   const CFX_ByteString& operator=(const FX_CHAR* str);
215
216   const CFX_ByteString& operator=(const CFX_ByteStringC& bstrc);
217
218   const CFX_ByteString& operator=(const CFX_ByteString& stringSrc);
219
220   const CFX_ByteString& operator=(const CFX_BinaryBuf& buf);
221
222   void Load(const uint8_t* str, FX_STRSIZE len);
223
224   const CFX_ByteString& operator+=(FX_CHAR ch);
225
226   const CFX_ByteString& operator+=(const FX_CHAR* str);
227
228   const CFX_ByteString& operator+=(const CFX_ByteString& str);
229
230   const CFX_ByteString& operator+=(const CFX_ByteStringC& bstrc);
231
232   uint8_t GetAt(FX_STRSIZE nIndex) const {
233     return m_pData ? m_pData->m_String[nIndex] : 0;
234   }
235
236   uint8_t operator[](FX_STRSIZE nIndex) const {
237     return m_pData ? m_pData->m_String[nIndex] : 0;
238   }
239
240   void SetAt(FX_STRSIZE nIndex, FX_CHAR ch);
241
242   FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch);
243
244   FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
245
246   void Format(const FX_CHAR* lpszFormat, ...);
247
248   void FormatV(const FX_CHAR* lpszFormat, va_list argList);
249
250   void Reserve(FX_STRSIZE len);
251
252   FX_CHAR* GetBuffer(FX_STRSIZE len);
253
254   void ReleaseBuffer(FX_STRSIZE len = -1);
255
256   CFX_ByteString Mid(FX_STRSIZE first) const;
257
258   CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const;
259
260   CFX_ByteString Left(FX_STRSIZE count) const;
261
262   CFX_ByteString Right(FX_STRSIZE count) const;
263
264   FX_STRSIZE Find(const CFX_ByteStringC& lpszSub, FX_STRSIZE start = 0) const;
265
266   FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) const;
267
268   FX_STRSIZE ReverseFind(FX_CHAR ch) const;
269
270   void MakeLower();
271
272   void MakeUpper();
273
274   void TrimRight();
275
276   void TrimRight(FX_CHAR chTarget);
277
278   void TrimRight(const CFX_ByteStringC& lpszTargets);
279
280   void TrimLeft();
281
282   void TrimLeft(FX_CHAR chTarget);
283
284   void TrimLeft(const CFX_ByteStringC& lpszTargets);
285
286   FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld,
287                      const CFX_ByteStringC& lpszNew);
288
289   FX_STRSIZE Remove(FX_CHAR ch);
290
291   CFX_WideString UTF8Decode() const;
292
293   void ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMap = NULL);
294
295   FX_DWORD GetID(FX_STRSIZE start_pos = 0) const;
296
297 #define FXFORMAT_SIGNED 1
298 #define FXFORMAT_HEX 2
299 #define FXFORMAT_CAPITAL 4
300
301   static CFX_ByteString FormatInteger(int i, FX_DWORD flags = 0);
302   static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0);
303
304  protected:
305   // To ensure ref counts do not overflow, consider the worst possible case:
306   // the entire address space contains nothing but pointers to this object.
307   // Since the count increments with each new pointer, the largest value is
308   // the number of pointers that can fit into the address space. The size of
309   // the address space itself is a good upper bound on it; we need not go
310   // larger.
311   class StringData {
312    public:
313     static StringData* Create(int nLen);
314     void Retain() { ++m_nRefs; }
315     void Release() {
316       if (--m_nRefs <= 0)
317         FX_Free(this);
318     }
319
320     intptr_t m_nRefs;  // Would prefer ssize_t, but no windows support.
321     FX_STRSIZE m_nDataLength;
322     FX_STRSIZE m_nAllocLength;
323     FX_CHAR m_String[1];
324
325    private:
326     StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
327         : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
328       FXSYS_assert(dataLen >= 0);
329       FXSYS_assert(allocLen >= 0);
330       FXSYS_assert(dataLen <= allocLen);
331       m_String[dataLen] = 0;
332     }
333     ~StringData() = delete;
334   };
335
336   void AllocCopy(CFX_ByteString& dest,
337                  FX_STRSIZE nCopyLen,
338                  FX_STRSIZE nCopyIndex) const;
339   void AssignCopy(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData);
340   void ConcatCopy(FX_STRSIZE nSrc1Len,
341                   const FX_CHAR* lpszSrc1Data,
342                   FX_STRSIZE nSrc2Len,
343                   const FX_CHAR* lpszSrc2Data);
344   void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData);
345   void CopyBeforeWrite();
346   void AllocBeforeWrite(FX_STRSIZE nLen);
347
348   StringData* m_pData;
349   friend class fxcrt_ByteStringConcatInPlace_Test;
350 };
351 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src) {
352   m_Ptr = (const uint8_t*)src;
353   m_Length = src.GetLength();
354 }
355 inline CFX_ByteStringC& CFX_ByteStringC::operator=(const CFX_ByteString& src) {
356   m_Ptr = (const uint8_t*)src;
357   m_Length = src.GetLength();
358   return *this;
359 }
360
361 inline bool operator==(const char* lhs, const CFX_ByteString& rhs) {
362   return rhs == lhs;
363 }
364 inline bool operator==(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) {
365   return rhs == lhs;
366 }
367 inline bool operator!=(const char* lhs, const CFX_ByteString& rhs) {
368   return rhs != lhs;
369 }
370 inline bool operator!=(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) {
371   return rhs != lhs;
372 }
373
374 inline CFX_ByteString operator+(const CFX_ByteStringC& str1,
375                                 const CFX_ByteStringC& str2) {
376   return CFX_ByteString(str1, str2);
377 }
378 inline CFX_ByteString operator+(const CFX_ByteStringC& str1,
379                                 const FX_CHAR* str2) {
380   return CFX_ByteString(str1, str2);
381 }
382 inline CFX_ByteString operator+(const FX_CHAR* str1,
383                                 const CFX_ByteStringC& str2) {
384   return CFX_ByteString(str1, str2);
385 }
386 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, FX_CHAR ch) {
387   return CFX_ByteString(str1, CFX_ByteStringC(ch));
388 }
389 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteStringC& str2) {
390   return CFX_ByteString(ch, str2);
391 }
392 inline CFX_ByteString operator+(const CFX_ByteString& str1,
393                                 const CFX_ByteString& str2) {
394   return CFX_ByteString(str1, str2);
395 }
396 inline CFX_ByteString operator+(const CFX_ByteString& str1, FX_CHAR ch) {
397   return CFX_ByteString(str1, CFX_ByteStringC(ch));
398 }
399 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteString& str2) {
400   return CFX_ByteString(ch, str2);
401 }
402 inline CFX_ByteString operator+(const CFX_ByteString& str1,
403                                 const FX_CHAR* str2) {
404   return CFX_ByteString(str1, str2);
405 }
406 inline CFX_ByteString operator+(const FX_CHAR* str1,
407                                 const CFX_ByteString& str2) {
408   return CFX_ByteString(str1, str2);
409 }
410 inline CFX_ByteString operator+(const CFX_ByteString& str1,
411                                 const CFX_ByteStringC& str2) {
412   return CFX_ByteString(str1, str2);
413 }
414 inline CFX_ByteString operator+(const CFX_ByteStringC& str1,
415                                 const CFX_ByteString& str2) {
416   return CFX_ByteString(str1, str2);
417 }
418 class CFX_WideStringC {
419  public:
420   typedef FX_WCHAR value_type;
421
422   CFX_WideStringC() {
423     m_Ptr = NULL;
424     m_Length = 0;
425   }
426
427   CFX_WideStringC(const FX_WCHAR* ptr) {
428     m_Ptr = ptr;
429     m_Length = ptr ? FXSYS_wcslen(ptr) : 0;
430   }
431
432   CFX_WideStringC(FX_WCHAR& ch) {
433     m_Ptr = &ch;
434     m_Length = 1;
435   }
436
437   CFX_WideStringC(const FX_WCHAR* ptr, FX_STRSIZE len) {
438     m_Ptr = ptr;
439     m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len;
440   }
441
442   CFX_WideStringC(const CFX_WideStringC& src) {
443     m_Ptr = src.m_Ptr;
444     m_Length = src.m_Length;
445   }
446
447   CFX_WideStringC(const CFX_WideString& src);
448
449   CFX_WideStringC& operator=(const FX_WCHAR* src) {
450     m_Ptr = src;
451     m_Length = FXSYS_wcslen(src);
452     return *this;
453   }
454
455   CFX_WideStringC& operator=(const CFX_WideStringC& src) {
456     m_Ptr = src.m_Ptr;
457     m_Length = src.m_Length;
458     return *this;
459   }
460
461   CFX_WideStringC& operator=(const CFX_WideString& src);
462
463   bool operator==(const wchar_t* ptr) const {
464     return FXSYS_wcslen(ptr) == m_Length && wmemcmp(ptr, m_Ptr, m_Length) == 0;
465   }
466   bool operator==(const CFX_WideStringC& str) const {
467     return str.m_Length == m_Length && wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0;
468   }
469   bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); }
470   bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); }
471
472   const FX_WCHAR* GetPtr() const { return m_Ptr; }
473
474   FX_STRSIZE GetLength() const { return m_Length; }
475
476   bool IsEmpty() const { return m_Length == 0; }
477
478   FX_WCHAR GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }
479
480   CFX_WideStringC Left(FX_STRSIZE count) const {
481     if (count < 1) {
482       return CFX_WideStringC();
483     }
484     if (count > m_Length) {
485       count = m_Length;
486     }
487     return CFX_WideStringC(m_Ptr, count);
488   }
489
490   CFX_WideStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const {
491     if (index < 0) {
492       index = 0;
493     }
494     if (index > m_Length) {
495       return CFX_WideStringC();
496     }
497     if (count < 0 || count > m_Length - index) {
498       count = m_Length - index;
499     }
500     return CFX_WideStringC(m_Ptr + index, count);
501   }
502
503   CFX_WideStringC Right(FX_STRSIZE count) const {
504     if (count < 1) {
505       return CFX_WideStringC();
506     }
507     if (count > m_Length) {
508       count = m_Length;
509     }
510     return CFX_WideStringC(m_Ptr + m_Length - count, count);
511   }
512
513   const FX_WCHAR& operator[](size_t index) const { return m_Ptr[index]; }
514
515   bool operator<(const CFX_WideStringC& that) const {
516     int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length));
517     return result < 0 || (result == 0 && m_Length < that.m_Length);
518   }
519
520  protected:
521   const FX_WCHAR* m_Ptr;
522   FX_STRSIZE m_Length;
523
524  private:
525   void* operator new(size_t) throw() { return NULL; }
526 };
527 inline bool operator==(const wchar_t* lhs, const CFX_WideStringC& rhs) {
528   return rhs == lhs;
529 }
530 inline bool operator!=(const wchar_t* lhs, const CFX_WideStringC& rhs) {
531   return rhs != lhs;
532 }
533 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1)
534
535 // A mutable string with shared buffers using copy-on-write semantics that
536 // avoids the cost of std::string's iterator stability guarantees.
537 class CFX_WideString {
538  public:
539   typedef FX_WCHAR value_type;
540
541   CFX_WideString() : m_pData(nullptr) {}
542
543   // Copy constructor.
544   CFX_WideString(const CFX_WideString& str);
545
546   // Move constructor.
547   inline CFX_WideString(CFX_WideString&& other) {
548     m_pData = other.m_pData;
549     other.m_pData = nullptr;
550   }
551
552   CFX_WideString(const FX_WCHAR* ptr)
553       : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {}
554
555   CFX_WideString(const FX_WCHAR* ptr, FX_STRSIZE len);
556
557   CFX_WideString(FX_WCHAR ch);
558
559   CFX_WideString(const CFX_WideStringC& str);
560
561   CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2);
562
563   ~CFX_WideString();
564
565   static CFX_WideString FromLocal(const char* str, FX_STRSIZE len = -1);
566
567   static CFX_WideString FromUTF8(const char* str, FX_STRSIZE len);
568
569   static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len);
570
571   static FX_STRSIZE WStringLength(const unsigned short* str);
572
573   // Explicit conversion to raw string
574   const FX_WCHAR* c_str() const { return m_pData ? m_pData->m_String : L""; }
575
576   // Implicit conversion to C-style wide string -- deprecated
577   operator const FX_WCHAR*() const { return m_pData ? m_pData->m_String : L""; }
578
579   void Empty();
580
581   FX_BOOL IsEmpty() const { return !GetLength(); }
582
583   FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }
584
585   const CFX_WideString& operator=(const FX_WCHAR* str);
586
587   const CFX_WideString& operator=(const CFX_WideString& stringSrc);
588
589   const CFX_WideString& operator=(const CFX_WideStringC& stringSrc);
590
591   const CFX_WideString& operator+=(const FX_WCHAR* str);
592
593   const CFX_WideString& operator+=(FX_WCHAR ch);
594
595   const CFX_WideString& operator+=(const CFX_WideString& str);
596
597   const CFX_WideString& operator+=(const CFX_WideStringC& str);
598
599   bool operator==(const wchar_t* ptr) const { return Equal(ptr); }
600   bool operator==(const CFX_WideStringC& str) const { return Equal(str); }
601   bool operator==(const CFX_WideString& other) const { return Equal(other); }
602
603   bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); }
604   bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); }
605   bool operator!=(const CFX_WideString& other) const {
606     return !(*this == other);
607   }
608
609   bool operator<(const CFX_WideString& str) const {
610     int result =
611         wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength()));
612     return result < 0 || (result == 0 && GetLength() < str.GetLength());
613   }
614
615   FX_WCHAR GetAt(FX_STRSIZE nIndex) const {
616     return m_pData ? m_pData->m_String[nIndex] : 0;
617   }
618
619   FX_WCHAR operator[](FX_STRSIZE nIndex) const {
620     return m_pData ? m_pData->m_String[nIndex] : 0;
621   }
622
623   void SetAt(FX_STRSIZE nIndex, FX_WCHAR ch);
624
625   int Compare(const FX_WCHAR* str) const;
626
627   int Compare(const CFX_WideString& str) const;
628
629   int CompareNoCase(const FX_WCHAR* str) const;
630
631   bool Equal(const wchar_t* ptr) const;
632   bool Equal(const CFX_WideStringC& str) const;
633   bool Equal(const CFX_WideString& other) const;
634
635   CFX_WideString Mid(FX_STRSIZE first) const;
636
637   CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const;
638
639   CFX_WideString Left(FX_STRSIZE count) const;
640
641   CFX_WideString Right(FX_STRSIZE count) const;
642
643   FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch);
644
645   FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
646
647   void Format(const FX_WCHAR* lpszFormat, ...);
648
649   void FormatV(const FX_WCHAR* lpszFormat, va_list argList);
650
651   void MakeLower();
652
653   void MakeUpper();
654
655   void TrimRight();
656
657   void TrimRight(FX_WCHAR chTarget);
658
659   void TrimRight(const FX_WCHAR* lpszTargets);
660
661   void TrimLeft();
662
663   void TrimLeft(FX_WCHAR chTarget);
664
665   void TrimLeft(const FX_WCHAR* lpszTargets);
666
667   void Reserve(FX_STRSIZE len);
668
669   FX_WCHAR* GetBuffer(FX_STRSIZE len);
670
671   void ReleaseBuffer(FX_STRSIZE len = -1);
672
673   int GetInteger() const;
674
675   FX_FLOAT GetFloat() const;
676
677   FX_STRSIZE Find(const FX_WCHAR* lpszSub, FX_STRSIZE start = 0) const;
678
679   FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0) const;
680
681   FX_STRSIZE Replace(const FX_WCHAR* lpszOld, const FX_WCHAR* lpszNew);
682
683   FX_STRSIZE Remove(FX_WCHAR ch);
684
685   CFX_ByteString UTF8Encode() const;
686
687   CFX_ByteString UTF16LE_Encode() const;
688
689   void ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL);
690
691  protected:
692   class StringData {
693    public:
694     static StringData* Create(int nLen);
695     void Retain() { ++m_nRefs; }
696     void Release() {
697       if (--m_nRefs <= 0)
698         FX_Free(this);
699     }
700
701     intptr_t m_nRefs;  // Would prefer ssize_t, but no windows support.
702     FX_STRSIZE m_nDataLength;
703     FX_STRSIZE m_nAllocLength;
704     FX_WCHAR m_String[1];
705
706    private:
707     StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
708         : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
709       FXSYS_assert(dataLen >= 0);
710       FXSYS_assert(allocLen >= 0);
711       FXSYS_assert(dataLen <= allocLen);
712       m_String[dataLen] = 0;
713     }
714     ~StringData() = delete;
715   };
716
717   void CopyBeforeWrite();
718   void AllocBeforeWrite(FX_STRSIZE nLen);
719   void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData);
720   void ConcatCopy(FX_STRSIZE nSrc1Len,
721                   const FX_WCHAR* lpszSrc1Data,
722                   FX_STRSIZE nSrc2Len,
723                   const FX_WCHAR* lpszSrc2Data);
724   void AssignCopy(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData);
725   void AllocCopy(CFX_WideString& dest,
726                  FX_STRSIZE nCopyLen,
727                  FX_STRSIZE nCopyIndex) const;
728
729   StringData* m_pData;
730   friend class fxcrt_WideStringConcatInPlace_Test;
731 };
732 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src) {
733   m_Ptr = src.c_str();
734   m_Length = src.GetLength();
735 }
736 inline CFX_WideStringC& CFX_WideStringC::operator=(const CFX_WideString& src) {
737   m_Ptr = src.c_str();
738   m_Length = src.GetLength();
739   return *this;
740 }
741
742 inline CFX_WideString operator+(const CFX_WideStringC& str1,
743                                 const CFX_WideStringC& str2) {
744   return CFX_WideString(str1, str2);
745 }
746 inline CFX_WideString operator+(const CFX_WideStringC& str1,
747                                 const FX_WCHAR* str2) {
748   return CFX_WideString(str1, str2);
749 }
750 inline CFX_WideString operator+(const FX_WCHAR* str1,
751                                 const CFX_WideStringC& str2) {
752   return CFX_WideString(str1, str2);
753 }
754 inline CFX_WideString operator+(const CFX_WideStringC& str1, FX_WCHAR ch) {
755   return CFX_WideString(str1, CFX_WideStringC(ch));
756 }
757 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideStringC& str2) {
758   return CFX_WideString(ch, str2);
759 }
760 inline CFX_WideString operator+(const CFX_WideString& str1,
761                                 const CFX_WideString& str2) {
762   return CFX_WideString(str1, str2);
763 }
764 inline CFX_WideString operator+(const CFX_WideString& str1, FX_WCHAR ch) {
765   return CFX_WideString(str1, CFX_WideStringC(ch));
766 }
767 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideString& str2) {
768   return CFX_WideString(ch, str2);
769 }
770 inline CFX_WideString operator+(const CFX_WideString& str1,
771                                 const FX_WCHAR* str2) {
772   return CFX_WideString(str1, str2);
773 }
774 inline CFX_WideString operator+(const FX_WCHAR* str1,
775                                 const CFX_WideString& str2) {
776   return CFX_WideString(str1, str2);
777 }
778 inline CFX_WideString operator+(const CFX_WideString& str1,
779                                 const CFX_WideStringC& str2) {
780   return CFX_WideString(str1, str2);
781 }
782 inline CFX_WideString operator+(const CFX_WideStringC& str1,
783                                 const CFX_WideString& str2) {
784   return CFX_WideString(str1, str2);
785 }
786 inline bool operator==(const wchar_t* lhs, const CFX_WideString& rhs) {
787   return rhs == lhs;
788 }
789 inline bool operator==(const CFX_WideStringC& lhs, const CFX_WideString& rhs) {
790   return rhs == lhs;
791 }
792 inline bool operator!=(const wchar_t* lhs, const CFX_WideString& rhs) {
793   return rhs != lhs;
794 }
795 inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) {
796   return rhs != lhs;
797 }
798 FX_FLOAT FX_atof(const CFX_ByteStringC& str);
799 void FX_atonum(const CFX_ByteStringC& str, FX_BOOL& bInteger, void* pData);
800 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_CHAR* buf);
801 CFX_ByteString FX_UTF8Encode(const FX_WCHAR* pwsStr, FX_STRSIZE len);
802 inline CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr) {
803   return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength());
804 }
805 inline CFX_ByteString FX_UTF8Encode(const CFX_WideString& wsStr) {
806   return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength());
807 }
808
809 #endif  // CORE_INCLUDE_FXCRT_FX_STRING_H_