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