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