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 #include "../../include/fxcrt/fx_basic.h"
      8 static CFX_StringDataW* FX_AllocStringW(int nLen)
      9 {
     10     if (nLen == 0) {
     11         return NULL;
     12     }
     13     CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, sizeof(long) * 3 + (nLen + 1) * sizeof(FX_WCHAR));
     14     if (!pData) {
     15         return NULL;
     16     }
     17     pData->m_nAllocLength = nLen;
     18     pData->m_nDataLength = nLen;
     19     pData->m_nRefs = 1;
     20     pData->m_String[nLen] = 0;
     21     return pData;
     22 }
     23 static void FX_ReleaseStringW(CFX_StringDataW* pData)
     24 {
     25     if (pData == NULL) {
     26         return;
     27     }
     28     pData->m_nRefs --;
     29     if (pData->m_nRefs <= 0) {
     30         FX_Free(pData);
     31     }
     32 }
     33 CFX_WideString::~CFX_WideString()
     34 {
     35     if (m_pData == NULL) {
     36         return;
     37     }
     38     m_pData->m_nRefs --;
     39     if (m_pData->m_nRefs < 1) {
     40         FX_Free(m_pData);
     41     }
     42 }
     43 void CFX_WideString::InitStr(FX_LPCWSTR lpsz, FX_STRSIZE nLen)
     44 {
     45     if (nLen < 0) {
     46         nLen = lpsz ? (FX_STRSIZE)FXSYS_wcslen(lpsz) : 0;
     47     }
     48     if (nLen) {
     49         m_pData = FX_AllocStringW(nLen);
     50         if (!m_pData) {
     51             return;
     52         }
     53         FXSYS_memcpy32(m_pData->m_String, lpsz, nLen * sizeof(FX_WCHAR));
     54     } else {
     55         m_pData = NULL;
     56     }
     57 }
     58 CFX_WideString::CFX_WideString(const CFX_WideString& stringSrc)
     59 {
     60     if (stringSrc.m_pData == NULL) {
     61         m_pData = NULL;
     62         return;
     63     }
     64     if (stringSrc.m_pData->m_nRefs >= 0) {
     65         m_pData = stringSrc.m_pData;
     66         m_pData->m_nRefs ++;
     67     } else {
     68         m_pData = NULL;
     69         *this = stringSrc;
     70     }
     71 }
     72 CFX_WideString::CFX_WideString(FX_WCHAR ch)
     73 {
     74     m_pData = FX_AllocStringW(1);
     75     if (m_pData) {
     76         m_pData->m_String[0] = ch;
     77     }
     78 }
     79 CFX_WideString::CFX_WideString(const CFX_WideStringC& str)
     80 {
     81     if (str.IsEmpty()) {
     82         m_pData = NULL;
     83         return;
     84     }
     85     m_pData = FX_AllocStringW(str.GetLength());
     86     if (m_pData) {
     87         FXSYS_memcpy32(m_pData->m_String, str.GetPtr(), str.GetLength()*sizeof(FX_WCHAR));
     88     }
     89 }
     90 CFX_WideString::CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2)
     91 {
     92     m_pData = NULL;
     93     int nNewLen = str1.GetLength() + str2.GetLength();
     94     if (nNewLen == 0) {
     95         return;
     96     }
     97     m_pData = FX_AllocStringW(nNewLen);
     98     if (m_pData) {
     99         FXSYS_memcpy32(m_pData->m_String, str1.GetPtr(), str1.GetLength()*sizeof(FX_WCHAR));
    100         FXSYS_memcpy32(m_pData->m_String + str1.GetLength(), str2.GetPtr(), str2.GetLength()*sizeof(FX_WCHAR));
    101     }
    102 }
    103 void CFX_WideString::ReleaseBuffer(FX_STRSIZE nNewLength)
    104 {
    105     if (m_pData == NULL) {
    106         return;
    107     }
    108     CopyBeforeWrite();
    109     if (nNewLength == -1) {
    110         nNewLength = m_pData ? (FX_STRSIZE)FXSYS_wcslen(m_pData->m_String) : 0;
    111     }
    112     if (nNewLength == 0) {
    113         Empty();
    114         return;
    115     }
    116     FXSYS_assert(nNewLength <= m_pData->m_nAllocLength);
    117     m_pData->m_nDataLength = nNewLength;
    118     m_pData->m_String[nNewLength] = 0;
    119 }
    120 const CFX_WideString& CFX_WideString::operator=(FX_LPCWSTR lpsz)
    121 {
    122     if (lpsz == NULL || lpsz[0] == 0) {
    123         Empty();
    124     } else {
    125         AssignCopy((FX_STRSIZE)FXSYS_wcslen(lpsz), lpsz);
    126     }
    127     return *this;
    128 }
    129 const CFX_WideString& CFX_WideString::operator=(const CFX_WideStringC& stringSrc)
    130 {
    131     if (stringSrc.IsEmpty()) {
    132         Empty();
    133     } else {
    134         AssignCopy(stringSrc.GetLength(), stringSrc.GetPtr());
    135     }
    136     return *this;
    137 }
    138 const CFX_WideString& CFX_WideString::operator=(const CFX_WideString& stringSrc)
    139 {
    140     if (m_pData == stringSrc.m_pData) {
    141         return *this;
    142     }
    143     if (stringSrc.IsEmpty()) {
    144         Empty();
    145     } else if ((m_pData && m_pData->m_nRefs < 0) ||
    146                (stringSrc.m_pData && stringSrc.m_pData->m_nRefs < 0)) {
    147         AssignCopy(stringSrc.m_pData->m_nDataLength, stringSrc.m_pData->m_String);
    148     } else {
    149         Empty();
    150         m_pData = stringSrc.m_pData;
    151         if (m_pData) {
    152             m_pData->m_nRefs ++;
    153         }
    154     }
    155     return *this;
    156 }
    157 const CFX_WideString& CFX_WideString::operator+=(FX_WCHAR ch)
    158 {
    159     ConcatInPlace(1, &ch);
    160     return *this;
    161 }
    162 const CFX_WideString& CFX_WideString::operator+=(FX_LPCWSTR lpsz)
    163 {
    164     if (lpsz) {
    165         ConcatInPlace((FX_STRSIZE)FXSYS_wcslen(lpsz), lpsz);
    166     }
    167     return *this;
    168 }
    169 const CFX_WideString& CFX_WideString::operator+=(const CFX_WideString& string)
    170 {
    171     if (string.m_pData == NULL) {
    172         return *this;
    173     }
    174     ConcatInPlace(string.m_pData->m_nDataLength, string.m_pData->m_String);
    175     return *this;
    176 }
    177 const CFX_WideString& CFX_WideString::operator+=(const CFX_WideStringC& string)
    178 {
    179     if (string.IsEmpty()) {
    180         return *this;
    181     }
    182     ConcatInPlace(string.GetLength(), string.GetPtr());
    183     return *this;
    184 }
    185 bool operator==(const CFX_WideString& s1, FX_LPCWSTR s2)
    186 {
    187     return s1.Equal(s2);
    188 }
    189 bool operator==(FX_LPCWSTR s1, const CFX_WideString& s2)
    190 {
    191     return s2.Equal(s1);
    192 }
    193 bool operator==(const CFX_WideString& s1, const CFX_WideString& s2)
    194 {
    195     return s1.Equal(s2);
    196 }
    197 bool operator==(const CFX_WideString& s1, const CFX_WideStringC& s2)
    198 {
    199     return s1.Equal(s2);
    200 }
    201 bool operator==(const CFX_WideStringC& s1, const CFX_WideString& s2)
    202 {
    203     return s2.Equal(s1);
    204 }
    205 bool operator != (const CFX_WideString& s1, FX_LPCWSTR s2)
    206 {
    207     return !s1.Equal(s2);
    208 }
    209 bool operator!=(const CFX_WideString& s1, const CFX_WideString& s2)
    210 {
    211     return !s1.Equal(s2);
    212 }
    213 bool operator!=(const CFX_WideString& s1, const CFX_WideStringC& s2)
    214 {
    215     return !s1.Equal(s2);
    216 }
    217 bool operator!=(const CFX_WideStringC& s1, const CFX_WideString& s2)
    218 {
    219     return !s2.Equal(s1);
    220 }
    221 bool CFX_WideString::Equal(const CFX_WideStringC& str) const
    222 {
    223     if (m_pData == NULL) {
    224         return str.IsEmpty();
    225     }
    226     return str.GetLength() == m_pData->m_nDataLength &&
    227            FXSYS_memcmp32(str.GetPtr(), m_pData->m_String, m_pData->m_nDataLength * sizeof(FX_WCHAR)) == 0;
    228 }
    229 void CFX_WideString::Empty()
    230 {
    231     if (m_pData == NULL) {
    232         return;
    233     }
    234     if (m_pData->m_nRefs > 1) {
    235         m_pData->m_nRefs --;
    236     } else {
    237         FX_Free(m_pData);
    238     }
    239     m_pData = NULL;
    240 }
    241 void CFX_WideString::ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData)
    242 {
    243     if (nSrcLen == 0 || lpszSrcData == NULL) {
    244         return;
    245     }
    246     if (m_pData == NULL) {
    247         m_pData = FX_AllocStringW(nSrcLen);
    248         if (m_pData) {
    249             FXSYS_memcpy32(m_pData->m_String, lpszSrcData, nSrcLen * sizeof(FX_WCHAR));
    250         }
    251         return;
    252     }
    253     if (m_pData->m_nRefs > 1 || m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) {
    254         CFX_StringDataW* pOldData = m_pData;
    255         ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData);
    256         FX_ReleaseStringW(pOldData);
    257     } else {
    258         FXSYS_memcpy32(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, nSrcLen * sizeof(FX_WCHAR));
    259         m_pData->m_nDataLength += nSrcLen;
    260         m_pData->m_String[m_pData->m_nDataLength] = 0;
    261     }
    262 }
    263 void CFX_WideString::ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data,
    264                                 FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data)
    265 {
    266     FX_STRSIZE nNewLen = nSrc1Len + nSrc2Len;
    267     if (nNewLen == 0) {
    268         return;
    269     }
    270     m_pData = FX_AllocStringW(nNewLen);
    271     if (m_pData) {
    272         FXSYS_memcpy32(m_pData->m_String, lpszSrc1Data, nSrc1Len * sizeof(FX_WCHAR));
    273         FXSYS_memcpy32(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len * sizeof(FX_WCHAR));
    274     }
    275 }
    276 void CFX_WideString::CopyBeforeWrite()
    277 {
    278     if (m_pData == NULL || m_pData->m_nRefs <= 1) {
    279         return;
    280     }
    281     CFX_StringDataW* pData = m_pData;
    282     m_pData->m_nRefs --;
    283     FX_STRSIZE nDataLength = pData->m_nDataLength;
    284     m_pData = FX_AllocStringW(nDataLength);
    285     if (m_pData != NULL) {
    286         FXSYS_memcpy32(m_pData->m_String, pData->m_String, (nDataLength + 1) * sizeof(FX_WCHAR));
    287     }
    288 }
    289 void CFX_WideString::AllocBeforeWrite(FX_STRSIZE nLen)
    290 {
    291     if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nLen) {
    292         return;
    293     }
    294     Empty();
    295     m_pData = FX_AllocStringW(nLen);
    296 }
    297 void CFX_WideString::AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData)
    298 {
    299     AllocBeforeWrite(nSrcLen);
    300     FXSYS_memcpy32(m_pData->m_String, lpszSrcData, nSrcLen * sizeof(FX_WCHAR));
    301     m_pData->m_nDataLength = nSrcLen;
    302     m_pData->m_String[nSrcLen] = 0;
    303 }
    304 int CFX_WideString::Compare(FX_LPCWSTR lpsz) const
    305 {
    306     if (m_pData == NULL) {
    307         return (lpsz == NULL || lpsz[0] == 0) ? 0 : -1;
    308     }
    309     return FXSYS_wcscmp(m_pData->m_String, lpsz);
    310 }
    311 CFX_ByteString CFX_WideString::UTF8Encode() const
    312 {
    313     return FX_UTF8Encode(*this);
    314 }
    315 CFX_ByteString CFX_WideString::UTF16LE_Encode(FX_BOOL bTerminate) const
    316 {
    317     if (m_pData == NULL) {
    318         return bTerminate ? CFX_ByteString(FX_BSTRC("\0\0")) : CFX_ByteString();
    319     }
    320     int len = m_pData->m_nDataLength;
    321     CFX_ByteString result;
    322     FX_LPSTR buffer = result.GetBuffer(len * 2 + (bTerminate ? 2 : 0));
    323     for (int i = 0; i < len; i ++) {
    324         buffer[i * 2] = m_pData->m_String[i] & 0xff;
    325         buffer[i * 2 + 1] = m_pData->m_String[i] >> 8;
    326     }
    327     if (bTerminate) {
    328         buffer[len * 2] = 0;
    329         buffer[len * 2 + 1] = 0;
    330         result.ReleaseBuffer(len * 2 + 2);
    331     } else {
    332         result.ReleaseBuffer(len * 2);
    333     }
    334     return result;
    335 }
    336 void CFX_WideString::ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap)
    337 {
    338     if (pCharMap == NULL) {
    339         pCharMap = CFX_CharMap::GetDefaultMapper();
    340     }
    341     *this = pCharMap->m_GetWideString(pCharMap, str);
    342 }
    343 void CFX_WideString::Reserve(FX_STRSIZE len)
    344 {
    345     GetBuffer(len);
    346     ReleaseBuffer(GetLength());
    347 }
    348 FX_LPWSTR CFX_WideString::GetBuffer(FX_STRSIZE nMinBufLength)
    349 {
    350     if (m_pData == NULL && nMinBufLength == 0) {
    351         return NULL;
    352     }
    353     if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nMinBufLength) {
    354         return m_pData->m_String;
    355     }
    356     if (m_pData == NULL) {
    357         m_pData = FX_AllocStringW(nMinBufLength);
    358         if (!m_pData) {
    359             return NULL;
    360         }
    361         m_pData->m_nDataLength = 0;
    362         m_pData->m_String[0] = 0;
    363         return m_pData->m_String;
    364     }
    365     CFX_StringDataW* pOldData = m_pData;
    366     FX_STRSIZE nOldLen = pOldData->m_nDataLength;
    367     if (nMinBufLength < nOldLen) {
    368         nMinBufLength = nOldLen;
    369     }
    370     m_pData = FX_AllocStringW(nMinBufLength);
    371     if (!m_pData) {
    372         return NULL;
    373     }
    374     FXSYS_memcpy32(m_pData->m_String, pOldData->m_String, (nOldLen + 1)*sizeof(FX_WCHAR));
    375     m_pData->m_nDataLength = nOldLen;
    376     pOldData->m_nRefs --;
    377     if (pOldData->m_nRefs <= 0) {
    378         FX_Free(pOldData);
    379     }
    380     return m_pData->m_String;
    381 }
    382 CFX_WideString CFX_WideString::FromLocal(const char* str, FX_STRSIZE len)
    383 {
    384     CFX_WideString result;
    385     result.ConvertFrom(CFX_ByteString(str, len));
    386     return result;
    387 }
    388 CFX_WideString CFX_WideString::FromUTF8(const char* str, FX_STRSIZE len)
    389 {
    390     if (!str) {
    391         return CFX_WideString();
    392     }
    393     if (len < 0) {
    394         len = 0;
    395         while (str[len]) {
    396             len ++;
    397         }
    398     }
    399     CFX_UTF8Decoder decoder;
    400     for (FX_STRSIZE i = 0; i < len; i ++) {
    401         decoder.Input(str[i]);
    402     }
    403     return decoder.GetResult();
    404 }
    405 CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZE wlen)
    406 {
    407     if (!wstr || !wlen) {
    408         return CFX_WideString();
    409     }
    410     if (wlen < 0) {
    411         wlen = 0;
    412         while (wstr[wlen]) {
    413             wlen ++;
    414         }
    415     }
    416     CFX_WideString result;
    417     FX_WCHAR* buf = result.GetBuffer(wlen);
    418     for (int i = 0; i < wlen; i ++) {
    419         buf[i] = wstr[i];
    420     }
    421     result.ReleaseBuffer(wlen);
    422     return result;
    423 }
    424 void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex,
    425                                FX_STRSIZE nExtraLen) const
    426 {
    427     FX_STRSIZE nNewLen = nCopyLen + nExtraLen;
    428     if (nNewLen == 0) {
    429         return;
    430     }
    431     ASSERT(dest.m_pData == NULL);
    432     dest.m_pData = FX_AllocStringW(nNewLen);
    433     if (dest.m_pData) {
    434         FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, nCopyLen * sizeof(FX_WCHAR));
    435     }
    436 }
    437 CFX_WideString CFX_WideString::Left(FX_STRSIZE nCount) const
    438 {
    439     if (m_pData == NULL) {
    440         return CFX_WideString();
    441     }
    442     if (nCount < 0) {
    443         nCount = 0;
    444     }
    445     if (nCount >= m_pData->m_nDataLength) {
    446         return *this;
    447     }
    448     CFX_WideString dest;
    449     AllocCopy(dest, nCount, 0, 0);
    450     return dest;
    451 }
    452 CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst) const
    453 {
    454     return Mid(nFirst, m_pData->m_nDataLength - nFirst);
    455 }
    456 CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const
    457 {
    458     if (m_pData == NULL) {
    459         return CFX_WideString();
    460     }
    461     if (nFirst < 0) {
    462         nFirst = 0;
    463     }
    464     if (nCount < 0) {
    465         nCount = 0;
    466     }
    467     if (nFirst + nCount > m_pData->m_nDataLength) {
    468         nCount = m_pData->m_nDataLength - nFirst;
    469     }
    470     if (nFirst > m_pData->m_nDataLength) {
    471         nCount = 0;
    472     }
    473     if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength) {
    474         return *this;
    475     }
    476     CFX_WideString dest;
    477     AllocCopy(dest, nCount, nFirst, 0);
    478     return dest;
    479 }
    480 CFX_WideString CFX_WideString::Right(FX_STRSIZE nCount) const
    481 {
    482     if (m_pData == NULL) {
    483         return CFX_WideString();
    484     }
    485     if (nCount < 0) {
    486         nCount = 0;
    487     }
    488     if (nCount >= m_pData->m_nDataLength) {
    489         return *this;
    490     }
    491     CFX_WideString dest;
    492     AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount, 0);
    493     return dest;
    494 }
    495 int CFX_WideString::CompareNoCase(FX_LPCWSTR lpsz) const
    496 {
    497     if (m_pData == NULL) {
    498         return (lpsz == NULL || lpsz[0] == 0) ? 0 : -1;
    499     }
    500     return FXSYS_wcsicmp(m_pData->m_String, lpsz);
    501 }
    502 int CFX_WideString::Compare(const CFX_WideString& str) const
    503 {
    504     if (m_pData == NULL) {
    505         if (str.m_pData == NULL) {
    506             return 0;
    507         }
    508         return -1;
    509     } else if (str.m_pData == NULL) {
    510         return 1;
    511     }
    512     int this_len = m_pData->m_nDataLength;
    513     int that_len = str.m_pData->m_nDataLength;
    514     int min_len = this_len < that_len ? this_len : that_len;
    515     for (int i = 0; i < min_len; i ++) {
    516         if (m_pData->m_String[i] < str.m_pData->m_String[i]) {
    517             return -1;
    518         } else if (m_pData->m_String[i] > str.m_pData->m_String[i]) {
    519             return 1;
    520         }
    521     }
    522     if (this_len < that_len) {
    523         return -1;
    524     } else if (this_len > that_len) {
    525         return 1;
    526     }
    527     return 0;
    528 }
    529 FX_LPWSTR CFX_WideString::LockBuffer()
    530 {
    531     if (m_pData == NULL) {
    532         return NULL;
    533     }
    534     FX_LPWSTR lpsz = GetBuffer(0);
    535     m_pData->m_nRefs = -1;
    536     return lpsz;
    537 }
    538 void CFX_WideString::SetAt(FX_STRSIZE nIndex, FX_WCHAR ch)
    539 {
    540     if (m_pData == NULL) {
    541         return;
    542     }
    543     ASSERT(nIndex >= 0);
    544     ASSERT(nIndex < m_pData->m_nDataLength);
    545     CopyBeforeWrite();
    546     m_pData->m_String[nIndex] = ch;
    547 }
    548 void CFX_WideString::MakeLower()
    549 {
    550     if (m_pData == NULL) {
    551         return;
    552     }
    553     CopyBeforeWrite();
    554     if (GetLength() < 1) {
    555         return;
    556     }
    557     FXSYS_wcslwr(m_pData->m_String);
    558 }
    559 void CFX_WideString::MakeUpper()
    560 {
    561     if (m_pData == NULL) {
    562         return;
    563     }
    564     CopyBeforeWrite();
    565     if (GetLength() < 1) {
    566         return;
    567     }
    568     FXSYS_wcsupr(m_pData->m_String);
    569 }
    570 FX_STRSIZE CFX_WideString::Find(FX_LPCWSTR lpszSub, FX_STRSIZE nStart) const
    571 {
    572     FX_STRSIZE nLength = GetLength();
    573     if (nLength < 1 || nStart > nLength) {
    574         return -1;
    575     }
    576     FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcsstr(m_pData->m_String + nStart, lpszSub);
    577     return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String);
    578 }
    579 FX_STRSIZE CFX_WideString::Find(FX_WCHAR ch, FX_STRSIZE nStart) const
    580 {
    581     if (m_pData == NULL) {
    582         return -1;
    583     }
    584     FX_STRSIZE nLength = m_pData->m_nDataLength;
    585     if (nStart >= nLength) {
    586         return -1;
    587     }
    588     FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcschr(m_pData->m_String + nStart, ch);
    589     return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String);
    590 }
    591 void CFX_WideString::TrimRight(FX_LPCWSTR lpszTargetList)
    592 {
    593     FXSYS_assert(lpszTargetList != NULL);
    594     if (m_pData == NULL || *lpszTargetList == 0) {
    595         return;
    596     }
    597     CopyBeforeWrite();
    598     FX_STRSIZE len = GetLength();
    599     if (len < 1) {
    600         return;
    601     }
    602     FX_STRSIZE pos = len;
    603     while (pos) {
    604         if (FXSYS_wcschr(lpszTargetList, m_pData->m_String[pos - 1]) == NULL) {
    605             break;
    606         }
    607         pos --;
    608     }
    609     if (pos < len) {
    610         m_pData->m_String[pos] = 0;
    611         m_pData->m_nDataLength = pos;
    612     }
    613 }
    614 void CFX_WideString::TrimRight(FX_WCHAR chTarget)
    615 {
    616     FX_WCHAR str[2] = {chTarget, 0};
    617     TrimRight(str);
    618 }
    619 void CFX_WideString::TrimRight()
    620 {
    621     TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20");
    622 }
    623 void CFX_WideString::TrimLeft(FX_LPCWSTR lpszTargets)
    624 {
    625     FXSYS_assert(lpszTargets != NULL);
    626     if (m_pData == NULL || *lpszTargets == 0) {
    627         return;
    628     }
    629     CopyBeforeWrite();
    630     if (GetLength() < 1) {
    631         return;
    632     }
    633     FX_LPCWSTR lpsz = m_pData->m_String;
    634     while (*lpsz != 0) {
    635         if (FXSYS_wcschr(lpszTargets, *lpsz) == NULL) {
    636             break;
    637         }
    638         lpsz ++;
    639     }
    640     if (lpsz != m_pData->m_String) {
    641         int nDataLength = m_pData->m_nDataLength - (FX_STRSIZE)(lpsz - m_pData->m_String);
    642         FXSYS_memmove32(m_pData->m_String, lpsz, (nDataLength + 1)*sizeof(FX_WCHAR));
    643         m_pData->m_nDataLength = nDataLength;
    644     }
    645 }
    646 void CFX_WideString::TrimLeft(FX_WCHAR chTarget)
    647 {
    648     FX_WCHAR str[2] = {chTarget, 0};
    649     TrimLeft(str);
    650 }
    651 void CFX_WideString::TrimLeft()
    652 {
    653     TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20");
    654 }
    655 FX_STRSIZE CFX_WideString::Replace(FX_LPCWSTR lpszOld, FX_LPCWSTR lpszNew)
    656 {
    657     if (GetLength() < 1) {
    658         return 0;
    659     }
    660     if (lpszOld == NULL) {
    661         return 0;
    662     }
    663     FX_STRSIZE nSourceLen = (FX_STRSIZE)FXSYS_wcslen(lpszOld);
    664     if (nSourceLen == 0) {
    665         return 0;
    666     }
    667     FX_STRSIZE nReplacementLen = lpszNew ? (FX_STRSIZE)FXSYS_wcslen(lpszNew) : 0;
    668     FX_STRSIZE nCount = 0;
    669     FX_LPWSTR lpszStart = m_pData->m_String;
    670     FX_LPWSTR lpszEnd = m_pData->m_String + m_pData->m_nDataLength;
    671     FX_LPWSTR lpszTarget;
    672     {
    673         while ((lpszTarget = (FX_LPWSTR)FXSYS_wcsstr(lpszStart, lpszOld)) != NULL && lpszStart < lpszEnd) {
    674             nCount++;
    675             lpszStart = lpszTarget + nSourceLen;
    676         }
    677     }
    678     if (nCount > 0) {
    679         CopyBeforeWrite();
    680         FX_STRSIZE nOldLength = m_pData->m_nDataLength;
    681         FX_STRSIZE nNewLength =  nOldLength + (nReplacementLen - nSourceLen) * nCount;
    682         if (m_pData->m_nAllocLength < nNewLength || m_pData->m_nRefs > 1) {
    683             CFX_StringDataW* pOldData = m_pData;
    684             FX_LPCWSTR pstr = m_pData->m_String;
    685             m_pData = FX_AllocStringW(nNewLength);
    686             if (!m_pData) {
    687                 return 0;
    688             }
    689             FXSYS_memcpy32(m_pData->m_String, pstr, pOldData->m_nDataLength * sizeof(FX_WCHAR));
    690             FX_ReleaseStringW(pOldData);
    691         }
    692         lpszStart = m_pData->m_String;
    693         lpszEnd = m_pData->m_String + FX_MAX(m_pData->m_nDataLength, nNewLength);
    694         {
    695             while ((lpszTarget = (FX_LPWSTR)FXSYS_wcsstr(lpszStart, lpszOld)) != NULL && lpszStart < lpszEnd) {
    696                 FX_STRSIZE nBalance = nOldLength - (FX_STRSIZE)(lpszTarget - m_pData->m_String + nSourceLen);
    697                 FXSYS_memmove32(lpszTarget + nReplacementLen, lpszTarget + nSourceLen, nBalance * sizeof(FX_WCHAR));
    698                 FXSYS_memcpy32(lpszTarget, lpszNew, nReplacementLen * sizeof(FX_WCHAR));
    699                 lpszStart = lpszTarget + nReplacementLen;
    700                 lpszStart[nBalance] = 0;
    701                 nOldLength += (nReplacementLen - nSourceLen);
    702             }
    703         }
    704         ASSERT(m_pData->m_String[nNewLength] == 0);
    705         m_pData->m_nDataLength = nNewLength;
    706     }
    707     return nCount;
    708 }
    709 FX_STRSIZE CFX_WideString::Insert(FX_STRSIZE nIndex, FX_WCHAR ch)
    710 {
    711     CopyBeforeWrite();
    712     if (nIndex < 0) {
    713         nIndex = 0;
    714     }
    715     FX_STRSIZE nNewLength = GetLength();
    716     if (nIndex > nNewLength) {
    717         nIndex = nNewLength;
    718     }
    719     nNewLength++;
    720     if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) {
    721         CFX_StringDataW* pOldData = m_pData;
    722         FX_LPCWSTR pstr = m_pData->m_String;
    723         m_pData = FX_AllocStringW(nNewLength);
    724         if (!m_pData) {
    725             return 0;
    726         }
    727         if(pOldData != NULL) {
    728             FXSYS_memmove32(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1)*sizeof(FX_WCHAR));
    729             FX_ReleaseStringW(pOldData);
    730         } else {
    731             m_pData->m_String[0] = 0;
    732         }
    733     }
    734     FXSYS_memmove32(m_pData->m_String + nIndex + 1,
    735                     m_pData->m_String + nIndex, (nNewLength - nIndex)*sizeof(FX_WCHAR));
    736     m_pData->m_String[nIndex] = ch;
    737     m_pData->m_nDataLength = nNewLength;
    738     return nNewLength;
    739 }
    740 FX_STRSIZE CFX_WideString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount)
    741 {
    742     if (GetLength() < 1) {
    743         return 0;
    744     }
    745     if (nIndex < 0) {
    746         nIndex = 0;
    747     }
    748     FX_STRSIZE nOldLength = m_pData->m_nDataLength;
    749     if (nCount > 0 && nIndex < nOldLength) {
    750         CopyBeforeWrite();
    751         int nBytesToCopy = nOldLength - (nIndex + nCount) + 1;
    752         FXSYS_memmove32(m_pData->m_String + nIndex,
    753                         m_pData->m_String + nIndex + nCount, nBytesToCopy * sizeof(FX_WCHAR));
    754         m_pData->m_nDataLength = nOldLength - nCount;
    755     }
    756     return m_pData->m_nDataLength;
    757 }
    758 FX_STRSIZE CFX_WideString::Remove(FX_WCHAR chRemove)
    759 {
    760     if (m_pData == NULL) {
    761         return 0;
    762     }
    763     CopyBeforeWrite();
    764     if (GetLength() < 1) {
    765         return 0;
    766     }
    767     FX_LPWSTR pstrSource = m_pData->m_String;
    768     FX_LPWSTR pstrDest = m_pData->m_String;
    769     FX_LPWSTR pstrEnd = m_pData->m_String + m_pData->m_nDataLength;
    770     while (pstrSource < pstrEnd) {
    771         if (*pstrSource != chRemove) {
    772             *pstrDest = *pstrSource;
    773             pstrDest ++;
    774         }
    775         pstrSource ++;
    776     }
    777     *pstrDest = 0;
    778     FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest);
    779     m_pData->m_nDataLength -= nCount;
    780     return nCount;
    781 }
    782 #define FORCE_ANSI      0x10000
    783 #define FORCE_UNICODE   0x20000
    784 #define FORCE_INT64     0x40000
    785 void CFX_WideString::FormatV(FX_LPCWSTR lpszFormat, va_list argList)
    786 {
    787     va_list argListSave;
    788 #if defined(__ARMCC_VERSION) || (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || _FX_CPU_ == _FX_ARM64_)) || defined(__native_client__)
    789     va_copy(argListSave, argList);
    790 #else
    791     argListSave = argList;
    792 #endif
    793     int nMaxLen = 0;
    794     for (FX_LPCWSTR lpsz = lpszFormat; *lpsz != 0; lpsz ++) {
    795         if (*lpsz != '%' || *(lpsz = lpsz + 1) == '%') {
    796             nMaxLen += (FX_STRSIZE)FXSYS_wcslen(lpsz);
    797             continue;
    798         }
    799         int nItemLen = 0;
    800         int nWidth = 0;
    801         for (; *lpsz != 0; lpsz ++) {
    802             if (*lpsz == '#') {
    803                 nMaxLen += 2;
    804             } else if (*lpsz == '*') {
    805                 nWidth = va_arg(argList, int);
    806             } else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
    807                        *lpsz == ' ')
    808                 ;
    809             else {
    810                 break;
    811             }
    812         }
    813         if (nWidth == 0) {
    814             nWidth = FXSYS_wtoi(lpsz);
    815             for (; *lpsz != 0 && (*lpsz) <= '9' && (*lpsz) >= '0'; lpsz ++)
    816                 ;
    817         }
    818         if (nWidth < 0 || nWidth > 128 * 1024) {
    819             lpszFormat = (FX_LPCWSTR)L"Bad width";
    820             nMaxLen = 10;
    821             break;
    822         }
    823         int nPrecision = 0;
    824         if (*lpsz == '.') {
    825             lpsz ++;
    826             if (*lpsz == '*') {
    827                 nPrecision = va_arg(argList, int);
    828                 lpsz ++;
    829             } else {
    830                 nPrecision = FXSYS_wtoi(lpsz);
    831                 for (; *lpsz != 0 && (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz ++)
    832                     ;
    833             }
    834         }
    835         if (nPrecision < 0 || nPrecision > 128 * 1024) {
    836             lpszFormat = (FX_LPCWSTR)L"Bad precision";
    837             nMaxLen = 14;
    838             break;
    839         }
    840         int nModifier = 0;
    841         if (*lpsz == L'I' && *(lpsz + 1) == L'6' && *(lpsz + 2) == L'4') {
    842             lpsz += 3;
    843             nModifier = FORCE_INT64;
    844         } else {
    845             switch (*lpsz) {
    846                 case 'h':
    847                     nModifier = FORCE_ANSI;
    848                     lpsz ++;
    849                     break;
    850                 case 'l':
    851                     nModifier = FORCE_UNICODE;
    852                     lpsz ++;
    853                     break;
    854                 case 'F':
    855                 case 'N':
    856                 case 'L':
    857                     lpsz ++;
    858                     break;
    859             }
    860         }
    861         switch (*lpsz | nModifier) {
    862             case 'c':
    863             case 'C':
    864                 nItemLen = 2;
    865                 va_arg(argList, int);
    866                 break;
    867             case 'c'|FORCE_ANSI:
    868             case 'C'|FORCE_ANSI:
    869                 nItemLen = 2;
    870                 va_arg(argList, int);
    871                 break;
    872             case 'c'|FORCE_UNICODE:
    873             case 'C'|FORCE_UNICODE:
    874                 nItemLen = 2;
    875                 va_arg(argList, int);
    876                 break;
    877             case 's': {
    878                     FX_LPCWSTR pstrNextArg = va_arg(argList, FX_LPCWSTR);
    879                     if (pstrNextArg == NULL) {
    880                         nItemLen = 6;
    881                     } else {
    882                         nItemLen = (FX_STRSIZE)FXSYS_wcslen(pstrNextArg);
    883                         if (nItemLen < 1) {
    884                             nItemLen = 1;
    885                         }
    886                     }
    887                 }
    888                 break;
    889             case 'S': {
    890                     FX_LPCSTR pstrNextArg = va_arg(argList, FX_LPCSTR);
    891                     if (pstrNextArg == NULL) {
    892                         nItemLen = 6;
    893                     } else {
    894                         nItemLen = (FX_STRSIZE)FXSYS_strlen(pstrNextArg);
    895                         if (nItemLen < 1) {
    896                             nItemLen = 1;
    897                         }
    898                     }
    899                 }
    900                 break;
    901             case 's'|FORCE_ANSI:
    902             case 'S'|FORCE_ANSI: {
    903                     FX_LPCSTR pstrNextArg = va_arg(argList, FX_LPCSTR);
    904                     if (pstrNextArg == NULL) {
    905                         nItemLen = 6;
    906                     } else {
    907                         nItemLen = (FX_STRSIZE)FXSYS_strlen(pstrNextArg);
    908                         if (nItemLen < 1) {
    909                             nItemLen = 1;
    910                         }
    911                     }
    912                 }
    913                 break;
    914             case 's'|FORCE_UNICODE:
    915             case 'S'|FORCE_UNICODE: {
    916                     FX_LPWSTR pstrNextArg = va_arg(argList, FX_LPWSTR);
    917                     if (pstrNextArg == NULL) {
    918                         nItemLen = 6;
    919                     } else {
    920                         nItemLen = (FX_STRSIZE)FXSYS_wcslen(pstrNextArg);
    921                         if (nItemLen < 1) {
    922                             nItemLen = 1;
    923                         }
    924                     }
    925                 }
    926                 break;
    927         }
    928         if (nItemLen != 0) {
    929             if (nPrecision != 0 && nItemLen > nPrecision) {
    930                 nItemLen = nPrecision;
    931             }
    932             if (nItemLen < nWidth) {
    933                 nItemLen = nWidth;
    934             }
    935         } else {
    936             switch (*lpsz) {
    937                 case 'd':
    938                 case 'i':
    939                 case 'u':
    940                 case 'x':
    941                 case 'X':
    942                 case 'o':
    943                     if (nModifier & FORCE_INT64) {
    944                         va_arg(argList, FX_INT64);
    945                     } else {
    946                         va_arg(argList, int);
    947                     }
    948                     nItemLen = 32;
    949                     if (nItemLen < nWidth + nPrecision) {
    950                         nItemLen = nWidth + nPrecision;
    951                     }
    952                     break;
    953                 case 'a':
    954                 case 'A':
    955                 case 'e':
    956                 case 'E':
    957                 case 'g':
    958                 case 'G':
    959                     va_arg(argList, double);
    960                     nItemLen = 128;
    961                     if (nItemLen < nWidth + nPrecision) {
    962                         nItemLen = nWidth + nPrecision;
    963                     }
    964                     break;
    965                 case 'f':
    966                     if (nWidth + nPrecision > 100) {
    967                         nItemLen = nPrecision + nWidth + 128;
    968                     } else {
    969                         double f;
    970                         char pszTemp[256];
    971                         f = va_arg(argList, double);
    972                         FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, nPrecision + 6, f );
    973                         nItemLen = (FX_STRSIZE)FXSYS_strlen(pszTemp);
    974                     }
    975                     break;
    976                 case 'p':
    977                     va_arg(argList, void*);
    978                     nItemLen = 32;
    979                     if (nItemLen < nWidth + nPrecision) {
    980                         nItemLen = nWidth + nPrecision;
    981                     }
    982                     break;
    983                 case 'n':
    984                     va_arg(argList, int*);
    985                     break;
    986             }
    987         }
    988         nMaxLen += nItemLen;
    989     }
    990     GetBuffer(nMaxLen);
    991     if (m_pData) {
    992         FXSYS_vswprintf((wchar_t*)m_pData->m_String, nMaxLen + 1, (const wchar_t*)lpszFormat, argListSave);
    993         ReleaseBuffer();
    994     }
    995     va_end(argListSave);
    996 }
    997 void CFX_WideString::Format(FX_LPCWSTR lpszFormat, ...)
    998 {
    999     va_list argList;
   1000     va_start(argList, lpszFormat);
   1001     FormatV(lpszFormat, argList);
   1002     va_end(argList);
   1003 }
   1004 FX_FLOAT FX_wtof(FX_LPCWSTR str, int len)
   1005 {
   1006     if (len == 0) {
   1007         return 0.0;
   1008     }
   1009     int cc = 0;
   1010     FX_BOOL bNegative = FALSE;
   1011     if (str[0] == '+') {
   1012         cc++;
   1013     } else if (str[0] == '-') {
   1014         bNegative = TRUE;
   1015         cc++;
   1016     }
   1017     int integer = 0;
   1018     while (cc < len) {
   1019         if (str[cc] == '.') {
   1020             break;
   1021         }
   1022         integer = integer * 10 + str[cc] - '0';
   1023         cc ++;
   1024     }
   1025     FX_FLOAT fraction = 0;
   1026     if (str[cc] == '.') {
   1027         cc ++;
   1028         FX_FLOAT scale = 0.1f;
   1029         while (cc < len) {
   1030             fraction += scale * (str[cc] - '0');
   1031             scale *= 0.1f;
   1032             cc ++;
   1033         }
   1034     }
   1035     fraction += (FX_FLOAT)integer;
   1036     return bNegative ? -fraction : fraction;
   1037 }
   1038 int CFX_WideString::GetInteger() const
   1039 {
   1040     if (m_pData == NULL) {
   1041         return 0;
   1042     }
   1043     return FXSYS_wtoi(m_pData->m_String);
   1044 }
   1045 FX_FLOAT CFX_WideString::GetFloat() const
   1046 {
   1047     if (m_pData == NULL) {
   1048         return 0.0;
   1049     }
   1050     return FX_wtof(m_pData->m_String, m_pData->m_nDataLength);
   1051 }
   1052 void CFX_WideStringL::Empty(IFX_Allocator* pAllocator)
   1053 {
   1054     if (m_Ptr) {
   1055         FX_Allocator_Free(pAllocator, (FX_LPVOID)m_Ptr);
   1056     }
   1057     m_Ptr = NULL, m_Length = 0;
   1058 }
   1059 void CFX_WideStringL::Set(FX_WSTR src, IFX_Allocator* pAllocator)
   1060 {
   1061     Empty(pAllocator);
   1062     if (src.GetPtr() != NULL && src.GetLength() > 0) {
   1063         FX_LPWSTR str = FX_Allocator_Alloc(pAllocator, FX_WCHAR, src.GetLength() + 1);
   1064         if (!str) {
   1065             return;
   1066         }
   1067         FXSYS_memcpy32(str, src.GetPtr(), src.GetLength()*sizeof(FX_WCHAR));
   1068         str[src.GetLength()] = '\0';
   1069         *(FX_LPWSTR*)(&m_Ptr) = str;
   1070         m_Length = src.GetLength();
   1071     }
   1072 }
   1073 int CFX_WideStringL::GetInteger() const
   1074 {
   1075     if (!m_Ptr) {
   1076         return 0;
   1077     }
   1078     return FXSYS_wtoi(m_Ptr);
   1079 }
   1080 FX_FLOAT CFX_WideStringL::GetFloat() const
   1081 {
   1082     if (!m_Ptr) {
   1083         return 0.0f;
   1084     }
   1085     return FX_wtof(m_Ptr, m_Length);
   1086 }
   1087 void CFX_WideStringL::TrimRight(FX_LPCWSTR lpszTargets)
   1088 {
   1089     if (!lpszTargets || *lpszTargets == 0 || !m_Ptr || m_Length < 1) {
   1090         return;
   1091     }
   1092     FX_STRSIZE pos = m_Length;
   1093     while (pos) {
   1094         if (FXSYS_wcschr(lpszTargets, m_Ptr[pos - 1]) == NULL) {
   1095             break;
   1096         }
   1097         pos --;
   1098     }
   1099     if (pos < m_Length) {
   1100         (*(FX_LPWSTR*)(&m_Ptr))[pos] = 0;
   1101         m_Length = pos;
   1102     }
   1103 }
   1104 static CFX_ByteString _DefMap_GetByteString(CFX_CharMap* pCharMap, const CFX_WideString& widestr)
   1105 {
   1106     int src_len = widestr.GetLength();
   1107     int codepage = pCharMap->m_GetCodePage ? pCharMap->m_GetCodePage() : 0;
   1108     int dest_len = FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, NULL, 0, NULL, NULL);
   1109     if (dest_len == 0) {
   1110         return CFX_ByteString();
   1111     }
   1112     CFX_ByteString bytestr;
   1113     FX_LPSTR dest_buf = bytestr.GetBuffer(dest_len);
   1114     FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, dest_buf, dest_len, NULL, NULL);
   1115     bytestr.ReleaseBuffer(dest_len);
   1116     return bytestr;
   1117 }
   1118 static CFX_WideString _DefMap_GetWideString(CFX_CharMap* pCharMap, const CFX_ByteString& bytestr)
   1119 {
   1120     int src_len = bytestr.GetLength();
   1121     int codepage = pCharMap->m_GetCodePage ? pCharMap->m_GetCodePage() : 0;
   1122     int dest_len = FXSYS_MultiByteToWideChar(codepage, 0, bytestr, src_len, NULL, 0);
   1123     if (dest_len == 0) {
   1124         return CFX_WideString();
   1125     }
   1126     CFX_WideString widestr;
   1127     FX_LPWSTR dest_buf = widestr.GetBuffer(dest_len);
   1128     FXSYS_MultiByteToWideChar(codepage, 0, bytestr, src_len, dest_buf, dest_len);
   1129     widestr.ReleaseBuffer(dest_len);
   1130     return widestr;
   1131 }
   1132 static int _DefMap_GetGBKCodePage()
   1133 {
   1134     return 936;
   1135 }
   1136 static int _DefMap_GetUHCCodePage()
   1137 {
   1138     return 949;
   1139 }
   1140 static int _DefMap_GetJISCodePage()
   1141 {
   1142     return 932;
   1143 }
   1144 static int _DefMap_GetBig5CodePage()
   1145 {
   1146     return 950;
   1147 }
   1148 static const CFX_CharMap g_DefaultMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, NULL};
   1149 static const CFX_CharMap g_DefaultGBKMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetGBKCodePage};
   1150 static const CFX_CharMap g_DefaultJISMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetJISCodePage};
   1151 static const CFX_CharMap g_DefaultUHCMapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetUHCCodePage};
   1152 static const CFX_CharMap g_DefaultBig5Mapper = {&_DefMap_GetWideString, &_DefMap_GetByteString, &_DefMap_GetBig5CodePage};
   1153 CFX_CharMap* CFX_CharMap::GetDefaultMapper(FX_INT32 codepage)
   1154 {
   1155     switch (codepage) {
   1156         case 0:
   1157             return (CFX_CharMap*)&g_DefaultMapper;
   1158         case 932:
   1159             return (CFX_CharMap*)&g_DefaultJISMapper;
   1160         case 936:
   1161             return (CFX_CharMap*)&g_DefaultGBKMapper;
   1162         case 949:
   1163             return (CFX_CharMap*)&g_DefaultUHCMapper;
   1164         case 950:
   1165             return (CFX_CharMap*)&g_DefaultBig5Mapper;
   1166     }
   1167     return NULL;
   1168 }
   1169