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