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