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