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