• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FX_strstr(const char * haystack,int haystack_len,const char * needle,int needle_len)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
IsValidCodePage(uint16_t codepage)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 
GetByteString(uint16_t codepage,const WideStringView & wstr)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
FormatInteger(int i)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
FormatFloat(float d)110 ByteString ByteString::FormatFloat(float d) {
111   char buf[32];
112   return ByteString(buf, FX_ftoa(d, buf));
113 }
114 
115 // static
FormatV(const char * pFormat,va_list argList)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
Format(const char * pFormat,...)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 
ByteString(const char * pStr,size_t nLen)149 ByteString::ByteString(const char* pStr, size_t nLen) {
150   if (nLen)
151     m_pData.Reset(StringData::Create(pStr, nLen));
152 }
153 
ByteString(const uint8_t * pStr,size_t nLen)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 
ByteString()160 ByteString::ByteString() {}
161 
ByteString(const ByteString & other)162 ByteString::ByteString(const ByteString& other) : m_pData(other.m_pData) {}
163 
ByteString(ByteString && other)164 ByteString::ByteString(ByteString&& other) noexcept {
165   m_pData.Swap(other.m_pData);
166 }
167 
ByteString(char ch)168 ByteString::ByteString(char ch) {
169   m_pData.Reset(StringData::Create(1));
170   m_pData->m_String[0] = ch;
171 }
172 
ByteString(const char * ptr)173 ByteString::ByteString(const char* ptr)
174     : ByteString(ptr, ptr ? strlen(ptr) : 0) {}
175 
ByteString(const ByteStringView & stringSrc)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 
ByteString(const ByteStringView & str1,const ByteStringView & str2)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 
ByteString(const std::initializer_list<ByteStringView> & list)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 
ByteString(const std::ostringstream & outStream)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 
~ByteString()221 ByteString::~ByteString() {}
222 
operator =(const char * pStr)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 
operator =(const ByteStringView & stringSrc)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 
operator =(const ByteString & stringSrc)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 
operator +=(const char * pStr)248 const ByteString& ByteString::operator+=(const char* pStr) {
249   if (pStr)
250     Concat(pStr, strlen(pStr));
251 
252   return *this;
253 }
254 
operator +=(char ch)255 const ByteString& ByteString::operator+=(char ch) {
256   Concat(&ch, 1);
257   return *this;
258 }
259 
operator +=(const ByteString & str)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 
operator +=(const ByteStringView & str)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 
operator ==(const char * ptr) const274 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 
operator ==(const ByteStringView & str) const285 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 
operator ==(const ByteString & other) const294 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 
operator <(const char * ptr) const309 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 
operator <(const ByteStringView & str) const321 bool ByteString::operator<(const ByteStringView& str) const {
322   return Compare(str) < 0;
323 }
324 
operator <(const ByteString & other) const325 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 
EqualNoCase(const ByteStringView & str) const335 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 
AssignCopy(const char * pSrcData,size_t nSrcLen)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 
ReallocBeforeWrite(size_t nNewLength)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 
AllocBeforeWrite(size_t nNewLength)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 
ReleaseBuffer(size_t nNewLength)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 
Reserve(size_t len)418 void ByteString::Reserve(size_t len) {
419   GetBuffer(len);
420 }
421 
GetBuffer(size_t nMinBufLength)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 
Delete(size_t index,size_t count)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 
Concat(const char * pSrcData,size_t nSrcLen)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 
Mid(size_t first,size_t count) const490 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 
Left(size_t count) const511 ByteString ByteString::Left(size_t count) const {
512   if (count == 0 || !IsValidLength(count))
513     return ByteString();
514   return Mid(0, count);
515 }
516 
Right(size_t count) const517 ByteString ByteString::Right(size_t count) const {
518   if (count == 0 || !IsValidLength(count))
519     return ByteString();
520   return Mid(GetLength() - count, count);
521 }
522 
AllocCopy(ByteString & dest,size_t nCopyLen,size_t nCopyIndex) const523 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 
SetAt(size_t index,char c)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 
Insert(size_t location,char ch)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 
Find(char ch,size_t start) const554 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 
Find(const ByteStringView & subStr,size_t start) const567 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 
ReverseFind(char ch) const582 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 
MakeLower()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 
MakeUpper()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 
Remove(char chRemove)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 
Replace(const ByteStringView & pOld,const ByteStringView & pNew)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 
UTF8Decode() const691 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
FromUnicode(const WideString & str)700 ByteString ByteString::FromUnicode(const WideString& str) {
701   return GetByteString(0, str.AsStringView());
702 }
703 
Compare(const ByteStringView & str) const704 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 
Trim()719 void ByteString::Trim() {
720   TrimRight(kTrimChars);
721   TrimLeft(kTrimChars);
722 }
723 
Trim(char target)724 void ByteString::Trim(char target) {
725   ByteStringView targets(target);
726   TrimRight(targets);
727   TrimLeft(targets);
728 }
729 
Trim(const ByteStringView & targets)730 void ByteString::Trim(const ByteStringView& targets) {
731   TrimRight(targets);
732   TrimLeft(targets);
733 }
734 
TrimLeft()735 void ByteString::TrimLeft() {
736   TrimLeft(kTrimChars);
737 }
738 
TrimLeft(char target)739 void ByteString::TrimLeft(char target) {
740   TrimLeft(ByteStringView(target));
741 }
742 
TrimLeft(const ByteStringView & targets)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 
TrimRight()769 void ByteString::TrimRight() {
770   TrimRight(kTrimChars);
771 }
772 
TrimRight(char target)773 void ByteString::TrimRight(char target) {
774   TrimRight(ByteStringView(target));
775 }
776 
TrimRight(const ByteStringView & targets)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 
operator <<(std::ostream & os,const ByteString & str)800 std::ostream& operator<<(std::ostream& os, const ByteString& str) {
801   return os.write(str.c_str(), str.GetLength());
802 }
803 
operator <<(std::ostream & os,const ByteStringView & str)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