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