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 "core/fxcrt/bytestring.h"
      8 
      9 #include <stddef.h>
     10 
     11 #include <algorithm>
     12 #include <cctype>
     13 #include <string>
     14 
     15 #include "core/fxcrt/cfx_utf8decoder.h"
     16 #include "core/fxcrt/fx_codepage.h"
     17 #include "core/fxcrt/fx_extension.h"
     18 #include "core/fxcrt/fx_safe_types.h"
     19 #include "core/fxcrt/string_pool_template.h"
     20 #include "third_party/base/numerics/safe_math.h"
     21 #include "third_party/base/stl_util.h"
     22 
     23 template class fxcrt::StringDataTemplate<char>;
     24 template class fxcrt::StringViewTemplate<char>;
     25 template class fxcrt::StringPoolTemplate<ByteString>;
     26 template struct std::hash<ByteString>;
     27 
     28 namespace {
     29 
     30 constexpr char kTrimChars[] = "\x09\x0a\x0b\x0c\x0d\x20";
     31 
     32 const char* FX_strstr(const char* haystack,
     33                       int haystack_len,
     34                       const char* needle,
     35                       int needle_len) {
     36   if (needle_len > haystack_len || needle_len == 0) {
     37     return nullptr;
     38   }
     39   const char* end_ptr = haystack + haystack_len - needle_len;
     40   while (haystack <= end_ptr) {
     41     int i = 0;
     42     while (1) {
     43       if (haystack[i] != needle[i]) {
     44         break;
     45       }
     46       i++;
     47       if (i == needle_len) {
     48         return haystack;
     49       }
     50     }
     51     haystack++;
     52   }
     53   return nullptr;
     54 }
     55 
     56 #ifndef NDEBUG
     57 bool IsValidCodePage(uint16_t codepage) {
     58   switch (codepage) {
     59     case FX_CODEPAGE_DefANSI:
     60     case FX_CODEPAGE_ShiftJIS:
     61     case FX_CODEPAGE_ChineseSimplified:
     62     case FX_CODEPAGE_Hangul:
     63     case FX_CODEPAGE_ChineseTraditional:
     64       return true;
     65     default:
     66       return false;
     67   }
     68 }
     69 #endif
     70 
     71 ByteString GetByteString(uint16_t codepage, const WideStringView& wstr) {
     72 #ifndef NDEBUG
     73   ASSERT(IsValidCodePage(codepage));
     74 #endif
     75 
     76   int src_len = wstr.GetLength();
     77   int dest_len =
     78       FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len,
     79                                 nullptr, 0, nullptr, nullptr);
     80   if (!dest_len)
     81     return ByteString();
     82 
     83   ByteString bstr;
     84   char* dest_buf = bstr.GetBuffer(dest_len);
     85   FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len,
     86                             dest_buf, dest_len, nullptr, nullptr);
     87   bstr.ReleaseBuffer(dest_len);
     88   return bstr;
     89 }
     90 
     91 }  // namespace
     92 
     93 namespace fxcrt {
     94 
     95 static_assert(sizeof(ByteString) <= sizeof(char*),
     96               "Strings must not require more space than pointers");
     97 
     98 #define FORCE_ANSI 0x10000
     99 #define FORCE_UNICODE 0x20000
    100 #define FORCE_INT64 0x40000
    101 
    102 // static
    103 ByteString ByteString::FormatInteger(int i) {
    104   char buf[32];
    105   FXSYS_snprintf(buf, sizeof(buf), "%d", i);
    106   return ByteString(buf);
    107 }
    108 
    109 // static
    110 ByteString ByteString::FormatFloat(float d) {
    111   char buf[32];
    112   return ByteString(buf, FX_ftoa(d, buf));
    113 }
    114 
    115 // static
    116 ByteString ByteString::FormatV(const char* pFormat, va_list argList) {
    117   va_list argListCopy;
    118   va_copy(argListCopy, argList);
    119   int nMaxLen = vsnprintf(nullptr, 0, pFormat, argListCopy);
    120   va_end(argListCopy);
    121 
    122   if (nMaxLen <= 0)
    123     return "";
    124 
    125   ByteString ret;
    126   char* buf = ret.GetBuffer(nMaxLen);
    127   if (buf) {
    128     // In the following two calls, there's always space in the buffer for
    129     // a terminating NUL that's not included in nMaxLen.
    130     memset(buf, 0, nMaxLen + 1);
    131     va_copy(argListCopy, argList);
    132     vsnprintf(buf, nMaxLen + 1, pFormat, argListCopy);
    133     va_end(argListCopy);
    134     ret.ReleaseBuffer(ret.GetStringLength());
    135   }
    136   return ret;
    137 }
    138 
    139 // static
    140 ByteString ByteString::Format(const char* pFormat, ...) {
    141   va_list argList;
    142   va_start(argList, pFormat);
    143   ByteString ret = FormatV(pFormat, argList);
    144   va_end(argList);
    145 
    146   return ret;
    147 }
    148 
    149 ByteString::ByteString(const char* pStr, size_t nLen) {
    150   if (nLen)
    151     m_pData.Reset(StringData::Create(pStr, nLen));
    152 }
    153 
    154 ByteString::ByteString(const uint8_t* pStr, size_t nLen) {
    155   if (nLen)
    156     m_pData.Reset(
    157         StringData::Create(reinterpret_cast<const char*>(pStr), nLen));
    158 }
    159 
    160 ByteString::ByteString() {}
    161 
    162 ByteString::ByteString(const ByteString& other) : m_pData(other.m_pData) {}
    163 
    164 ByteString::ByteString(ByteString&& other) noexcept {
    165   m_pData.Swap(other.m_pData);
    166 }
    167 
    168 ByteString::ByteString(char ch) {
    169   m_pData.Reset(StringData::Create(1));
    170   m_pData->m_String[0] = ch;
    171 }
    172 
    173 ByteString::ByteString(const char* ptr)
    174     : ByteString(ptr, ptr ? strlen(ptr) : 0) {}
    175 
    176 ByteString::ByteString(const ByteStringView& stringSrc) {
    177   if (!stringSrc.IsEmpty())
    178     m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(),
    179                                      stringSrc.GetLength()));
    180 }
    181 
    182 ByteString::ByteString(const ByteStringView& str1, const ByteStringView& str2) {
    183   FX_SAFE_SIZE_T nSafeLen = str1.GetLength();
    184   nSafeLen += str2.GetLength();
    185 
    186   size_t nNewLen = nSafeLen.ValueOrDie();
    187   if (nNewLen == 0)
    188     return;
    189 
    190   m_pData.Reset(StringData::Create(nNewLen));
    191   m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength());
    192   m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(),
    193                           str2.GetLength());
    194 }
    195 
    196 ByteString::ByteString(const std::initializer_list<ByteStringView>& list) {
    197   FX_SAFE_SIZE_T nSafeLen = 0;
    198   for (const auto& item : list)
    199     nSafeLen += item.GetLength();
    200 
    201   size_t nNewLen = nSafeLen.ValueOrDie();
    202   if (nNewLen == 0)
    203     return;
    204 
    205   m_pData.Reset(StringData::Create(nNewLen));
    206 
    207   size_t nOffset = 0;
    208   for (const auto& item : list) {
    209     m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(),
    210                             item.GetLength());
    211     nOffset += item.GetLength();
    212   }
    213 }
    214 
    215 ByteString::ByteString(const std::ostringstream& outStream) {
    216   std::string str = outStream.str();
    217   if (str.length() > 0)
    218     m_pData.Reset(StringData::Create(str.c_str(), str.length()));
    219 }
    220 
    221 ByteString::~ByteString() {}
    222 
    223 const ByteString& ByteString::operator=(const char* pStr) {
    224   if (!pStr || !pStr[0])
    225     clear();
    226   else
    227     AssignCopy(pStr, strlen(pStr));
    228 
    229   return *this;
    230 }
    231 
    232 const ByteString& ByteString::operator=(const ByteStringView& stringSrc) {
    233   if (stringSrc.IsEmpty())
    234     clear();
    235   else
    236     AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength());
    237 
    238   return *this;
    239 }
    240 
    241 const ByteString& ByteString::operator=(const ByteString& stringSrc) {
    242   if (m_pData != stringSrc.m_pData)
    243     m_pData = stringSrc.m_pData;
    244 
    245   return *this;
    246 }
    247 
    248 const ByteString& ByteString::operator+=(const char* pStr) {
    249   if (pStr)
    250     Concat(pStr, strlen(pStr));
    251 
    252   return *this;
    253 }
    254 
    255 const ByteString& ByteString::operator+=(char ch) {
    256   Concat(&ch, 1);
    257   return *this;
    258 }
    259 
    260 const ByteString& ByteString::operator+=(const ByteString& str) {
    261   if (str.m_pData)
    262     Concat(str.m_pData->m_String, str.m_pData->m_nDataLength);
    263 
    264   return *this;
    265 }
    266 
    267 const ByteString& ByteString::operator+=(const ByteStringView& str) {
    268   if (!str.IsEmpty())
    269     Concat(str.unterminated_c_str(), str.GetLength());
    270 
    271   return *this;
    272 }
    273 
    274 bool ByteString::operator==(const char* ptr) const {
    275   if (!m_pData)
    276     return !ptr || !ptr[0];
    277 
    278   if (!ptr)
    279     return m_pData->m_nDataLength == 0;
    280 
    281   return strlen(ptr) == m_pData->m_nDataLength &&
    282          memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
    283 }
    284 
    285 bool ByteString::operator==(const ByteStringView& str) const {
    286   if (!m_pData)
    287     return str.IsEmpty();
    288 
    289   return m_pData->m_nDataLength == str.GetLength() &&
    290          memcmp(m_pData->m_String, str.unterminated_c_str(), str.GetLength()) ==
    291              0;
    292 }
    293 
    294 bool ByteString::operator==(const ByteString& other) const {
    295   if (m_pData == other.m_pData)
    296     return true;
    297 
    298   if (IsEmpty())
    299     return other.IsEmpty();
    300 
    301   if (other.IsEmpty())
    302     return false;
    303 
    304   return other.m_pData->m_nDataLength == m_pData->m_nDataLength &&
    305          memcmp(other.m_pData->m_String, m_pData->m_String,
    306                 m_pData->m_nDataLength) == 0;
    307 }
    308 
    309 bool ByteString::operator<(const char* ptr) const {
    310   if (!m_pData && !ptr)
    311     return false;
    312   if (c_str() == ptr)
    313     return false;
    314 
    315   size_t len = GetLength();
    316   size_t other_len = ptr ? strlen(ptr) : 0;
    317   int result = memcmp(c_str(), ptr, std::min(len, other_len));
    318   return result < 0 || (result == 0 && len < other_len);
    319 }
    320 
    321 bool ByteString::operator<(const ByteStringView& str) const {
    322   return Compare(str) < 0;
    323 }
    324 
    325 bool ByteString::operator<(const ByteString& other) const {
    326   if (m_pData == other.m_pData)
    327     return false;
    328 
    329   size_t len = GetLength();
    330   size_t other_len = other.GetLength();
    331   int result = memcmp(c_str(), other.c_str(), std::min(len, other_len));
    332   return result < 0 || (result == 0 && len < other_len);
    333 }
    334 
    335 bool ByteString::EqualNoCase(const ByteStringView& str) const {
    336   if (!m_pData)
    337     return str.IsEmpty();
    338 
    339   size_t len = str.GetLength();
    340   if (m_pData->m_nDataLength != len)
    341     return false;
    342 
    343   const uint8_t* pThis = (const uint8_t*)m_pData->m_String;
    344   const uint8_t* pThat = str.raw_str();
    345   for (size_t i = 0; i < len; i++) {
    346     if ((*pThis) != (*pThat)) {
    347       uint8_t bThis = FXSYS_tolower(*pThis);
    348       uint8_t bThat = FXSYS_tolower(*pThat);
    349       if (bThis != bThat)
    350         return false;
    351     }
    352     pThis++;
    353     pThat++;
    354   }
    355   return true;
    356 }
    357 
    358 void ByteString::AssignCopy(const char* pSrcData, size_t nSrcLen) {
    359   AllocBeforeWrite(nSrcLen);
    360   m_pData->CopyContents(pSrcData, nSrcLen);
    361   m_pData->m_nDataLength = nSrcLen;
    362 }
    363 
    364 void ByteString::ReallocBeforeWrite(size_t nNewLength) {
    365   if (m_pData && m_pData->CanOperateInPlace(nNewLength))
    366     return;
    367 
    368   if (nNewLength == 0) {
    369     clear();
    370     return;
    371   }
    372 
    373   RetainPtr<StringData> pNewData(StringData::Create(nNewLength));
    374   if (m_pData) {
    375     size_t nCopyLength = std::min(m_pData->m_nDataLength, nNewLength);
    376     pNewData->CopyContents(m_pData->m_String, nCopyLength);
    377     pNewData->m_nDataLength = nCopyLength;
    378   } else {
    379     pNewData->m_nDataLength = 0;
    380   }
    381   pNewData->m_String[pNewData->m_nDataLength] = 0;
    382   m_pData.Swap(pNewData);
    383 }
    384 
    385 void ByteString::AllocBeforeWrite(size_t nNewLength) {
    386   if (m_pData && m_pData->CanOperateInPlace(nNewLength))
    387     return;
    388 
    389   if (nNewLength == 0) {
    390     clear();
    391     return;
    392   }
    393 
    394   m_pData.Reset(StringData::Create(nNewLength));
    395 }
    396 
    397 void ByteString::ReleaseBuffer(size_t nNewLength) {
    398   if (!m_pData)
    399     return;
    400 
    401   nNewLength = std::min(nNewLength, m_pData->m_nAllocLength);
    402   if (nNewLength == 0) {
    403     clear();
    404     return;
    405   }
    406 
    407   ASSERT(m_pData->m_nRefs == 1);
    408   m_pData->m_nDataLength = nNewLength;
    409   m_pData->m_String[nNewLength] = 0;
    410   if (m_pData->m_nAllocLength - nNewLength >= 32) {
    411     // Over arbitrary threshold, so pay the price to relocate.  Force copy to
    412     // always occur by holding a second reference to the string.
    413     ByteString preserve(*this);
    414     ReallocBeforeWrite(nNewLength);
    415   }
    416 }
    417 
    418 void ByteString::Reserve(size_t len) {
    419   GetBuffer(len);
    420 }
    421 
    422 char* ByteString::GetBuffer(size_t nMinBufLength) {
    423   if (!m_pData) {
    424     if (nMinBufLength == 0)
    425       return nullptr;
    426 
    427     m_pData.Reset(StringData::Create(nMinBufLength));
    428     m_pData->m_nDataLength = 0;
    429     m_pData->m_String[0] = 0;
    430     return m_pData->m_String;
    431   }
    432 
    433   if (m_pData->CanOperateInPlace(nMinBufLength))
    434     return m_pData->m_String;
    435 
    436   nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength);
    437   if (nMinBufLength == 0)
    438     return nullptr;
    439 
    440   RetainPtr<StringData> pNewData(StringData::Create(nMinBufLength));
    441   pNewData->CopyContents(*m_pData);
    442   pNewData->m_nDataLength = m_pData->m_nDataLength;
    443   m_pData.Swap(pNewData);
    444   return m_pData->m_String;
    445 }
    446 
    447 size_t ByteString::Delete(size_t index, size_t count) {
    448   if (!m_pData)
    449     return 0;
    450 
    451   size_t old_length = m_pData->m_nDataLength;
    452   if (count == 0 ||
    453       index != pdfium::clamp(index, static_cast<size_t>(0), old_length))
    454     return old_length;
    455 
    456   size_t removal_length = index + count;
    457   if (removal_length > old_length)
    458     return old_length;
    459 
    460   ReallocBeforeWrite(old_length);
    461   size_t chars_to_copy = old_length - removal_length + 1;
    462   memmove(m_pData->m_String + index, m_pData->m_String + removal_length,
    463           chars_to_copy);
    464   m_pData->m_nDataLength = old_length - count;
    465   return m_pData->m_nDataLength;
    466 }
    467 
    468 void ByteString::Concat(const char* pSrcData, size_t nSrcLen) {
    469   if (!pSrcData || nSrcLen == 0)
    470     return;
    471 
    472   if (!m_pData) {
    473     m_pData.Reset(StringData::Create(pSrcData, nSrcLen));
    474     return;
    475   }
    476 
    477   if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) {
    478     m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen);
    479     m_pData->m_nDataLength += nSrcLen;
    480     return;
    481   }
    482 
    483   RetainPtr<StringData> pNewData(
    484       StringData::Create(m_pData->m_nDataLength + nSrcLen));
    485   pNewData->CopyContents(*m_pData);
    486   pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen);
    487   m_pData.Swap(pNewData);
    488 }
    489 
    490 ByteString ByteString::Mid(size_t first, size_t count) const {
    491   if (!m_pData)
    492     return ByteString();
    493 
    494   if (!IsValidIndex(first))
    495     return ByteString();
    496 
    497   if (count == 0 || !IsValidLength(count))
    498     return ByteString();
    499 
    500   if (!IsValidIndex(first + count - 1))
    501     return ByteString();
    502 
    503   if (first == 0 && count == m_pData->m_nDataLength)
    504     return *this;
    505 
    506   ByteString dest;
    507   AllocCopy(dest, count, first);
    508   return dest;
    509 }
    510 
    511 ByteString ByteString::Left(size_t count) const {
    512   if (count == 0 || !IsValidLength(count))
    513     return ByteString();
    514   return Mid(0, count);
    515 }
    516 
    517 ByteString ByteString::Right(size_t count) const {
    518   if (count == 0 || !IsValidLength(count))
    519     return ByteString();
    520   return Mid(GetLength() - count, count);
    521 }
    522 
    523 void ByteString::AllocCopy(ByteString& dest,
    524                            size_t nCopyLen,
    525                            size_t nCopyIndex) const {
    526   if (nCopyLen == 0)
    527     return;
    528 
    529   RetainPtr<StringData> pNewData(
    530       StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen));
    531   dest.m_pData.Swap(pNewData);
    532 }
    533 
    534 void ByteString::SetAt(size_t index, char c) {
    535   ASSERT(IsValidIndex(index));
    536   ReallocBeforeWrite(m_pData->m_nDataLength);
    537   m_pData->m_String[index] = c;
    538 }
    539 
    540 size_t ByteString::Insert(size_t location, char ch) {
    541   const size_t cur_length = m_pData ? m_pData->m_nDataLength : 0;
    542   if (!IsValidLength(location))
    543     return cur_length;
    544 
    545   const size_t new_length = cur_length + 1;
    546   ReallocBeforeWrite(new_length);
    547   memmove(m_pData->m_String + location + 1, m_pData->m_String + location,
    548           new_length - location);
    549   m_pData->m_String[location] = ch;
    550   m_pData->m_nDataLength = new_length;
    551   return new_length;
    552 }
    553 
    554 Optional<size_t> ByteString::Find(char ch, size_t start) const {
    555   if (!m_pData)
    556     return Optional<size_t>();
    557 
    558   if (!IsValidIndex(start))
    559     return Optional<size_t>();
    560 
    561   const char* pStr = static_cast<const char*>(
    562       memchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start));
    563   return pStr ? Optional<size_t>(static_cast<size_t>(pStr - m_pData->m_String))
    564               : Optional<size_t>();
    565 }
    566 
    567 Optional<size_t> ByteString::Find(const ByteStringView& subStr,
    568                                   size_t start) const {
    569   if (!m_pData)
    570     return Optional<size_t>();
    571 
    572   if (!IsValidIndex(start))
    573     return Optional<size_t>();
    574 
    575   const char* pStr =
    576       FX_strstr(m_pData->m_String + start, m_pData->m_nDataLength - start,
    577                 subStr.unterminated_c_str(), subStr.GetLength());
    578   return pStr ? Optional<size_t>(static_cast<size_t>(pStr - m_pData->m_String))
    579               : Optional<size_t>();
    580 }
    581 
    582 Optional<size_t> ByteString::ReverseFind(char ch) const {
    583   if (!m_pData)
    584     return Optional<size_t>();
    585 
    586   size_t nLength = m_pData->m_nDataLength;
    587   while (nLength--) {
    588     if (m_pData->m_String[nLength] == ch)
    589       return Optional<size_t>(nLength);
    590   }
    591   return Optional<size_t>();
    592 }
    593 
    594 void ByteString::MakeLower() {
    595   if (!m_pData)
    596     return;
    597 
    598   ReallocBeforeWrite(m_pData->m_nDataLength);
    599   FXSYS_strlwr(m_pData->m_String);
    600 }
    601 
    602 void ByteString::MakeUpper() {
    603   if (!m_pData)
    604     return;
    605 
    606   ReallocBeforeWrite(m_pData->m_nDataLength);
    607   FXSYS_strupr(m_pData->m_String);
    608 }
    609 
    610 size_t ByteString::Remove(char chRemove) {
    611   if (!m_pData || m_pData->m_nDataLength < 1)
    612     return 0;
    613 
    614   char* pstrSource = m_pData->m_String;
    615   char* pstrEnd = m_pData->m_String + m_pData->m_nDataLength;
    616   while (pstrSource < pstrEnd) {
    617     if (*pstrSource == chRemove)
    618       break;
    619     pstrSource++;
    620   }
    621   if (pstrSource == pstrEnd)
    622     return 0;
    623 
    624   ptrdiff_t copied = pstrSource - m_pData->m_String;
    625   ReallocBeforeWrite(m_pData->m_nDataLength);
    626   pstrSource = m_pData->m_String + copied;
    627   pstrEnd = m_pData->m_String + m_pData->m_nDataLength;
    628 
    629   char* pstrDest = pstrSource;
    630   while (pstrSource < pstrEnd) {
    631     if (*pstrSource != chRemove) {
    632       *pstrDest = *pstrSource;
    633       pstrDest++;
    634     }
    635     pstrSource++;
    636   }
    637 
    638   *pstrDest = 0;
    639   size_t nCount = static_cast<size_t>(pstrSource - pstrDest);
    640   m_pData->m_nDataLength -= nCount;
    641   return nCount;
    642 }
    643 
    644 size_t ByteString::Replace(const ByteStringView& pOld,
    645                            const ByteStringView& pNew) {
    646   if (!m_pData || pOld.IsEmpty())
    647     return 0;
    648 
    649   size_t nSourceLen = pOld.GetLength();
    650   size_t nReplacementLen = pNew.GetLength();
    651   size_t nCount = 0;
    652   const char* pStart = m_pData->m_String;
    653   char* pEnd = m_pData->m_String + m_pData->m_nDataLength;
    654   while (1) {
    655     const char* pTarget = FX_strstr(pStart, static_cast<int>(pEnd - pStart),
    656                                     pOld.unterminated_c_str(), nSourceLen);
    657     if (!pTarget)
    658       break;
    659 
    660     nCount++;
    661     pStart = pTarget + nSourceLen;
    662   }
    663   if (nCount == 0)
    664     return 0;
    665 
    666   size_t nNewLength =
    667       m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount;
    668 
    669   if (nNewLength == 0) {
    670     clear();
    671     return nCount;
    672   }
    673 
    674   RetainPtr<StringData> pNewData(StringData::Create(nNewLength));
    675   pStart = m_pData->m_String;
    676   char* pDest = pNewData->m_String;
    677   for (size_t i = 0; i < nCount; i++) {
    678     const char* pTarget = FX_strstr(pStart, static_cast<int>(pEnd - pStart),
    679                                     pOld.unterminated_c_str(), nSourceLen);
    680     memcpy(pDest, pStart, pTarget - pStart);
    681     pDest += pTarget - pStart;
    682     memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength());
    683     pDest += pNew.GetLength();
    684     pStart = pTarget + nSourceLen;
    685   }
    686   memcpy(pDest, pStart, pEnd - pStart);
    687   m_pData.Swap(pNewData);
    688   return nCount;
    689 }
    690 
    691 WideString ByteString::UTF8Decode() const {
    692   CFX_UTF8Decoder decoder;
    693   for (size_t i = 0; i < GetLength(); i++) {
    694     decoder.Input(static_cast<uint8_t>(m_pData->m_String[i]));
    695   }
    696   return WideString(decoder.GetResult());
    697 }
    698 
    699 // static
    700 ByteString ByteString::FromUnicode(const WideString& str) {
    701   return GetByteString(0, str.AsStringView());
    702 }
    703 
    704 int ByteString::Compare(const ByteStringView& str) const {
    705   if (!m_pData)
    706     return str.IsEmpty() ? 0 : -1;
    707 
    708   size_t this_len = m_pData->m_nDataLength;
    709   size_t that_len = str.GetLength();
    710   size_t min_len = std::min(this_len, that_len);
    711   int result = memcmp(m_pData->m_String, str.unterminated_c_str(), min_len);
    712   if (result != 0)
    713     return result;
    714   if (this_len == that_len)
    715     return 0;
    716   return this_len < that_len ? -1 : 1;
    717 }
    718 
    719 void ByteString::Trim() {
    720   TrimRight(kTrimChars);
    721   TrimLeft(kTrimChars);
    722 }
    723 
    724 void ByteString::Trim(char target) {
    725   ByteStringView targets(target);
    726   TrimRight(targets);
    727   TrimLeft(targets);
    728 }
    729 
    730 void ByteString::Trim(const ByteStringView& targets) {
    731   TrimRight(targets);
    732   TrimLeft(targets);
    733 }
    734 
    735 void ByteString::TrimLeft() {
    736   TrimLeft(kTrimChars);
    737 }
    738 
    739 void ByteString::TrimLeft(char target) {
    740   TrimLeft(ByteStringView(target));
    741 }
    742 
    743 void ByteString::TrimLeft(const ByteStringView& targets) {
    744   if (!m_pData || targets.IsEmpty())
    745     return;
    746 
    747   size_t len = GetLength();
    748   if (len == 0)
    749     return;
    750 
    751   size_t pos = 0;
    752   while (pos < len) {
    753     size_t i = 0;
    754     while (i < targets.GetLength() && targets[i] != m_pData->m_String[pos])
    755       i++;
    756     if (i == targets.GetLength())
    757       break;
    758     pos++;
    759   }
    760   if (pos) {
    761     ReallocBeforeWrite(len);
    762     size_t nDataLength = len - pos;
    763     memmove(m_pData->m_String, m_pData->m_String + pos,
    764             (nDataLength + 1) * sizeof(char));
    765     m_pData->m_nDataLength = nDataLength;
    766   }
    767 }
    768 
    769 void ByteString::TrimRight() {
    770   TrimRight(kTrimChars);
    771 }
    772 
    773 void ByteString::TrimRight(char target) {
    774   TrimRight(ByteStringView(target));
    775 }
    776 
    777 void ByteString::TrimRight(const ByteStringView& targets) {
    778   if (!m_pData || targets.IsEmpty())
    779     return;
    780 
    781   size_t pos = GetLength();
    782   if (pos == 0)
    783     return;
    784 
    785   while (pos) {
    786     size_t i = 0;
    787     while (i < targets.GetLength() && targets[i] != m_pData->m_String[pos - 1])
    788       i++;
    789     if (i == targets.GetLength())
    790       break;
    791     pos--;
    792   }
    793   if (pos < m_pData->m_nDataLength) {
    794     ReallocBeforeWrite(m_pData->m_nDataLength);
    795     m_pData->m_String[pos] = 0;
    796     m_pData->m_nDataLength = pos;
    797   }
    798 }
    799 
    800 std::ostream& operator<<(std::ostream& os, const ByteString& str) {
    801   return os.write(str.c_str(), str.GetLength());
    802 }
    803 
    804 std::ostream& operator<<(std::ostream& os, const ByteStringView& str) {
    805   return os.write(str.unterminated_c_str(), str.GetLength());
    806 }
    807 
    808 }  // namespace fxcrt
    809