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