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 {
     25 public:
     26     typedef FX_CHAR value_type;
     27 
     28     CFX_ByteStringC()
     29     {
     30         m_Ptr = NULL;
     31         m_Length = 0;
     32     }
     33 
     34     CFX_ByteStringC(FX_LPCBYTE ptr, FX_STRSIZE size)
     35     {
     36         m_Ptr = ptr;
     37         m_Length = size;
     38     }
     39 
     40     CFX_ByteStringC(FX_LPCSTR ptr)
     41     {
     42         m_Ptr = (FX_LPCBYTE)ptr;
     43         m_Length = ptr ? FXSYS_strlen(ptr) : 0;
     44     }
     45 
     46     // |ch| must be an lvalue that outlives the the CFX_ByteStringC. However,
     47     // the use of char rvalues are not caught at compile time.  They are
     48     // implicitly promoted to CFX_ByteString (see below) and then the
     49     // CFX_ByteStringC is constructed from the CFX_ByteString via the alternate
     50     // constructor below. The CFX_ByteString then typically goes out of scope
     51     // and |m_Ptr| may be left pointing to invalid memory. Beware.
     52     // TODO(tsepez): Mark single-argument string constructors as explicit.
     53     CFX_ByteStringC(FX_CHAR& ch)
     54     {
     55         m_Ptr = (FX_LPCBYTE)&ch;
     56         m_Length = 1;
     57     }
     58 
     59     CFX_ByteStringC(FX_LPCSTR ptr, FX_STRSIZE len)
     60     {
     61         m_Ptr = (FX_LPCBYTE)ptr;
     62         m_Length = (len == -1) ? FXSYS_strlen(ptr) : len;
     63     }
     64 
     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 
    104     FX_LPCBYTE		GetPtr() const
    105     {
    106         return m_Ptr;
    107     }
    108 
    109     FX_LPCSTR		GetCStr() const
    110     {
    111         return (FX_LPCSTR)m_Ptr;
    112     }
    113 
    114     FX_STRSIZE		GetLength() const
    115     {
    116         return m_Length;
    117     }
    118 
    119     bool			IsEmpty() const
    120     {
    121         return m_Length == 0;
    122     }
    123 
    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:
    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 
    181     CFX_ByteString()
    182     {
    183         m_pData = NULL;
    184     }
    185 
    186     CFX_ByteString(const CFX_ByteString& str);
    187 
    188     CFX_ByteString(char ch);
    189 
    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
    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
    213     operator				FX_LPCSTR() const
    214     {
    215         return m_pData ? m_pData->m_String : "";
    216     }
    217 
    218     operator				FX_LPCBYTE() const
    219     {
    220         return m_pData ? (FX_LPCBYTE)m_pData->m_String : NULL;
    221     }
    222 
    223     FX_STRSIZE				GetLength() const
    224     {
    225         return m_pData ? m_pData->m_nDataLength : 0;
    226     }
    227 
    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 
    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);
    365         void Retain() { ++m_nRefs; }
    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:
    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 };
    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 
    472     CFX_WideStringC()
    473     {
    474         m_Ptr = NULL;
    475         m_Length = 0;
    476     }
    477 
    478     CFX_WideStringC(FX_LPCWSTR ptr)
    479     {
    480         m_Ptr = ptr;
    481         m_Length = ptr ? FXSYS_wcslen(ptr) : 0;
    482     }
    483 
    484     CFX_WideStringC(FX_WCHAR& ch)
    485     {
    486         m_Ptr = &ch;
    487         m_Length = 1;
    488     }
    489 
    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 
    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 
    533     FX_LPCWSTR		GetPtr() const
    534     {
    535         return m_Ptr;
    536     }
    537 
    538     FX_STRSIZE		GetLength() const
    539     {
    540         return m_Length;
    541     }
    542 
    543     bool			IsEmpty() const
    544     {
    545         return m_Length == 0;
    546     }
    547 
    548     FX_WCHAR		GetAt(FX_STRSIZE index) const
    549     {
    550         return m_Ptr[index];
    551     }
    552 
    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 
    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:
    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 
    626     CFX_WideString()
    627     {
    628         m_pData = NULL;
    629     }
    630 
    631     CFX_WideString(const CFX_WideString& str);
    632 
    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
    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
    661     operator FX_LPCWSTR() const
    662     {
    663         return m_pData ? m_pData->m_String : L"";
    664     }
    665 
    666     void					Empty();
    667 
    668 
    669     FX_BOOL					IsEmpty() const
    670     {
    671         return !GetLength();
    672     }
    673 
    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 
    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);
    792         void Retain() { ++m_nRefs; }
    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:
    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 };
    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);
    897 inline CFX_ByteString	FX_UTF8Encode(FX_WSTR wsStr)
    898 {
    899     return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength());
    900 }
    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