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