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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #ifndef CORE_INCLUDE_FXCRT_FX_STRING_H_
8 #define CORE_INCLUDE_FXCRT_FX_STRING_H_
10 #include <stdint.h> // For intptr_t.
13 #include "fx_memory.h"
14 #include "fx_system.h"
21 // An immutable string with caller-provided storage which must outlive the
26 typedef FX_CHAR value_type;
34 CFX_ByteStringC(FX_LPCBYTE ptr, FX_STRSIZE size)
40 CFX_ByteStringC(FX_LPCSTR ptr)
42 m_Ptr = (FX_LPCBYTE)ptr;
43 m_Length = ptr ? FXSYS_strlen(ptr) : 0;
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)
55 m_Ptr = (FX_LPCBYTE)&ch;
59 CFX_ByteStringC(FX_LPCSTR ptr, FX_STRSIZE len)
61 m_Ptr = (FX_LPCBYTE)ptr;
62 m_Length = (len == -1) ? FXSYS_strlen(ptr) : len;
65 CFX_ByteStringC(const CFX_ByteStringC& src)
68 m_Length = src.m_Length;
71 CFX_ByteStringC(const CFX_ByteString& src);
73 CFX_ByteStringC& operator = (FX_LPCSTR src)
75 m_Ptr = (FX_LPCBYTE)src;
76 m_Length = m_Ptr ? FXSYS_strlen(src) : 0;
80 CFX_ByteStringC& operator = (const CFX_ByteStringC& src)
83 m_Length = src.m_Length;
87 CFX_ByteStringC& operator = (const CFX_ByteString& src);
89 bool operator== (const char* ptr) const {
90 return FXSYS_strlen(ptr) == m_Length &&
91 FXSYS_memcmp32(ptr, m_Ptr, m_Length) == 0;
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;
97 bool operator!= (const char* ptr) const { return !(*this == ptr); }
98 bool operator!= (const CFX_ByteStringC& other) const {
99 return !(*this == other);
102 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const;
104 FX_LPCBYTE GetPtr() const
109 FX_LPCSTR GetCStr() const
111 return (FX_LPCSTR)m_Ptr;
114 FX_STRSIZE GetLength() const
121 return m_Length == 0;
124 FX_BYTE GetAt(FX_STRSIZE index) const
129 CFX_ByteStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const
134 if (index > m_Length) {
135 return CFX_ByteStringC();
137 if (count < 0 || count > m_Length - index) {
138 count = m_Length - index;
140 return CFX_ByteStringC(m_Ptr + index, count);
143 const FX_BYTE& operator[] (size_t index) const
148 bool operator< (const CFX_ByteStringC& that) const
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);
159 void* operator new (size_t) throw()
164 inline bool operator== (const char* lhs, const CFX_ByteStringC& rhs) {
167 inline bool operator!= (const char* lhs, const CFX_ByteStringC& rhs) {
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))
174 // A mutable string with shared buffers using copy-on-write semantics that
175 // avoids the cost of std::string's iterator stability guarantees.
179 typedef FX_CHAR value_type;
181 CFX_ByteString() : m_pData(nullptr) { }
184 CFX_ByteString(const CFX_ByteString& str);
187 inline CFX_ByteString(CFX_ByteString&& other) {
188 this->m_pData = other.m_pData;
189 other.m_pData = nullptr;
192 CFX_ByteString(char ch);
193 CFX_ByteString(FX_LPCSTR ptr)
194 : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) { }
196 CFX_ByteString(FX_LPCSTR ptr, FX_STRSIZE len);
197 CFX_ByteString(FX_LPCBYTE ptr, FX_STRSIZE len);
199 CFX_ByteString(FX_BSTR bstrc);
200 CFX_ByteString(FX_BSTR bstrc1, FX_BSTR bstrc2);
204 static CFX_ByteString FromUnicode(FX_LPCWSTR ptr, FX_STRSIZE len = -1);
206 static CFX_ByteString FromUnicode(const CFX_WideString& str);
208 // Explicit conversion to raw string
209 FX_LPCSTR c_str() const
211 return m_pData ? m_pData->m_String : "";
214 // Implicit conversion to C-style string -- deprecated
215 operator FX_LPCSTR() const
217 return m_pData ? m_pData->m_String : "";
220 operator FX_LPCBYTE() const
222 return m_pData ? (FX_LPCBYTE)m_pData->m_String : NULL;
225 FX_STRSIZE GetLength() const
227 return m_pData ? m_pData->m_nDataLength : 0;
235 int Compare(FX_BSTR str) const;
238 bool Equal(const char* ptr) const;
239 bool Equal(const CFX_ByteStringC& str) const;
240 bool Equal(const CFX_ByteString& other) const;
242 bool EqualNoCase(FX_BSTR str) const;
244 bool operator== (const char* ptr) const { return Equal(ptr); }
245 bool operator== (const CFX_ByteStringC& str) const { return Equal(str); }
246 bool operator== (const CFX_ByteString& other) const { return Equal(other); }
248 bool operator!= (const char* ptr) const { return !(*this == ptr); }
249 bool operator!= (const CFX_ByteStringC& str) const {
250 return !(*this == str);
252 bool operator!= (const CFX_ByteString& other) const {
253 return !(*this == other);
256 bool operator< (const CFX_ByteString& str) const
258 int result = FXSYS_memcmp32(c_str(), str.c_str(), std::min(GetLength(), str.GetLength()));
259 return result < 0 || (result == 0 && GetLength() < str.GetLength());
264 const CFX_ByteString& operator = (FX_LPCSTR str);
266 const CFX_ByteString& operator = (FX_BSTR bstrc);
268 const CFX_ByteString& operator = (const CFX_ByteString& stringSrc);
270 const CFX_ByteString& operator = (const CFX_BinaryBuf& buf);
272 void Load(FX_LPCBYTE str, FX_STRSIZE len);
274 const CFX_ByteString& operator += (FX_CHAR ch);
276 const CFX_ByteString& operator += (FX_LPCSTR str);
278 const CFX_ByteString& operator += (const CFX_ByteString& str);
280 const CFX_ByteString& operator += (FX_BSTR bstrc);
282 FX_BYTE GetAt(FX_STRSIZE nIndex) const
284 return m_pData ? m_pData->m_String[nIndex] : 0;
287 FX_BYTE operator[](FX_STRSIZE nIndex) const
289 return m_pData ? m_pData->m_String[nIndex] : 0;
292 void SetAt(FX_STRSIZE nIndex, FX_CHAR ch);
294 FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch);
296 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
299 void Format(FX_LPCSTR lpszFormat, ... );
301 void FormatV(FX_LPCSTR lpszFormat, va_list argList);
304 void Reserve(FX_STRSIZE len);
306 FX_LPSTR GetBuffer(FX_STRSIZE len);
308 void ReleaseBuffer(FX_STRSIZE len = -1);
310 CFX_ByteString Mid(FX_STRSIZE first) const;
312 CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const;
314 CFX_ByteString Left(FX_STRSIZE count) const;
316 CFX_ByteString Right(FX_STRSIZE count) const;
318 FX_STRSIZE Find(FX_BSTR lpszSub, FX_STRSIZE start = 0) const;
320 FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) const;
322 FX_STRSIZE ReverseFind(FX_CHAR ch) const;
330 void TrimRight(FX_CHAR chTarget);
332 void TrimRight(FX_BSTR lpszTargets);
336 void TrimLeft(FX_CHAR chTarget);
338 void TrimLeft(FX_BSTR lpszTargets);
340 FX_STRSIZE Replace(FX_BSTR lpszOld, FX_BSTR lpszNew);
342 FX_STRSIZE Remove(FX_CHAR ch);
344 CFX_WideString UTF8Decode() const;
346 void ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMap = NULL);
348 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const;
350 #define FXFORMAT_SIGNED 1
351 #define FXFORMAT_HEX 2
352 #define FXFORMAT_CAPITAL 4
354 static CFX_ByteString FormatInteger(int i, FX_DWORD flags = 0);
355 static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0);
358 // To ensure ref counts do not overflow, consider the worst possible case:
359 // the entire address space contains nothing but pointers to this object.
360 // Since the count increments with each new pointer, the largest value is
361 // the number of pointers that can fit into the address space. The size of
362 // the address space itself is a good upper bound on it; we need not go
366 static StringData* Create(int nLen);
367 void Retain() { ++m_nRefs; }
368 void Release() { if (--m_nRefs <= 0) FX_Free(this); }
370 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support.
371 FX_STRSIZE m_nDataLength;
372 FX_STRSIZE m_nAllocLength;
376 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
377 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
378 FXSYS_assert(dataLen >= 0);
379 FXSYS_assert(allocLen >= 0);
380 FXSYS_assert(dataLen <= allocLen);
381 m_String[dataLen] = 0;
383 ~StringData() = delete;
386 void AllocCopy(CFX_ByteString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
387 void AssignCopy(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
388 void ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCSTR lpszSrc2Data);
389 void ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
390 void CopyBeforeWrite();
391 void AllocBeforeWrite(FX_STRSIZE nLen);
394 friend class fxcrt_ByteStringConcatInPlace_Test;
396 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src)
398 m_Ptr = (FX_LPCBYTE)src;
399 m_Length = src.GetLength();
401 inline CFX_ByteStringC& CFX_ByteStringC::operator = (const CFX_ByteString& src)
403 m_Ptr = (FX_LPCBYTE)src;
404 m_Length = src.GetLength();
408 inline bool operator== (const char* lhs, const CFX_ByteString& rhs) {
411 inline bool operator== (const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) {
414 inline bool operator!= (const char* lhs, const CFX_ByteString& rhs) {
417 inline bool operator!= (const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) {
421 inline CFX_ByteString operator + (FX_BSTR str1, FX_BSTR str2)
423 return CFX_ByteString(str1, str2);
425 inline CFX_ByteString operator + (FX_BSTR str1, FX_LPCSTR str2)
427 return CFX_ByteString(str1, str2);
429 inline CFX_ByteString operator + (FX_LPCSTR str1, FX_BSTR str2)
431 return CFX_ByteString(str1, str2);
433 inline CFX_ByteString operator + (FX_BSTR str1, FX_CHAR ch)
435 return CFX_ByteString(str1, CFX_ByteStringC(ch));
437 inline CFX_ByteString operator + (FX_CHAR ch, FX_BSTR str2)
439 return CFX_ByteString(ch, str2);
441 inline CFX_ByteString operator + (const CFX_ByteString& str1, const CFX_ByteString& str2)
443 return CFX_ByteString(str1, str2);
445 inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_CHAR ch)
447 return CFX_ByteString(str1, CFX_ByteStringC(ch));
449 inline CFX_ByteString operator + (FX_CHAR ch, const CFX_ByteString& str2)
451 return CFX_ByteString(ch, str2);
453 inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_LPCSTR str2)
455 return CFX_ByteString(str1, str2);
457 inline CFX_ByteString operator + (FX_LPCSTR str1, const CFX_ByteString& str2)
459 return CFX_ByteString(str1, str2);
461 inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_BSTR str2)
463 return CFX_ByteString(str1, str2);
465 inline CFX_ByteString operator + (FX_BSTR str1, const CFX_ByteString& str2)
467 return CFX_ByteString(str1, str2);
469 class CFX_WideStringC
472 typedef FX_WCHAR value_type;
480 CFX_WideStringC(FX_LPCWSTR ptr)
483 m_Length = ptr ? FXSYS_wcslen(ptr) : 0;
486 CFX_WideStringC(FX_WCHAR& ch)
492 CFX_WideStringC(FX_LPCWSTR ptr, FX_STRSIZE len)
495 m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len;
498 CFX_WideStringC(const CFX_WideStringC& src)
501 m_Length = src.m_Length;
504 CFX_WideStringC(const CFX_WideString& src);
506 CFX_WideStringC& operator = (FX_LPCWSTR src)
509 m_Length = FXSYS_wcslen(src);
513 CFX_WideStringC& operator = (const CFX_WideStringC& src)
516 m_Length = src.m_Length;
520 CFX_WideStringC& operator = (const CFX_WideString& src);
522 bool operator== (const wchar_t* ptr) const {
523 return FXSYS_wcslen(ptr) == m_Length &&
524 wmemcmp(ptr, m_Ptr, m_Length) == 0;
526 bool operator== (const CFX_WideStringC& str) const {
527 return str.m_Length == m_Length &&
528 wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0;
530 bool operator!= (const wchar_t* ptr) const { return !(*this == ptr); }
531 bool operator!= (const CFX_WideStringC& str) const {
532 return !(*this == str);
535 FX_LPCWSTR GetPtr() const
540 FX_STRSIZE GetLength() const
547 return m_Length == 0;
550 FX_WCHAR GetAt(FX_STRSIZE index) const
555 CFX_WideStringC Left(FX_STRSIZE count) const
558 return CFX_WideStringC();
560 if (count > m_Length) {
563 return CFX_WideStringC(m_Ptr, count);
566 CFX_WideStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const
571 if (index > m_Length) {
572 return CFX_WideStringC();
574 if (count < 0 || count > m_Length - index) {
575 count = m_Length - index;
577 return CFX_WideStringC(m_Ptr + index, count);
580 CFX_WideStringC Right(FX_STRSIZE count) const
583 return CFX_WideStringC();
585 if (count > m_Length) {
588 return CFX_WideStringC(m_Ptr + m_Length - count, count);
591 const FX_WCHAR& operator[] (size_t index) const
596 bool operator< (const CFX_WideStringC& that) const
598 int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length));
599 return result < 0 || (result == 0 && m_Length < that.m_Length);
607 void* operator new (size_t) throw()
612 inline bool operator== (const wchar_t* lhs, const CFX_WideStringC& rhs) {
615 inline bool operator!= (const wchar_t* lhs, const CFX_WideStringC& rhs) {
618 typedef const CFX_WideStringC& FX_WSTR;
619 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1)
621 // A mutable string with shared buffers using copy-on-write semantics that
622 // avoids the cost of std::string's iterator stability guarantees.
626 typedef FX_WCHAR value_type;
628 CFX_WideString() : m_pData(nullptr) { }
631 CFX_WideString(const CFX_WideString& str);
634 inline CFX_WideString(CFX_WideString&& other) {
635 this->m_pData = other.m_pData;
636 other.m_pData = nullptr;
639 CFX_WideString(FX_LPCWSTR ptr)
640 : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) { }
642 CFX_WideString(FX_LPCWSTR ptr, FX_STRSIZE len);
644 CFX_WideString(FX_WCHAR ch);
646 CFX_WideString(const CFX_WideStringC& str);
648 CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2);
652 static CFX_WideString FromLocal(const char* str, FX_STRSIZE len = -1);
654 static CFX_WideString FromUTF8(const char* str, FX_STRSIZE len);
656 static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len);
658 static FX_STRSIZE WStringLength(const unsigned short* str);
660 // Explicit conversion to raw string
661 FX_LPCWSTR c_str() const
663 return m_pData ? m_pData->m_String : L"";
666 // Implicit conversion to C-style wide string -- deprecated
667 operator FX_LPCWSTR() const
669 return m_pData ? m_pData->m_String : L"";
675 FX_BOOL IsEmpty() const
680 FX_STRSIZE GetLength() const
682 return m_pData ? m_pData->m_nDataLength : 0;
685 const CFX_WideString& operator = (FX_LPCWSTR str);
687 const CFX_WideString& operator =(const CFX_WideString& stringSrc);
689 const CFX_WideString& operator =(const CFX_WideStringC& stringSrc);
691 const CFX_WideString& operator += (FX_LPCWSTR str);
693 const CFX_WideString& operator += (FX_WCHAR ch);
695 const CFX_WideString& operator += (const CFX_WideString& str);
697 const CFX_WideString& operator += (const CFX_WideStringC& str);
699 bool operator== (const wchar_t* ptr) const { return Equal(ptr); }
700 bool operator== (const CFX_WideStringC& str) const { return Equal(str); }
701 bool operator== (const CFX_WideString& other) const { return Equal(other); }
703 bool operator!= (const wchar_t* ptr) const { return !(*this == ptr); }
704 bool operator!= (const CFX_WideStringC& str) const {
705 return !(*this == str);
707 bool operator!= (const CFX_WideString& other) const {
708 return !(*this == other);
711 bool operator< (const CFX_WideString& str) const {
712 int result = wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength()));
713 return result < 0 || (result == 0 && GetLength() < str.GetLength());
716 FX_WCHAR GetAt(FX_STRSIZE nIndex) const
718 return m_pData ? m_pData->m_String[nIndex] : 0;
721 FX_WCHAR operator[](FX_STRSIZE nIndex) const
723 return m_pData ? m_pData->m_String[nIndex] : 0;
726 void SetAt(FX_STRSIZE nIndex, FX_WCHAR ch);
728 int Compare(FX_LPCWSTR str) const;
730 int Compare(const CFX_WideString& str) const;
732 int CompareNoCase(FX_LPCWSTR str) const;
734 bool Equal(const wchar_t* ptr) const;
735 bool Equal(const CFX_WideStringC& str) const;
736 bool Equal(const CFX_WideString& other) const;
738 CFX_WideString Mid(FX_STRSIZE first) const;
740 CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const;
742 CFX_WideString Left(FX_STRSIZE count) const;
744 CFX_WideString Right(FX_STRSIZE count) const;
746 FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch);
748 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1);
750 void Format(FX_LPCWSTR lpszFormat, ... );
752 void FormatV(FX_LPCWSTR lpszFormat, va_list argList);
760 void TrimRight(FX_WCHAR chTarget);
762 void TrimRight(FX_LPCWSTR lpszTargets);
766 void TrimLeft(FX_WCHAR chTarget);
768 void TrimLeft(FX_LPCWSTR lpszTargets);
770 void Reserve(FX_STRSIZE len);
772 FX_LPWSTR GetBuffer(FX_STRSIZE len);
774 void ReleaseBuffer(FX_STRSIZE len = -1);
776 int GetInteger() const;
778 FX_FLOAT GetFloat() const;
780 FX_STRSIZE Find(FX_LPCWSTR lpszSub, FX_STRSIZE start = 0) const;
782 FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0) const;
784 FX_STRSIZE Replace(FX_LPCWSTR lpszOld, FX_LPCWSTR lpszNew);
786 FX_STRSIZE Remove(FX_WCHAR ch);
788 CFX_ByteString UTF8Encode() const;
790 CFX_ByteString UTF16LE_Encode() const;
792 void ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL);
797 static StringData* Create(int nLen);
798 void Retain() { ++m_nRefs; }
799 void Release() { if (--m_nRefs <= 0) FX_Free(this); }
801 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support.
802 FX_STRSIZE m_nDataLength;
803 FX_STRSIZE m_nAllocLength;
804 FX_WCHAR m_String[1];
807 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
808 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
809 FXSYS_assert(dataLen >= 0);
810 FXSYS_assert(allocLen >= 0);
811 FXSYS_assert(dataLen <= allocLen);
812 m_String[dataLen] = 0;
814 ~StringData() = delete;
817 void CopyBeforeWrite();
818 void AllocBeforeWrite(FX_STRSIZE nLen);
819 void ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
820 void ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data);
821 void AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
822 void AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
825 friend class fxcrt_WideStringConcatInPlace_Test;
827 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src)
830 m_Length = src.GetLength();
832 inline CFX_WideStringC& CFX_WideStringC::operator = (const CFX_WideString& src)
835 m_Length = src.GetLength();
839 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideStringC& str2)
841 return CFX_WideString(str1, str2);
843 inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_LPCWSTR str2)
845 return CFX_WideString(str1, str2);
847 inline CFX_WideString operator + (FX_LPCWSTR str1, const CFX_WideStringC& str2)
849 return CFX_WideString(str1, str2);
851 inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_WCHAR ch)
853 return CFX_WideString(str1, CFX_WideStringC(ch));
855 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideStringC& str2)
857 return CFX_WideString(ch, str2);
859 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideString& str2)
861 return CFX_WideString(str1, str2);
863 inline CFX_WideString operator + (const CFX_WideString& str1, FX_WCHAR ch)
865 return CFX_WideString(str1, CFX_WideStringC(ch));
867 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideString& str2)
869 return CFX_WideString(ch, str2);
871 inline CFX_WideString operator + (const CFX_WideString& str1, FX_LPCWSTR str2)
873 return CFX_WideString(str1, str2);
875 inline CFX_WideString operator + (FX_LPCWSTR str1, const CFX_WideString& str2)
877 return CFX_WideString(str1, str2);
879 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideStringC& str2)
881 return CFX_WideString(str1, str2);
883 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideString& str2)
885 return CFX_WideString(str1, str2);
887 inline bool operator== (const wchar_t* lhs, const CFX_WideString& rhs) {
890 inline bool operator== (const CFX_WideStringC& lhs, const CFX_WideString& rhs) {
893 inline bool operator!= (const wchar_t* lhs, const CFX_WideString& rhs) {
896 inline bool operator!= (const CFX_WideStringC& lhs, const CFX_WideString& rhs) {
899 FX_FLOAT FX_atof(FX_BSTR str);
900 void FX_atonum(FX_BSTR str, FX_BOOL& bInteger, void* pData);
901 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_LPSTR buf);
902 CFX_ByteString FX_UTF8Encode(FX_LPCWSTR pwsStr, FX_STRSIZE len);
903 inline CFX_ByteString FX_UTF8Encode(FX_WSTR wsStr)
905 return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength());
907 inline CFX_ByteString FX_UTF8Encode(const CFX_WideString &wsStr)
909 return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength());
912 #endif // CORE_INCLUDE_FXCRT_FX_STRING_H_