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