Fix issuse with != and == shown by fx_basic_bstring unit tests.
[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 CFX_WideStringC& str) const
515     {
516         return  str.m_Length == m_Length && FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length * sizeof(FX_WCHAR)) == 0;
517     }
518
519     bool                        operator != (const CFX_WideStringC& str) const
520     {
521         return  str.m_Length != m_Length || FXSYS_memcmp32(str.m_Ptr, m_Ptr, m_Length * sizeof(FX_WCHAR)) != 0;
522     }
523
524     FX_LPCWSTR          GetPtr() const
525     {
526         return m_Ptr;
527     }
528
529     FX_STRSIZE          GetLength() const
530     {
531         return m_Length;
532     }
533
534     bool                        IsEmpty() const
535     {
536         return m_Length == 0;
537     }
538
539     FX_WCHAR            GetAt(FX_STRSIZE index) const
540     {
541         return m_Ptr[index];
542     }
543
544     CFX_WideStringC     Left(FX_STRSIZE count) const
545     {
546         if (count < 1) {
547             return CFX_WideStringC();
548         }
549         if (count > m_Length) {
550             count = m_Length;
551         }
552         return CFX_WideStringC(m_Ptr, count);
553     }
554
555     CFX_WideStringC     Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const
556     {
557         if (index < 0) {
558             index = 0;
559         }
560         if (index > m_Length) {
561             return CFX_WideStringC();
562         }
563         if (count < 0 || count > m_Length - index) {
564             count = m_Length - index;
565         }
566         return CFX_WideStringC(m_Ptr + index, count);
567     }
568
569     CFX_WideStringC     Right(FX_STRSIZE count) const
570     {
571         if (count < 1) {
572             return CFX_WideStringC();
573         }
574         if (count > m_Length) {
575             count = m_Length;
576         }
577         return CFX_WideStringC(m_Ptr + m_Length - count, count);
578     }
579
580     const FX_WCHAR& operator[] (size_t index) const
581     {
582         return m_Ptr[index];
583     }
584
585     bool operator< (const CFX_WideStringC& that) const
586     {
587         int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length));
588         return result < 0 || (result == 0 && m_Length < that.m_Length);
589      }
590
591 protected:
592     FX_LPCWSTR          m_Ptr;
593     FX_STRSIZE          m_Length;
594
595 private:
596     void*                       operator new (size_t) throw()
597     {
598         return NULL;
599     }
600 };
601 typedef const CFX_WideStringC&  FX_WSTR;
602 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1)
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, FX_STRSIZE len = -1)
625     {
626         InitStr(ptr, len);
627     }
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 CFX_WideString& str) const {
685         int result = wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength()));
686         return result < 0 || (result == 0 && GetLength() < str.GetLength());
687     }
688
689     FX_WCHAR                            GetAt(FX_STRSIZE nIndex) const
690     {
691         return m_pData ? m_pData->m_String[nIndex] : 0;
692     }
693
694     FX_WCHAR                            operator[](FX_STRSIZE nIndex) const
695     {
696         return m_pData ? m_pData->m_String[nIndex] : 0;
697     }
698
699     void                                        SetAt(FX_STRSIZE nIndex, FX_WCHAR ch);
700
701     int                                         Compare(FX_LPCWSTR str) const;
702
703     int                                         Compare(const CFX_WideString& str) const;
704
705     int                                         CompareNoCase(FX_LPCWSTR str) const;
706
707     bool                                        Equal(const CFX_WideStringC& str) const;
708
709     CFX_WideString                      Mid(FX_STRSIZE first) const;
710
711     CFX_WideString                      Mid(FX_STRSIZE first, FX_STRSIZE count) const;
712
713     CFX_WideString                      Left(FX_STRSIZE count) const;
714
715     CFX_WideString                      Right(FX_STRSIZE count) const;
716
717     FX_STRSIZE                          Insert(FX_STRSIZE index, FX_WCHAR ch);
718
719     FX_STRSIZE                          Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
720
721     void                                        Format(FX_LPCWSTR lpszFormat, ... );
722
723     void                                        FormatV(FX_LPCWSTR lpszFormat, va_list argList);
724
725     void                                        MakeLower();
726
727     void                                        MakeUpper();
728
729     void                                        TrimRight();
730
731     void                                        TrimRight(FX_WCHAR chTarget);
732
733     void                                        TrimRight(FX_LPCWSTR lpszTargets);
734
735     void                                        TrimLeft();
736
737     void                                        TrimLeft(FX_WCHAR chTarget);
738
739     void                                        TrimLeft(FX_LPCWSTR lpszTargets);
740
741     void                                        Reserve(FX_STRSIZE len);
742
743     FX_LPWSTR                           GetBuffer(FX_STRSIZE len);
744
745     void                                        ReleaseBuffer(FX_STRSIZE len = -1);
746
747     int                                         GetInteger() const;
748
749     FX_FLOAT                            GetFloat() const;
750
751     FX_STRSIZE                          Find(FX_LPCWSTR lpszSub, FX_STRSIZE start = 0) const;
752
753     FX_STRSIZE                          Find(FX_WCHAR ch, FX_STRSIZE start = 0) const;
754
755     FX_STRSIZE                          Replace(FX_LPCWSTR lpszOld, FX_LPCWSTR lpszNew);
756
757     FX_STRSIZE                          Remove(FX_WCHAR ch);
758
759     CFX_ByteString                      UTF8Encode() const;
760
761     CFX_ByteString                      UTF16LE_Encode() const;
762
763     void                                        ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL);
764 protected:
765     void                                        InitStr(FX_LPCWSTR ptr, int len);
766
767     CFX_StringDataW*            m_pData;
768     void                                        CopyBeforeWrite();
769     void                                        AllocBeforeWrite(FX_STRSIZE nLen);
770     void                                        ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
771     void                                        ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data);
772     void                                        AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
773     void                                        AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
774 };
775 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src)
776 {
777     m_Ptr = src.c_str();
778     m_Length = src.GetLength();
779 }
780 inline CFX_WideStringC& CFX_WideStringC::operator = (const CFX_WideString& src)
781 {
782     m_Ptr = src.c_str();
783     m_Length = src.GetLength();
784     return *this;
785 }
786
787 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideStringC& str2)
788 {
789     return CFX_WideString(str1, str2);
790 }
791 inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_LPCWSTR str2)
792 {
793     return CFX_WideString(str1, str2);
794 }
795 inline CFX_WideString operator + (FX_LPCWSTR str1, const CFX_WideStringC& str2)
796 {
797     return CFX_WideString(str1, str2);
798 }
799 inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_WCHAR ch)
800 {
801     return CFX_WideString(str1, CFX_WideStringC(ch));
802 }
803 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideStringC& str2)
804 {
805     return CFX_WideString(ch, str2);
806 }
807 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideString& str2)
808 {
809     return CFX_WideString(str1, str2);
810 }
811 inline CFX_WideString operator + (const CFX_WideString& str1, FX_WCHAR ch)
812 {
813     return CFX_WideString(str1, CFX_WideStringC(ch));
814 }
815 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideString& str2)
816 {
817     return CFX_WideString(ch, str2);
818 }
819 inline CFX_WideString operator + (const CFX_WideString& str1, FX_LPCWSTR str2)
820 {
821     return CFX_WideString(str1, str2);
822 }
823 inline CFX_WideString operator + (FX_LPCWSTR str1, const CFX_WideString& str2)
824 {
825     return CFX_WideString(str1, str2);
826 }
827 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideStringC& str2)
828 {
829     return CFX_WideString(str1, str2);
830 }
831 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideString& str2)
832 {
833     return CFX_WideString(str1, str2);
834 }
835
836 bool operator==(const CFX_WideString& s1, const CFX_WideString& s2);
837 bool operator==(const CFX_WideString& s1, const CFX_WideStringC& s2);
838 bool operator==(const CFX_WideStringC& s1, const CFX_WideString& s2);
839 bool operator== (const CFX_WideString& s1, FX_LPCWSTR s2);
840 bool operator==(FX_LPCWSTR s1, const CFX_WideString& s2);
841 bool operator!=(const CFX_WideString& s1, const CFX_WideString& s2);
842 bool operator!=(const CFX_WideString& s1, const CFX_WideStringC& s2);
843 bool operator!=(const CFX_WideStringC& s1, const CFX_WideString& s2);
844 bool operator!= (const CFX_WideString& s1, FX_LPCWSTR s2);
845 bool operator!=(FX_LPCWSTR s1, const CFX_WideString& s2);
846 FX_FLOAT FX_atof(FX_BSTR str);
847 void FX_atonum(FX_BSTR str, FX_BOOL& bInteger, void* pData);
848 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_LPSTR buf);
849 CFX_ByteString  FX_UTF8Encode(FX_LPCWSTR pwsStr, FX_STRSIZE len);
850 inline CFX_ByteString   FX_UTF8Encode(FX_WSTR wsStr)
851 {
852     return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength());
853 }
854 inline CFX_ByteString   FX_UTF8Encode(const CFX_WideString &wsStr)
855 {
856     return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength());
857 }
858 #endif