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