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